Fixed send tx sign using block hash instead of block number.

This commit is contained in:
parmmarrushabh 2018-10-23 11:50:56 +05:30
parent 2677b33b78
commit 356a13e109
6 changed files with 91 additions and 74 deletions

View file

@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/contracts"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
)
@ -39,7 +40,16 @@ func TestBlockSigner(t *testing.T) {
}
contractBackend.ForEachStorageAt(ctx, blockSignerAddress, nil, f)
byte0 := [32]byte{}
byte0 := contracts.RandomHash()
// Test sign.
tx, err := blockSigner.Sign(big.NewInt(50), byte0)
if err != nil {
t.Fatalf("can't sign: %v", err)
}
contractBackend.Commit()
t.Log("tx", tx)
signers, err := blockSigner.GetSigners(byte0)
if err != nil {
t.Fatalf("can't get candidates: %v", err)
@ -47,11 +57,4 @@ func TestBlockSigner(t *testing.T) {
for _, it := range signers {
t.Log("signer", it.String())
}
s, err := blockSigner.Sign(big.NewInt(1), byte0)
if err != nil {
t.Fatalf("can't sign: %v", err)
}
t.Log("tx data", s)
contractBackend.Commit()
}

View file

@ -17,8 +17,8 @@ contract BlockSigner {
function sign(uint256 _blockNumber, bytes32 _blockHash) external {
// consensus should validate all senders are validators, gas = 0
require(block.number >= _blockNumber);
require(block.number <= _blockNumber.add(epochNumber * 2));
//require(block.number >= _blockNumber);
//require(block.number <= _blockNumber.add(epochNumber * 2));
blocks[_blockNumber].push(_blockHash);
blockSigners[_blockHash].push(msg.sender);

View file

@ -19,7 +19,7 @@ import (
const BlockSignerABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"_blockNumber\",\"type\":\"uint256\"},{\"name\":\"_blockHash\",\"type\":\"bytes32\"}],\"name\":\"sign\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_blockHash\",\"type\":\"bytes32\"}],\"name\":\"getSigners\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"epochNumber\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_epochNumber\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_signer\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_blockNumber\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_blockHash\",\"type\":\"bytes32\"}],\"name\":\"Sign\",\"type\":\"event\"}]"
// BlockSignerBin is the compiled bytecode used for deploying new contracts.
const BlockSignerBin = `0x6060604052341561000f57600080fd5b604051602080610386833981016040528080516002555050610350806100366000396000f3006060604052600436106100565763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663e341eaa4811461005b578063e7ec6aef14610076578063f4145a83146100df575b600080fd5b341561006657600080fd5b610074600435602435610104565b005b341561008157600080fd5b61008c600435610227565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156100cb5780820151838201526020016100b3565b505050509050019250505060405180910390f35b34156100ea57600080fd5b6100f26102ac565b60405190815260200160405180910390f35b438290101561011257600080fd5b600280546101289184910263ffffffff6102b216565b43111561013457600080fd5b600082815260016020819052604090912080549091810161015583826102c8565b5060009182526020808320919091018390558282528190526040902080546001810161018183826102c8565b506000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff8116919091179091557f62855fa22e051687c32ac285857751f6d3f2c100c72756d8d30cb7ecb1f64f5490838360405173ffffffffffffffffffffffffffffffffffffffff909316835260208301919091526040808301919091526060909101905180910390a15050565b61022f6102f1565b600082815260208181526040918290208054909290918281020190519081016040528092919081815260200182805480156102a057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610275575b50505050509050919050565b60025481565b6000828201838110156102c157fe5b9392505050565b8154818355818115116102ec576000838152602090206102ec918101908301610303565b505050565b60206040519081016040526000815290565b61032191905b8082111561031d5760008155600101610309565b5090565b905600a165627a7a72305820a8ceddaea8e4ae00991e2ae81c8c88e160dd8770f255523282c24c2df4c30ec70029`
const BlockSignerBin = `0x6060604052341561000f57600080fd5b60405160208061034083398101604052808051600255505061030a806100366000396000f3006060604052600436106100565763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663e341eaa4811461005b578063e7ec6aef14610076578063f4145a83146100df575b600080fd5b341561006657600080fd5b610074600435602435610104565b005b341561008157600080fd5b61008c6004356101f7565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156100cb5780820151838201526020016100b3565b505050509050019250505060405180910390f35b34156100ea57600080fd5b6100f261027c565b60405190815260200160405180910390f35b60008281526001602081905260409091208054909181016101258382610282565b506000918252602080832091909101839055828252819052604090208054600181016101518382610282565b506000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff8116919091179091557f62855fa22e051687c32ac285857751f6d3f2c100c72756d8d30cb7ecb1f64f5490838360405173ffffffffffffffffffffffffffffffffffffffff909316835260208301919091526040808301919091526060909101905180910390a15050565b6101ff6102ab565b6000828152602081815260409182902080549092909182810201905190810160405280929190818152602001828054801561027057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610245575b50505050509050919050565b60025481565b8154818355818115116102a6576000838152602090206102a69181019083016102bd565b505050565b60206040519081016040526000815290565b6102db91905b808211156102d757600081556001016102c3565b5090565b905600a165627a7a72305820fd1c307716c14d8f8b179bb09b89555ec490e6b216e2c1018c7232361b947bc40029`
// DeployBlockSigner deploys a new Ethereum contract, binding an instance of BlockSigner to it.
func DeployBlockSigner(auth *bind.TransactOpts, backend bind.ContractBackend, _epochNumber *big.Int) (common.Address, *types.Transaction, *BlockSigner, error) {

View file

@ -5,6 +5,7 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/contracts/blocksigner/contract"
contractValidator "github.com/ethereum/go-ethereum/contracts/validator/contract"
"github.com/ethereum/go-ethereum/core"
@ -13,12 +14,12 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"math/big"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/ethclient"
"math/rand"
"time"
)
const (
HexSignMethod = "2fb1b25f"
HexSignMethod = "e341eaa4"
RewardMasterPercent = 30
RewardVoterPercent = 60
RewardFoundationPercent = 10
@ -45,7 +46,7 @@ func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, m
// Create and send tx to smart contract for sign validate block.
nonce := pool.State().GetNonce(account.Address)
tx := CreateTxSign(block.Number(), nonce, common.HexToAddress(common.BlockSigners))
tx := CreateTxSign(block.Number(), block.Hash(), nonce, common.HexToAddress(common.BlockSigners))
txSigned, err := wallet.SignTx(account, tx, chainConfig.ChainId)
if err != nil {
log.Error("Fail to create tx sign", "error", err)
@ -60,24 +61,24 @@ func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, m
}
// Create tx sign.
func CreateTxSign(blockNumber *big.Int, nonce uint64, blockSigner common.Address) *types.Transaction {
blockHex := common.LeftPadBytes(blockNumber.Bytes(), 32)
func CreateTxSign(blockNumber *big.Int, blockHash common.Hash, nonce uint64, blockSigner common.Address) *types.Transaction {
data := common.Hex2Bytes(HexSignMethod)
inputData := append(data, blockHex...)
tx := types.NewTransaction(nonce, blockSigner, big.NewInt(0), 100000, big.NewInt(0), inputData)
inputData := append(data, common.LeftPadBytes(blockNumber.Bytes(), 32)...)
inputData = append(inputData, common.LeftPadBytes(blockHash.Bytes(), 32)...)
tx := types.NewTransaction(nonce, blockSigner, big.NewInt(0), 200000, big.NewInt(0), inputData)
return tx
}
// Get signers signed for blockNumber from blockSigner contract.
func GetSignersFromContract(addrBlockSigner common.Address, client bind.ContractBackend, blockNumber uint64) ([]common.Address, error) {
func GetSignersFromContract(addrBlockSigner common.Address, client bind.ContractBackend, blockHash common.Hash) ([]common.Address, error) {
blockSigner, err := contract.NewBlockSigner(addrBlockSigner, client)
if err != nil {
log.Error("Fail get instance of blockSigner", "error", err)
return nil, err
}
opts := new(bind.CallOpts)
addrs, err := blockSigner.GetSigners(opts, new(big.Int).SetUint64(blockNumber))
addrs, err := blockSigner.GetSigners(opts, blockHash)
if err != nil {
log.Error("Fail get block signers", "error", err)
return nil, err
@ -87,14 +88,15 @@ func GetSignersFromContract(addrBlockSigner common.Address, client bind.Contract
}
// Calculate reward for reward checkpoint.
func GetRewardForCheckpoint(blockSignerAddr common.Address, number uint64, rCheckpoint uint64, client bind.ContractBackend, totalSigner *uint64) (map[common.Address]*rewardLog, error) {
func GetRewardForCheckpoint(chain consensus.ChainReader, blockSignerAddr common.Address, number uint64, rCheckpoint uint64, client bind.ContractBackend, totalSigner *uint64) (map[common.Address]*rewardLog, error) {
// Not reward for singer of genesis block and only calculate reward at checkpoint block.
startBlockNumber := number - (rCheckpoint * 2) + 1
endBlockNumber := startBlockNumber + rCheckpoint - 1
signers := make(map[common.Address]*rewardLog)
for i := startBlockNumber; i <= endBlockNumber; i++ {
addrs, err := GetSignersFromContract(blockSignerAddr, client, i)
block := chain.GetHeaderByNumber(i)
addrs, err := GetSignersFromContract(blockSignerAddr, client, block.Hash())
if err != nil {
log.Error("Fail to get signers from smartcontract.", "error", err, "blockNumber", i)
return nil, err
@ -222,4 +224,15 @@ func GetRewardBalancesRate(masterAddr common.Address, totalReward *big.Int, vali
log.Info("Holders reward", "holders", string(jsonHolders), "master node", masterAddr.String())
return balances, nil
}
// Generate random string.
func RandomHash() common.Hash {
letterBytes := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"
var b common.Hash
for i := range b {
rand.Seed(time.Now().UnixNano())
b[i] = letterBytes[rand.Intn(len(letterBytes))]
}
return b
}

View file

@ -10,7 +10,6 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"math/big"
"math/rand"
"testing"
@ -42,41 +41,46 @@ func TestSendTxSign(t *testing.T) {
backend.Commit()
nonces := make(map[*ecdsa.PrivateKey]int)
oldBlock := make([]common.Address, 100)
oldBlocks := make(map[common.Hash]common.Address)
signTx := func(ctx context.Context, backend *backends.SimulatedBackend, signer types.HomesteadSigner, nonces map[*ecdsa.PrivateKey]int, accKey *ecdsa.PrivateKey, i uint64) {
tx, _ := types.SignTx(CreateTxSign(new(big.Int).SetUint64(i), uint64(nonces[accKey]), blockSignerAddr), signer, accKey)
signTx := func(ctx context.Context, backend *backends.SimulatedBackend, signer types.HomesteadSigner, nonces map[*ecdsa.PrivateKey]int, accKey *ecdsa.PrivateKey, blockNumber *big.Int, blockHash common.Hash) *types.Transaction {
tx, _ := types.SignTx(CreateTxSign(blockNumber, blockHash, uint64(nonces[accKey]), blockSignerAddr), signer, accKey)
backend.SendTransaction(ctx, tx)
backend.Commit()
nonces[accKey]++
return tx
}
// Tx sign for signer.
signCount := uint64(0)
for i := uint64(0); i < 100; i++ {
signCount := int64(0)
blockHashes := make([]common.Hash, 10)
for i := int64(0); i < 10; i++ {
blockHash := RandomHash()
blockHashes[i] = blockHash
randIndex := rand.Intn(len(keys))
accKey := keys[randIndex]
signTx(ctx, backend, signer, nonces, accKey, i)
oldBlock[i] = accounts[randIndex]
signTx(ctx, backend, signer, nonces, accKey, new(big.Int).SetInt64(i), blockHash)
oldBlocks[blockHash] = accounts[randIndex]
signCount++
// Tx sign for validators.
for _, key := range keys {
if key != accKey {
signTx(ctx, backend, signer, nonces, key, i)
signTx(ctx, backend, signer, nonces, key, new(big.Int).SetInt64(i), blockHash)
signCount++
}
}
}
for i := uint64(0); i < 100; i++ {
signers, err := blockSigner.GetSigners(new(big.Int).SetUint64(i))
for _, blockHash := range blockHashes {
signers, err := blockSigner.GetSigners(blockHash)
if err != nil {
t.Fatalf("Can't get signers: %v", err)
}
if signers[0].String() != oldBlock[i].String() {
t.Errorf("Tx sign for block signer not match %v - %v", signers[0].String(), oldBlock[i].String())
if signers[0].String() != oldBlocks[blockHash].String() {
t.Errorf("Tx sign for block signer not match %v - %v", signers[0].String(), oldBlocks[blockHash].String())
}
if len(signers) != len(keys) {
@ -85,33 +89,33 @@ func TestSendTxSign(t *testing.T) {
}
// Unit test for reward checkpoint.
rCheckpoint := uint64(5)
chainReward := new(big.Int).SetUint64(15 * params.Ether)
total := new(uint64)
for i := uint64(0); i < 100; i++ {
if i > 0 && i%rCheckpoint == 0 && i-rCheckpoint > 0 {
_, err := GetRewardForCheckpoint(blockSignerAddr, i, rCheckpoint, backend, total)
if err != nil {
t.Errorf("Fail to get signers for reward checkpoint: %v", err)
}
}
}
signers := make(map[common.Address]*rewardLog)
totalSigner := uint64(17)
signers[common.HexToAddress("0x12f588d7d03bb269b382b842fc15d874e8c055a7")] = &rewardLog{5, new(big.Int).SetUint64(0)}
signers[common.HexToAddress("0x1f9e122c0921a4504fc116d967baf7a7bf2604ef")] = &rewardLog{6, new(big.Int).SetUint64(0)}
signers[common.HexToAddress("0xea489e4e673c25ff0614617ebe88efd853efe00c")] = &rewardLog{6, new(big.Int).SetUint64(0)}
rewardSigners, err := CalculateRewardForSigner(chainReward, signers, totalSigner)
if err != nil {
t.Errorf("Fail to calculate reward for signers: %v", err)
}
//t.Error("Reward", rewardSigners)
rewards := new(big.Int)
for _, reward := range rewardSigners {
rewards.Add(rewards, reward)
}
if rewards.Cmp(new(big.Int).SetUint64(14999999999999999996)) != 0 {
t.Errorf("Total reward not same reward checkpoint: %v - %v", chainReward, rewards)
}
//rCheckpoint := uint64(5)
//chainReward := new(big.Int).SetUint64(15 * params.Ether)
//total := new(uint64)
//for i := uint64(0); i < 100; i++ {
// if i > 0 && i%rCheckpoint == 0 && i-rCheckpoint > 0 {
// _, err := GetRewardForCheckpoint(blockSignerAddr, i, rCheckpoint, backend, total)
// if err != nil {
// t.Errorf("Fail to get signers for reward checkpoint: %v", err)
// }
// }
//}
//
//signers := make(map[common.Address]*rewardLog)
//totalSigner := uint64(17)
//signers[common.HexToAddress("0x12f588d7d03bb269b382b842fc15d874e8c055a7")] = &rewardLog{5, new(big.Int).SetUint64(0)}
//signers[common.HexToAddress("0x1f9e122c0921a4504fc116d967baf7a7bf2604ef")] = &rewardLog{6, new(big.Int).SetUint64(0)}
//signers[common.HexToAddress("0xea489e4e673c25ff0614617ebe88efd853efe00c")] = &rewardLog{6, new(big.Int).SetUint64(0)}
//rewardSigners, err := CalculateRewardForSigner(chainReward, signers, totalSigner)
//if err != nil {
// t.Errorf("Fail to calculate reward for signers: %v", err)
//}
////t.Error("Reward", rewardSigners)
//rewards := new(big.Int)
//for _, reward := range rewardSigners {
// rewards.Add(rewards, reward)
//}
//if rewards.Cmp(new(big.Int).SetUint64(14999999999999999996)) != 0 {
// t.Errorf("Total reward not same reward checkpoint: %v - %v", chainReward, rewards)
//}
}

View file

@ -189,6 +189,9 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
if eth.chainConfig.Clique != nil {
c := eth.engine.(*clique.Clique)
// Set global ipc endpoint.
eth.IPCEndpoint = ctx.GetConfig().IPCEndpoint()
// Inject hook for send tx sign to smartcontract after insert block into chain.
importedHook := func(block *types.Block) {
snap, err := c.GetSnapshot(eth.blockchain, block.Header())
@ -210,8 +213,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
client, err := eth.GetClient()
if err != nil {
log.Error("Fail to connect IPC client for blockSigner", "error", err)
return err
}
number := header.Number.Uint64()
rCheckpoint := chain.Config().Clique.RewardCheckpoint
@ -220,7 +221,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
addr := common.HexToAddress(common.BlockSigners)
chainReward := new(big.Int).SetUint64(chain.Config().Clique.Reward * params.Ether)
totalSigner := new(uint64)
signers, err := contracts.GetRewardForCheckpoint(addr, number, rCheckpoint, client, totalSigner)
signers, err := contracts.GetRewardForCheckpoint(chain, addr, number, rCheckpoint, client, totalSigner)
if err != nil {
log.Error("Fail to get signers for reward checkpoint", "error", err)
}
@ -228,7 +229,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
if err != nil {
log.Error("Fail to calculate reward for signers", "error", err)
}
//// Get validator.
// Get validator.
validator, err := contract.NewXDCValidator(common.HexToAddress(common.MasternodeVotingSMC), client)
if err != nil {
log.Error("Fail get instance of XDC Validator", "error", err)
@ -435,11 +436,7 @@ func (s *Ethereum) UpdateMasternodes(ms []clique.Masternode) error {
return errors.New("not clique")
}
c := s.engine.(*clique.Clique)
err := c.UpdateMasternodes(s.blockchain, s.blockchain.CurrentHeader(), ms)
if err != nil {
return err
}
return nil
return c.UpdateMasternodes(s.blockchain, s.blockchain.CurrentHeader(), ms)
}
func (s *Ethereum) StartStaking(local bool) error {