diff --git a/contracts/blocksigner/blocksigner_test.go b/contracts/blocksigner/blocksigner_test.go index 0e8e675f29..4f2bf14b9a 100644 --- a/contracts/blocksigner/blocksigner_test.go +++ b/contracts/blocksigner/blocksigner_test.go @@ -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() } \ No newline at end of file diff --git a/contracts/blocksigner/contract/BlockSigner.sol b/contracts/blocksigner/contract/BlockSigner.sol index 98575256f4..d7a5b6ddb8 100644 --- a/contracts/blocksigner/contract/BlockSigner.sol +++ b/contracts/blocksigner/contract/BlockSigner.sol @@ -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); diff --git a/contracts/blocksigner/contract/blocksigner.go b/contracts/blocksigner/contract/blocksigner.go index 7eb5947e6a..044e0812d5 100644 --- a/contracts/blocksigner/contract/blocksigner.go +++ b/contracts/blocksigner/contract/blocksigner.go @@ -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) { diff --git a/contracts/utils.go b/contracts/utils.go index d26c761546..dfc50b1cd2 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -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 } \ No newline at end of file diff --git a/contracts/utils_test.go b/contracts/utils_test.go index a3297e98de..712d4a75c1 100644 --- a/contracts/utils_test.go +++ b/contracts/utils_test.go @@ -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) + //} } \ No newline at end of file diff --git a/eth/backend.go b/eth/backend.go index 2357ed9e9e..d62af0cb02 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -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 {