From 2a14f5a30e54e8328358a68c2d071da29c01bd6d Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 11:06:50 -0800 Subject: [PATCH 01/15] Use solc generated abi and binary --- api/service/staking/service.go | 33 +- contracts/README.md | 9 + contracts/StakeLockContract.go | 616 +++++++++++++++++++++++++++++++ contracts/StakeLockContract.json | 143 ------- contracts/contract_caller.go | 60 +++ go.mod | 2 + go.sum | 7 + node/contract.go | 7 +- node/node.go | 7 + node/node_handler.go | 11 +- node/staking.go | 64 ++++ 11 files changed, 788 insertions(+), 171 deletions(-) create mode 100644 contracts/StakeLockContract.go delete mode 100644 contracts/StakeLockContract.json create mode 100644 contracts/contract_caller.go diff --git a/api/service/staking/service.go b/api/service/staking/service.go index e856662a4..761fad675 100644 --- a/api/service/staking/service.go +++ b/api/service/staking/service.go @@ -3,10 +3,11 @@ package staking import ( "crypto/ecdsa" "math/big" - "os" + "strings" "time" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/harmony-one/harmony/contracts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -101,13 +102,6 @@ func (s *Service) IsStaked() bool { // DoService does staking. func (s *Service) DoService() { utils.GetLogInstance().Info("Trying to send a staking transaction.") - abi, err := s.getStakeLockContractABI() - if err != nil { - utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) - } else { - utils.GetLogInstance().Info("Generated staking contract's ABI", "abi", abi) - } - // TODO: use abi to generate staking transaction. if s.beaconChain == nil { utils.GetLogInstance().Info("Can not send a staking transaction because of nil beacon chain.") @@ -121,17 +115,6 @@ func (s *Service) DoService() { } } -func (s *Service) getStakeLockContractABI() (abi.ABI, error) { - f, err := os.Open("./contracts/StakeLockContract.json") - if err != nil { - if os.IsNotExist(err) { - return abi.ABI{}, err - } - } - defer f.Close() - return abi.JSON(f) -} - func (s *Service) getStakingInfo() *proto.StakingContractInfoResponse { address := crypto.PubkeyToAddress(s.accountKey.PublicKey) state, err := s.beaconChain.State() @@ -196,6 +179,16 @@ func (s *Service) createRawStakingMessage() []byte { // TODO(minhdoan): Enable getStakingInfo back after testing. stakingInfo := s.getFakeStakingInfo() toAddress := common.HexToAddress(stakingInfo.ContractAddress) + + abi, err := abi.JSON(strings.NewReader(contracts.StakeLockContractABI)) + if err != nil { + utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) + } + bytesData, err := abi.Pack("lock") + if err != nil { + utils.GetLogInstance().Error("Failed to generate ABI function bytes data", "error", err) + } + tx := types.NewTransaction( stakingInfo.Nonce, toAddress, @@ -203,7 +196,7 @@ func (s *Service) createRawStakingMessage() []byte { big.NewInt(s.stakingAmount), params.TxGas*10, nil, - common.FromHex("0xd0e30db0"), + bytesData, ) if signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, s.accountKey); err == nil { diff --git a/contracts/README.md b/contracts/README.md index b10c241cc..3f5d07301 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -2,3 +2,12 @@ The smart contract files in this folder contains protocol-level smart contracts * Faucet.sol is the smart contract to dispense free test tokens in our testnet. * StakeLockContract.sol is the staking smart contract that receives and locks stakes. The stakes are used for the POS and sharding protocol. + +Solc is needed to recompile the contracts into ABI and bytecode. Please follow https://solidity.readthedocs.io/en/v0.5.3/installing-solidity.html for the installation. + +Example command to compile a contract file into golang ABI. +```bash + +abigen -sol contracts/StakeLockContract.sol -pkg contracts -out contracts/StakeLockContract.go + +``` \ No newline at end of file diff --git a/contracts/StakeLockContract.go b/contracts/StakeLockContract.go new file mode 100644 index 000000000..6b224c17d --- /dev/null +++ b/contracts/StakeLockContract.go @@ -0,0 +1,616 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package contracts + +import ( + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = abi.U256 + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// StakeLockContractABI is the input ABI used to generate the binding from. +const StakeLockContractABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"listLockedAddresses\",\"outputs\":[{\"name\":\"lockedAddresses\",\"type\":\"address[]\"},{\"name\":\"blockNums\",\"type\":\"uint256[]\"},{\"name\":\"lockPeriodCounts\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_of\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"currentEpoch\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unlock\",\"outputs\":[{\"name\":\"unlockableTokens\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_of\",\"type\":\"address\"}],\"name\":\"getUnlockableTokens\",\"outputs\":[{\"name\":\"unlockableTokens\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"lock\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_of\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"Unlocked\",\"type\":\"event\"}]" + +// StakeLockContractBin is the compiled bytecode used for deploying new contracts. +const StakeLockContractBin = `0x6080604052600560005534801561001557600080fd5b50610895806100256000396000f3fe6080604052600436106100555760003560e01c806363b125151461005a57806370a082311461014d5780637667180814610192578063a69df4b5146101a7578063ab4a2eb3146101bc578063f83d08ba146101ef575b600080fd5b34801561006657600080fd5b5061006f61020b565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b838110156100b757818101518382015260200161009f565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156100f65781810151838201526020016100de565b50505050905001848103825285818151815260200191508051906020019060200280838360005b8381101561013557818101518382015260200161011d565b50505050905001965050505050505060405180910390f35b34801561015957600080fd5b506101806004803603602081101561017057600080fd5b50356001600160a01b031661039a565b60408051918252519081900360200190f35b34801561019e57600080fd5b506101806103b5565b3480156101b357600080fd5b506101806103ca565b3480156101c857600080fd5b50610180600480360360208110156101df57600080fd5b50356001600160a01b03166105b7565b6101f7610614565b604080519115158252519081900360200190f35b6060806060600380548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610248575b5050505050925060038054905060405190808252806020026020018201604052801561029c578160200160208202803883390190505b5060035460408051828152602080840282010190915291935080156102cb578160200160208202803883390190505b50905060005b8351811015610394576001600085838151811015156102ec57fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060010154838281518110151561032857fe5b60209081029091010152835160019060009086908490811061034657fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060030154828281518110151561038257fe5b602090810290910101526001016102d1565b50909192565b6001600160a01b031660009081526001602052604090205490565b60008054438115156103c357fe5b0490505b90565b60006103d5336105b7565b60408051808201909152601481527f4e6f20746f6b656e7320756e6c6f636b61626c65000000000000000000000000602082015290915081151561049a57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561045f578181015183820152602001610447565b50505050905090810190601f16801561048c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50336000908152600160208190526040822060048101805484835592820184905560028201849055600391820184905592909255815490919060001981019081106104e157fe5b600091825260209091200154600380546001600160a01b03909216918390811061050757fe5b6000918252602082200180546001600160a01b0319166001600160a01b0393909316929092179091556003805483926001929091600019810190811061054957fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020600401556003805490610584906000198301610822565b50604051339083156108fc029084906000818181858888f193505050501580156105b2573d6000803e3d6000fd5b505090565b6000806105c26103b5565b6001600160a01b0384166000908152600160205260409020600381810154600290920154929350020181111561060e576001600160a01b03831660009081526001602052604090205491505b50919050565b600061061f3361039a565b60408051808201909152601581527f546f6b656e7320616c7265616479206c6f636b65640000000000000000000000602082015290156106a457604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561045f578181015183820152602001610447565b5060408051808201909152601381527f416d6f756e742063616e206e6f74206265203000000000000000000000000000602082015234151561072b57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561045f578181015183820152602001610447565b506040518060a0016040528034815260200143815260200161074b6103b5565b8152600160208083018290526003805480840182557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810180546001600160a01b0319163390811790915560409586019190915260008181528484528590208651815592860151938301939093559284015160028201556060840151928101929092556080909201516004909101557fd4665e3049283582ba6f9eba07a5b3e12dab49e02da99e8927a47af5d134bea5346108046103b5565b6040805192835260208301919091528051918290030190a250600190565b8154818355818111156108465760008381526020902061084691810190830161084b565b505050565b6103c791905b808211156108655760008155600101610851565b509056fea165627a7a723058205d3d7c5ebbad421d6be22fbc24109d7b34d54381a9bf465e00863358c4c9be880029` + +// DeployStakeLockContract deploys a new Ethereum contract, binding an instance of StakeLockContract to it. +func DeployStakeLockContract(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *StakeLockContract, error) { + parsed, err := abi.JSON(strings.NewReader(StakeLockContractABI)) + if err != nil { + return common.Address{}, nil, nil, err + } + address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(StakeLockContractBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &StakeLockContract{StakeLockContractCaller: StakeLockContractCaller{contract: contract}, StakeLockContractTransactor: StakeLockContractTransactor{contract: contract}, StakeLockContractFilterer: StakeLockContractFilterer{contract: contract}}, nil +} + +// StakeLockContract is an auto generated Go binding around an Ethereum contract. +type StakeLockContract struct { + StakeLockContractCaller // Read-only binding to the contract + StakeLockContractTransactor // Write-only binding to the contract + StakeLockContractFilterer // Log filterer for contract events +} + +// StakeLockContractCaller is an auto generated read-only Go binding around an Ethereum contract. +type StakeLockContractCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StakeLockContractTransactor is an auto generated write-only Go binding around an Ethereum contract. +type StakeLockContractTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StakeLockContractFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type StakeLockContractFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StakeLockContractSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type StakeLockContractSession struct { + Contract *StakeLockContract // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// StakeLockContractCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type StakeLockContractCallerSession struct { + Contract *StakeLockContractCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// StakeLockContractTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type StakeLockContractTransactorSession struct { + Contract *StakeLockContractTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// StakeLockContractRaw is an auto generated low-level Go binding around an Ethereum contract. +type StakeLockContractRaw struct { + Contract *StakeLockContract // Generic contract binding to access the raw methods on +} + +// StakeLockContractCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type StakeLockContractCallerRaw struct { + Contract *StakeLockContractCaller // Generic read-only contract binding to access the raw methods on +} + +// StakeLockContractTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type StakeLockContractTransactorRaw struct { + Contract *StakeLockContractTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewStakeLockContract creates a new instance of StakeLockContract, bound to a specific deployed contract. +func NewStakeLockContract(address common.Address, backend bind.ContractBackend) (*StakeLockContract, error) { + contract, err := bindStakeLockContract(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &StakeLockContract{StakeLockContractCaller: StakeLockContractCaller{contract: contract}, StakeLockContractTransactor: StakeLockContractTransactor{contract: contract}, StakeLockContractFilterer: StakeLockContractFilterer{contract: contract}}, nil +} + +// NewStakeLockContractCaller creates a new read-only instance of StakeLockContract, bound to a specific deployed contract. +func NewStakeLockContractCaller(address common.Address, caller bind.ContractCaller) (*StakeLockContractCaller, error) { + contract, err := bindStakeLockContract(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &StakeLockContractCaller{contract: contract}, nil +} + +// NewStakeLockContractTransactor creates a new write-only instance of StakeLockContract, bound to a specific deployed contract. +func NewStakeLockContractTransactor(address common.Address, transactor bind.ContractTransactor) (*StakeLockContractTransactor, error) { + contract, err := bindStakeLockContract(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &StakeLockContractTransactor{contract: contract}, nil +} + +// NewStakeLockContractFilterer creates a new log filterer instance of StakeLockContract, bound to a specific deployed contract. +func NewStakeLockContractFilterer(address common.Address, filterer bind.ContractFilterer) (*StakeLockContractFilterer, error) { + contract, err := bindStakeLockContract(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &StakeLockContractFilterer{contract: contract}, nil +} + +// bindStakeLockContract binds a generic wrapper to an already deployed contract. +func bindStakeLockContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(StakeLockContractABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_StakeLockContract *StakeLockContractRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _StakeLockContract.Contract.StakeLockContractCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_StakeLockContract *StakeLockContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _StakeLockContract.Contract.StakeLockContractTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_StakeLockContract *StakeLockContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _StakeLockContract.Contract.StakeLockContractTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_StakeLockContract *StakeLockContractCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { + return _StakeLockContract.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_StakeLockContract *StakeLockContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _StakeLockContract.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_StakeLockContract *StakeLockContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _StakeLockContract.Contract.contract.Transact(opts, method, params...) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address _of) constant returns(uint256 balance) +func (_StakeLockContract *StakeLockContractCaller) BalanceOf(opts *bind.CallOpts, _of common.Address) (*big.Int, error) { + var ( + ret0 = new(*big.Int) + ) + out := ret0 + err := _StakeLockContract.contract.Call(opts, out, "balanceOf", _of) + return *ret0, err +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address _of) constant returns(uint256 balance) +func (_StakeLockContract *StakeLockContractSession) BalanceOf(_of common.Address) (*big.Int, error) { + return _StakeLockContract.Contract.BalanceOf(&_StakeLockContract.CallOpts, _of) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address _of) constant returns(uint256 balance) +func (_StakeLockContract *StakeLockContractCallerSession) BalanceOf(_of common.Address) (*big.Int, error) { + return _StakeLockContract.Contract.BalanceOf(&_StakeLockContract.CallOpts, _of) +} + +// CurrentEpoch is a free data retrieval call binding the contract method 0x76671808. +// +// Solidity: function currentEpoch() constant returns(uint256) +func (_StakeLockContract *StakeLockContractCaller) CurrentEpoch(opts *bind.CallOpts) (*big.Int, error) { + var ( + ret0 = new(*big.Int) + ) + out := ret0 + err := _StakeLockContract.contract.Call(opts, out, "currentEpoch") + return *ret0, err +} + +// CurrentEpoch is a free data retrieval call binding the contract method 0x76671808. +// +// Solidity: function currentEpoch() constant returns(uint256) +func (_StakeLockContract *StakeLockContractSession) CurrentEpoch() (*big.Int, error) { + return _StakeLockContract.Contract.CurrentEpoch(&_StakeLockContract.CallOpts) +} + +// CurrentEpoch is a free data retrieval call binding the contract method 0x76671808. +// +// Solidity: function currentEpoch() constant returns(uint256) +func (_StakeLockContract *StakeLockContractCallerSession) CurrentEpoch() (*big.Int, error) { + return _StakeLockContract.Contract.CurrentEpoch(&_StakeLockContract.CallOpts) +} + +// GetUnlockableTokens is a free data retrieval call binding the contract method 0xab4a2eb3. +// +// Solidity: function getUnlockableTokens(address _of) constant returns(uint256 unlockableTokens) +func (_StakeLockContract *StakeLockContractCaller) GetUnlockableTokens(opts *bind.CallOpts, _of common.Address) (*big.Int, error) { + var ( + ret0 = new(*big.Int) + ) + out := ret0 + err := _StakeLockContract.contract.Call(opts, out, "getUnlockableTokens", _of) + return *ret0, err +} + +// GetUnlockableTokens is a free data retrieval call binding the contract method 0xab4a2eb3. +// +// Solidity: function getUnlockableTokens(address _of) constant returns(uint256 unlockableTokens) +func (_StakeLockContract *StakeLockContractSession) GetUnlockableTokens(_of common.Address) (*big.Int, error) { + return _StakeLockContract.Contract.GetUnlockableTokens(&_StakeLockContract.CallOpts, _of) +} + +// GetUnlockableTokens is a free data retrieval call binding the contract method 0xab4a2eb3. +// +// Solidity: function getUnlockableTokens(address _of) constant returns(uint256 unlockableTokens) +func (_StakeLockContract *StakeLockContractCallerSession) GetUnlockableTokens(_of common.Address) (*big.Int, error) { + return _StakeLockContract.Contract.GetUnlockableTokens(&_StakeLockContract.CallOpts, _of) +} + +// ListLockedAddresses is a free data retrieval call binding the contract method 0x63b12515. +// +// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, uint256[] blockNums, uint256[] lockPeriodCounts) +func (_StakeLockContract *StakeLockContractCaller) ListLockedAddresses(opts *bind.CallOpts) (struct { + LockedAddresses []common.Address + BlockNums []*big.Int + LockPeriodCounts []*big.Int +}, error) { + ret := new(struct { + LockedAddresses []common.Address + BlockNums []*big.Int + LockPeriodCounts []*big.Int + }) + out := ret + err := _StakeLockContract.contract.Call(opts, out, "listLockedAddresses") + return *ret, err +} + +// ListLockedAddresses is a free data retrieval call binding the contract method 0x63b12515. +// +// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, uint256[] blockNums, uint256[] lockPeriodCounts) +func (_StakeLockContract *StakeLockContractSession) ListLockedAddresses() (struct { + LockedAddresses []common.Address + BlockNums []*big.Int + LockPeriodCounts []*big.Int +}, error) { + return _StakeLockContract.Contract.ListLockedAddresses(&_StakeLockContract.CallOpts) +} + +// ListLockedAddresses is a free data retrieval call binding the contract method 0x63b12515. +// +// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, uint256[] blockNums, uint256[] lockPeriodCounts) +func (_StakeLockContract *StakeLockContractCallerSession) ListLockedAddresses() (struct { + LockedAddresses []common.Address + BlockNums []*big.Int + LockPeriodCounts []*big.Int +}, error) { + return _StakeLockContract.Contract.ListLockedAddresses(&_StakeLockContract.CallOpts) +} + +// Lock is a paid mutator transaction binding the contract method 0xf83d08ba. +// +// Solidity: function lock() returns(bool) +func (_StakeLockContract *StakeLockContractTransactor) Lock(opts *bind.TransactOpts) (*types.Transaction, error) { + return _StakeLockContract.contract.Transact(opts, "lock") +} + +// Lock is a paid mutator transaction binding the contract method 0xf83d08ba. +// +// Solidity: function lock() returns(bool) +func (_StakeLockContract *StakeLockContractSession) Lock() (*types.Transaction, error) { + return _StakeLockContract.Contract.Lock(&_StakeLockContract.TransactOpts) +} + +// Lock is a paid mutator transaction binding the contract method 0xf83d08ba. +// +// Solidity: function lock() returns(bool) +func (_StakeLockContract *StakeLockContractTransactorSession) Lock() (*types.Transaction, error) { + return _StakeLockContract.Contract.Lock(&_StakeLockContract.TransactOpts) +} + +// Unlock is a paid mutator transaction binding the contract method 0xa69df4b5. +// +// Solidity: function unlock() returns(uint256 unlockableTokens) +func (_StakeLockContract *StakeLockContractTransactor) Unlock(opts *bind.TransactOpts) (*types.Transaction, error) { + return _StakeLockContract.contract.Transact(opts, "unlock") +} + +// Unlock is a paid mutator transaction binding the contract method 0xa69df4b5. +// +// Solidity: function unlock() returns(uint256 unlockableTokens) +func (_StakeLockContract *StakeLockContractSession) Unlock() (*types.Transaction, error) { + return _StakeLockContract.Contract.Unlock(&_StakeLockContract.TransactOpts) +} + +// Unlock is a paid mutator transaction binding the contract method 0xa69df4b5. +// +// Solidity: function unlock() returns(uint256 unlockableTokens) +func (_StakeLockContract *StakeLockContractTransactorSession) Unlock() (*types.Transaction, error) { + return _StakeLockContract.Contract.Unlock(&_StakeLockContract.TransactOpts) +} + +// StakeLockContractLockedIterator is returned from FilterLocked and is used to iterate over the raw logs and unpacked data for Locked events raised by the StakeLockContract contract. +type StakeLockContractLockedIterator struct { + Event *StakeLockContractLocked // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *StakeLockContractLockedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(StakeLockContractLocked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(StakeLockContractLocked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *StakeLockContractLockedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *StakeLockContractLockedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// StakeLockContractLocked represents a Locked event raised by the StakeLockContract contract. +type StakeLockContractLocked struct { + Of common.Address + Amount *big.Int + Epoch *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLocked is a free log retrieval operation binding the contract event 0xd4665e3049283582ba6f9eba07a5b3e12dab49e02da99e8927a47af5d134bea5. +// +// Solidity: event Locked(address indexed _of, uint256 _amount, uint256 _epoch) +func (_StakeLockContract *StakeLockContractFilterer) FilterLocked(opts *bind.FilterOpts, _of []common.Address) (*StakeLockContractLockedIterator, error) { + + var _ofRule []interface{} + for _, _ofItem := range _of { + _ofRule = append(_ofRule, _ofItem) + } + + logs, sub, err := _StakeLockContract.contract.FilterLogs(opts, "Locked", _ofRule) + if err != nil { + return nil, err + } + return &StakeLockContractLockedIterator{contract: _StakeLockContract.contract, event: "Locked", logs: logs, sub: sub}, nil +} + +// WatchLocked is a free log subscription operation binding the contract event 0xd4665e3049283582ba6f9eba07a5b3e12dab49e02da99e8927a47af5d134bea5. +// +// Solidity: event Locked(address indexed _of, uint256 _amount, uint256 _epoch) +func (_StakeLockContract *StakeLockContractFilterer) WatchLocked(opts *bind.WatchOpts, sink chan<- *StakeLockContractLocked, _of []common.Address) (event.Subscription, error) { + + var _ofRule []interface{} + for _, _ofItem := range _of { + _ofRule = append(_ofRule, _ofItem) + } + + logs, sub, err := _StakeLockContract.contract.WatchLogs(opts, "Locked", _ofRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(StakeLockContractLocked) + if err := _StakeLockContract.contract.UnpackLog(event, "Locked", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// StakeLockContractUnlockedIterator is returned from FilterUnlocked and is used to iterate over the raw logs and unpacked data for Unlocked events raised by the StakeLockContract contract. +type StakeLockContractUnlockedIterator struct { + Event *StakeLockContractUnlocked // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *StakeLockContractUnlockedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(StakeLockContractUnlocked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(StakeLockContractUnlocked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *StakeLockContractUnlockedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *StakeLockContractUnlockedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// StakeLockContractUnlocked represents a Unlocked event raised by the StakeLockContract contract. +type StakeLockContractUnlocked struct { + Account common.Address + Index *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUnlocked is a free log retrieval operation binding the contract event 0x0f0bc5b519ddefdd8e5f9e6423433aa2b869738de2ae34d58ebc796fc749fa0d. +// +// Solidity: event Unlocked(address indexed account, uint256 index) +func (_StakeLockContract *StakeLockContractFilterer) FilterUnlocked(opts *bind.FilterOpts, account []common.Address) (*StakeLockContractUnlockedIterator, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + + logs, sub, err := _StakeLockContract.contract.FilterLogs(opts, "Unlocked", accountRule) + if err != nil { + return nil, err + } + return &StakeLockContractUnlockedIterator{contract: _StakeLockContract.contract, event: "Unlocked", logs: logs, sub: sub}, nil +} + +// WatchUnlocked is a free log subscription operation binding the contract event 0x0f0bc5b519ddefdd8e5f9e6423433aa2b869738de2ae34d58ebc796fc749fa0d. +// +// Solidity: event Unlocked(address indexed account, uint256 index) +func (_StakeLockContract *StakeLockContractFilterer) WatchUnlocked(opts *bind.WatchOpts, sink chan<- *StakeLockContractUnlocked, account []common.Address) (event.Subscription, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + + logs, sub, err := _StakeLockContract.contract.WatchLogs(opts, "Unlocked", accountRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(StakeLockContractUnlocked) + if err := _StakeLockContract.contract.UnpackLog(event, "Unlocked", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} diff --git a/contracts/StakeLockContract.json b/contracts/StakeLockContract.json deleted file mode 100644 index f2ebd1d6f..000000000 --- a/contracts/StakeLockContract.json +++ /dev/null @@ -1,143 +0,0 @@ -[ - { - "constant": true, - "inputs": [], - "name": "listLockedAddresses", - "outputs": [ - { - "name": "lockedAddresses", - "type": "address[]" - }, - { - "name": "blockNums", - "type": "uint256[]" - }, - { - "name": "lockPeriodCounts", - "type": "uint256[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_of", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "balance", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "currentEpoch", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "unlock", - "outputs": [ - { - "name": "unlockableTokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_of", - "type": "address" - } - ], - "name": "getUnlockableTokens", - "outputs": [ - { - "name": "unlockableTokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "lock", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_of", - "type": "address" - }, - { - "indexed": false, - "name": "_amount", - "type": "uint256" - }, - { - "indexed": false, - "name": "_epoch", - "type": "uint256" - } - ], - "name": "Locked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "account", - "type": "address" - }, - { - "indexed": false, - "name": "index", - "type": "uint256" - } - ], - "name": "Unlocked", - "type": "event" - } -] diff --git a/contracts/contract_caller.go b/contracts/contract_caller.go new file mode 100644 index 000000000..5f27f922b --- /dev/null +++ b/contracts/contract_caller.go @@ -0,0 +1,60 @@ +package contracts + +import ( + "sync" + + "github.com/harmony-one/harmony/internal/utils" + + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/params" + "github.com/harmony-one/harmony/core" + "github.com/harmony-one/harmony/core/types" + "github.com/harmony-one/harmony/core/vm" +) + +// ContractCaller is used to call smart contract locally +type ContractCaller struct { + database *ethdb.Database + blockchain *core.BlockChain // Ethereum blockchain to handle the consensus + + mu sync.Mutex + config *params.ChainConfig +} + +// NewContractCaller initialize a new contract caller. +func NewContractCaller(db *ethdb.Database, bc *core.BlockChain, config *params.ChainConfig) *ContractCaller { + cc := ContractCaller{} + cc.database = db + cc.blockchain = bc + cc.mu = sync.Mutex{} + cc.config = config + return &cc +} + +// CallContract calls a contracts with the specified transaction. +func (cc *ContractCaller) CallContract(tx *types.Transaction) ([]byte, error) { + currBlock := cc.blockchain.CurrentBlock() + msg, err := tx.AsMessage(types.MakeSigner(cc.config, currBlock.Header().Number)) + if err != nil { + utils.GetLogInstance().Error("[ABI] Failed to convert transaction to message", "error", err) + return []byte{}, err + } + evmContext := core.NewEVMContext(msg, currBlock.Header(), cc.blockchain, nil) + // Create a new environment which holds all relevant information + // about the transaction and calling mechanisms. + stateDB, err := cc.blockchain.State() + if err != nil { + utils.GetLogInstance().Error("[ABI] Failed to retrieve state db", "error", err) + return []byte{}, err + } + vmenv := vm.NewEVM(evmContext, stateDB, cc.config, vm.Config{}) + gaspool := new(core.GasPool).AddGas(math.MaxUint64) + + returnValue, _, failed, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb() + if err != nil || failed { + utils.GetLogInstance().Error("[ABI] Failed executing the transaction", "error", err) + return []byte{}, err + } + return returnValue, nil +} diff --git a/go.mod b/go.mod index ba2757301..314417eb7 100644 --- a/go.mod +++ b/go.mod @@ -81,6 +81,8 @@ require ( github.com/multiformats/go-multibase v0.3.0 // indirect github.com/multiformats/go-multihash v1.0.10 // indirect github.com/multiformats/go-multistream v0.3.9 // indirect + github.com/pborman/uuid v1.2.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect github.com/rs/cors v1.6.0 // indirect github.com/shirou/gopsutil v2.18.12+incompatible github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect diff --git a/go.sum b/go.sum index e8a6ac062..b23899ded 100644 --- a/go.sum +++ b/go.sum @@ -21,6 +21,7 @@ github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazu github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/dedis/fixbuf v1.0.2/go.mod h1:2syWkaV6ERSAvTkXkD08E6Nrh3Wl8pHMa8F/+HFuAL4= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= @@ -45,6 +46,7 @@ github.com/golang/protobuf v1.2.1-0.20181127190454-8d0c54c12466 h1:Kz9p8XEhFbEfi github.com/golang/protobuf v1.2.1-0.20181127190454-8d0c54c12466/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s= github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U= @@ -204,9 +206,13 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM= github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= @@ -252,6 +258,7 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d h1:Z0Ahzd7HltpJtjAHHxX8QFP3j1yYgiuvjbjRzDj/KH0= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/node/contract.go b/node/contract.go index 505660d93..a57e273ad 100644 --- a/node/contract.go +++ b/node/contract.go @@ -6,6 +6,8 @@ import ( "math/big" "strings" + "github.com/harmony-one/harmony/contracts" + "github.com/harmony-one/harmony/internal/utils" "github.com/ethereum/go-ethereum/common" @@ -23,7 +25,6 @@ const ( FaucetContractBinary = "0x6080604052678ac7230489e8000060015560028054600160a060020a031916331790556101aa806100316000396000f3fe608060405260043610610045577c0100000000000000000000000000000000000000000000000000000000600035046327c78c42811461004a5780634ddd108a1461008c575b600080fd5b34801561005657600080fd5b5061008a6004803603602081101561006d57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166100b3565b005b34801561009857600080fd5b506100a1610179565b60408051918252519081900360200190f35b60025473ffffffffffffffffffffffffffffffffffffffff1633146100d757600080fd5b600154303110156100e757600080fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526020819052604090205460ff161561011a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116600081815260208190526040808220805460ff1916600190811790915554905181156108fc0292818181858888f19350505050158015610175573d6000803e3d6000fd5b5050565b30319056fea165627a7a723058203e799228fee2fa7c5d15e71c04267a0cc2687c5eff3b48b98f21f355e1064ab30029" FaucetContractFund = 8000000 FaucetFreeMoneyMethodCall = "0x27c78c42000000000000000000000000" - StakingContractBinary = "0x608060405234801561001057600080fd5b506103f7806100206000396000f3fe608060405260043610610067576000357c01000000000000000000000000000000000000000000000000000000009004806317437a2c1461006c5780632e1a7d4d146100975780638da5cb5b146100e6578063b69ef8a81461013d578063d0e30db014610168575b600080fd5b34801561007857600080fd5b50610081610186565b6040518082815260200191505060405180910390f35b3480156100a357600080fd5b506100d0600480360360208110156100ba57600080fd5b81019080803590602001909291905050506101a5565b6040518082815260200191505060405180910390f35b3480156100f257600080fd5b506100fb6102cd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561014957600080fd5b506101526102f3565b6040518082815260200191505060405180910390f35b610170610339565b6040518082815260200191505060405180910390f35b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115156102c757816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015610280573d6000803e3d6000fd5b506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506102c8565b5b919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905090565b6000346000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490509056fea165627a7a723058204acf95662eb95006df1e0b8ba32316211039c7872bc6eb99d12689c1624143d80029" ) // AddStakingContractToPendingTransactions adds the deposit smart contract the genesis block. @@ -35,9 +36,9 @@ func (node *Node) AddStakingContractToPendingTransactions() { //Initially the smart contract should have minimal funds. contractFunds := big.NewInt(0) contractFunds = contractFunds.Mul(contractFunds, big.NewInt(params.Ether)) - dataEnc := common.FromHex(StakingContractBinary) + dataEnc := common.FromHex(contracts.StakeLockContractBin) // Unsigned transaction to avoid the case of transaction address. - mycontracttx, _ := types.SignTx(types.NewContractCreation(uint64(0), node.Consensus.ShardID, contractFunds, params.TxGasContractCreation*10, nil, dataEnc), types.HomesteadSigner{}, priKey) + mycontracttx, _ := types.SignTx(types.NewContractCreation(uint64(0), node.Consensus.ShardID, contractFunds, params.TxGasContractCreation*100, nil, dataEnc), types.HomesteadSigner{}, priKey) //node.StakingContractAddress = crypto.CreateAddress(contractAddress, uint64(0)) node.StakingContractAddress = node.generateDeployedStakingContractAddress(contractAddress) node.addPendingTransactions(types.Transactions{mycontracttx}) diff --git a/node/node.go b/node/node.go index b7e76af3d..32624d2f3 100644 --- a/node/node.go +++ b/node/node.go @@ -9,6 +9,8 @@ import ( "sync" "time" + "github.com/harmony-one/harmony/contracts" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" @@ -166,6 +168,9 @@ type Node struct { // map of service type to its message channel. serviceMessageChan map[service.Type]chan *msg_pb.Message + + // Used to call smart contract locally + ContractCaller *contracts.ContractCaller } // Blockchain returns the blockchain from node @@ -251,6 +256,8 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, db ethdb.Database) *N node.DepositToStakingAccounts() } + node.ContractCaller = contracts.NewContractCaller(&db, node.blockchain, params.TestChainConfig) + if consensusObj != nil && consensusObj.IsLeader { node.State = NodeLeader go node.ReceiveClientGroupMessage() diff --git a/node/node_handler.go b/node/node_handler.go index bfb0d7e8f..9b8db9446 100644 --- a/node/node_handler.go +++ b/node/node_handler.go @@ -289,11 +289,6 @@ func (node *Node) VerifyNewBlock(newBlock *types.Block) bool { // 2. [leader] send new block to the client func (node *Node) PostConsensusProcessing(newBlock *types.Block) { utils.GetLogInstance().Info("PostConsensusProcessing") - if node.NodeConfig.Role() == nodeconfig.BeaconLeader { - utils.GetLogInstance().Info("Updating staking list") - node.UpdateStakingList(newBlock) - node.printStakingList() - } if node.Consensus.IsLeader { node.BroadcastNewBlock(newBlock) } @@ -306,6 +301,12 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block) { node.ConfirmedBlockChannel <- newBlock }() } + + if node.NodeConfig.Role() == nodeconfig.BeaconLeader { + utils.GetLogInstance().Info("Updating staking list") + node.UpdateStakingList(newBlock) + node.printStakingList() + } } // AddNewBlock is usedd to add new block into the blockchain. diff --git a/node/staking.go b/node/staking.go index cc4dd1f6d..72a1f3462 100644 --- a/node/staking.go +++ b/node/staking.go @@ -2,16 +2,22 @@ package node import ( "crypto/ecdsa" + "math" "math/big" "os" + "strings" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/harmony-one/harmony/contracts" "github.com/harmony-one/harmony/internal/utils/contract" "github.com/harmony-one/harmony/internal/utils" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/harmony-one/harmony/core/types" + contract_constants "github.com/harmony-one/harmony/internal/utils/contract" ) //constants related to staking @@ -72,7 +78,65 @@ func (node *Node) UpdateStakingList(block *types.Block) error { return nil } +// UpdateStakingListWithABI updates staking information by querying the staking smart contract. +func (node *Node) UpdateStakingListWithABI() { + abi, err := abi.JSON(strings.NewReader(contracts.StakeLockContractABI)) + if err != nil { + utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) + } + bytesData, err := abi.Pack("listLockedAddresses") + if err != nil { + utils.GetLogInstance().Error("Failed to generate ABI function bytes data", "error", err) + } + + priKey := contract_constants.GenesisBeaconAccountPriKey + deployerAddress := crypto.PubkeyToAddress(priKey.PublicKey) + + state, err := node.blockchain.State() + + stakingContractAddress := crypto.CreateAddress(deployerAddress, uint64(0)) + tx := types.NewTransaction( + state.GetNonce(deployerAddress), + stakingContractAddress, + 0, + nil, + math.MaxUint64, + nil, + bytesData, + ) + signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, priKey) + if err != nil { + utils.GetLogInstance().Error("Failed to sign contract call tx", "error", err) + return + } + output, err := node.ContractCaller.CallContract(signedTx) + + if err != nil { + utils.GetLogInstance().Error("Failed to call staking contract", "error", err) + return + } + + ret := new(struct { + LockedAddresses []common.Address + BlockNums []*big.Int + LockPeriodCounts []*big.Int + }) + + err = abi.Unpack(ret, "listLockedAddresses", output) + + if err != nil { + utils.GetLogInstance().Error("[ABI] Failed to unpack contract result", "error", err, "output", output) + } else { + utils.GetLogInstance().Info("\n") + utils.GetLogInstance().Info("ABI [START] ------------------------------------") + utils.GetLogInstance().Info("", "result", ret) + utils.GetLogInstance().Info("ABI [END} ------------------------------------") + utils.GetLogInstance().Info("\n") + } +} + func (node *Node) printStakingList() { + node.UpdateStakingListWithABI() utils.GetLogInstance().Info("\n") utils.GetLogInstance().Info("CURRENT STAKING INFO [START] ------------------------------------") for addr, stake := range node.CurrentStakes { From e2f1e692485dfa813c1a1fcc1a3da99a014c25f4 Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 14:05:00 -0800 Subject: [PATCH 02/15] Update CurrentStake by querying stake contract --- contracts/StakeLockContract.go | 14 ++-- contracts/StakeLockContract.sol | 4 +- node/contract.go | 52 +++++++++++++ node/node.go | 5 +- node/node_handler.go | 2 +- node/staking.go | 134 +++++++------------------------- node/staking_test.go | 105 ++++++------------------- 7 files changed, 119 insertions(+), 197 deletions(-) diff --git a/contracts/StakeLockContract.go b/contracts/StakeLockContract.go index 6b224c17d..0c0e9e430 100644 --- a/contracts/StakeLockContract.go +++ b/contracts/StakeLockContract.go @@ -28,10 +28,10 @@ var ( ) // StakeLockContractABI is the input ABI used to generate the binding from. -const StakeLockContractABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"listLockedAddresses\",\"outputs\":[{\"name\":\"lockedAddresses\",\"type\":\"address[]\"},{\"name\":\"blockNums\",\"type\":\"uint256[]\"},{\"name\":\"lockPeriodCounts\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_of\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"currentEpoch\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unlock\",\"outputs\":[{\"name\":\"unlockableTokens\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_of\",\"type\":\"address\"}],\"name\":\"getUnlockableTokens\",\"outputs\":[{\"name\":\"unlockableTokens\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"lock\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_of\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"Unlocked\",\"type\":\"event\"}]" +const StakeLockContractABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"listLockedAddresses\",\"outputs\":[{\"name\":\"lockedAddresses\",\"type\":\"address[]\"},{\"name\":\"blockNums\",\"type\":\"uint256[]\"},{\"name\":\"lockPeriodCounts\",\"type\":\"uint256[]\"},{\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_of\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"currentEpoch\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unlock\",\"outputs\":[{\"name\":\"unlockableTokens\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_of\",\"type\":\"address\"}],\"name\":\"getUnlockableTokens\",\"outputs\":[{\"name\":\"unlockableTokens\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"lock\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_of\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"Unlocked\",\"type\":\"event\"}]" // StakeLockContractBin is the compiled bytecode used for deploying new contracts. -const StakeLockContractBin = `0x6080604052600560005534801561001557600080fd5b50610895806100256000396000f3fe6080604052600436106100555760003560e01c806363b125151461005a57806370a082311461014d5780637667180814610192578063a69df4b5146101a7578063ab4a2eb3146101bc578063f83d08ba146101ef575b600080fd5b34801561006657600080fd5b5061006f61020b565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b838110156100b757818101518382015260200161009f565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156100f65781810151838201526020016100de565b50505050905001848103825285818151815260200191508051906020019060200280838360005b8381101561013557818101518382015260200161011d565b50505050905001965050505050505060405180910390f35b34801561015957600080fd5b506101806004803603602081101561017057600080fd5b50356001600160a01b031661039a565b60408051918252519081900360200190f35b34801561019e57600080fd5b506101806103b5565b3480156101b357600080fd5b506101806103ca565b3480156101c857600080fd5b50610180600480360360208110156101df57600080fd5b50356001600160a01b03166105b7565b6101f7610614565b604080519115158252519081900360200190f35b6060806060600380548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610248575b5050505050925060038054905060405190808252806020026020018201604052801561029c578160200160208202803883390190505b5060035460408051828152602080840282010190915291935080156102cb578160200160208202803883390190505b50905060005b8351811015610394576001600085838151811015156102ec57fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060010154838281518110151561032857fe5b60209081029091010152835160019060009086908490811061034657fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060030154828281518110151561038257fe5b602090810290910101526001016102d1565b50909192565b6001600160a01b031660009081526001602052604090205490565b60008054438115156103c357fe5b0490505b90565b60006103d5336105b7565b60408051808201909152601481527f4e6f20746f6b656e7320756e6c6f636b61626c65000000000000000000000000602082015290915081151561049a57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561045f578181015183820152602001610447565b50505050905090810190601f16801561048c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50336000908152600160208190526040822060048101805484835592820184905560028201849055600391820184905592909255815490919060001981019081106104e157fe5b600091825260209091200154600380546001600160a01b03909216918390811061050757fe5b6000918252602082200180546001600160a01b0319166001600160a01b0393909316929092179091556003805483926001929091600019810190811061054957fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020600401556003805490610584906000198301610822565b50604051339083156108fc029084906000818181858888f193505050501580156105b2573d6000803e3d6000fd5b505090565b6000806105c26103b5565b6001600160a01b0384166000908152600160205260409020600381810154600290920154929350020181111561060e576001600160a01b03831660009081526001602052604090205491505b50919050565b600061061f3361039a565b60408051808201909152601581527f546f6b656e7320616c7265616479206c6f636b65640000000000000000000000602082015290156106a457604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561045f578181015183820152602001610447565b5060408051808201909152601381527f416d6f756e742063616e206e6f74206265203000000000000000000000000000602082015234151561072b57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561045f578181015183820152602001610447565b506040518060a0016040528034815260200143815260200161074b6103b5565b8152600160208083018290526003805480840182557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810180546001600160a01b0319163390811790915560409586019190915260008181528484528590208651815592860151938301939093559284015160028201556060840151928101929092556080909201516004909101557fd4665e3049283582ba6f9eba07a5b3e12dab49e02da99e8927a47af5d134bea5346108046103b5565b6040805192835260208301919091528051918290030190a250600190565b8154818355818111156108465760008381526020902061084691810190830161084b565b505050565b6103c791905b808211156108655760008155600101610851565b509056fea165627a7a723058205d3d7c5ebbad421d6be22fbc24109d7b34d54381a9bf465e00863358c4c9be880029` +const StakeLockContractBin = `0x6080604052600560005534801561001557600080fd5b5061095a806100256000396000f3fe6080604052600436106100555760003560e01c806363b125151461005a57806370a082311461019257806376671808146101d7578063a69df4b5146101ec578063ab4a2eb314610201578063f83d08ba14610234575b600080fd5b34801561006657600080fd5b5061006f610250565b6040518080602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b838110156100bb5781810151838201526020016100a3565b50505050905001858103845288818151815260200191508051906020019060200280838360005b838110156100fa5781810151838201526020016100e2565b50505050905001858103835287818151815260200191508051906020019060200280838360005b83811015610139578181015183820152602001610121565b50505050905001858103825286818151815260200191508051906020019060200280838360005b83811015610178578181015183820152602001610160565b505050509050019850505050505050505060405180910390f35b34801561019e57600080fd5b506101c5600480360360208110156101b557600080fd5b50356001600160a01b031661045f565b60408051918252519081900360200190f35b3480156101e357600080fd5b506101c561047a565b3480156101f857600080fd5b506101c561048f565b34801561020d57600080fd5b506101c56004803603602081101561022457600080fd5b50356001600160a01b031661067c565b61023c6106d9565b604080519115158252519081900360200190f35b60608060608060038054806020026020016040519081016040528092919081815260200182805480156102ac57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161028e575b505050505093506003805490506040519080825280602002602001820160405280156102e2578160200160208202803883390190505b506003546040805182815260208084028201019091529194508015610311578160200160208202803883390190505b506003546040805182815260208084028201019091529193508015610340578160200160208202803883390190505b50905060005b84518110156104585760016000868381518110151561036157fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060010154848281518110151561039d57fe5b6020908102909101015284516001906000908790849081106103bb57fe5b906020019060200201516001600160a01b03166001600160a01b031681526020019081526020016000206003015483828151811015156103f757fe5b60209081029091010152845160019060009087908490811061041557fe5b60209081029091018101516001600160a01b0316825281019190915260400160002054825183908390811061044657fe5b60209081029091010152600101610346565b5090919293565b6001600160a01b031660009081526001602052604090205490565b600080544381151561048857fe5b0490505b90565b600061049a3361067c565b60408051808201909152601481527f4e6f20746f6b656e7320756e6c6f636b61626c65000000000000000000000000602082015290915081151561055f57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561052457818101518382015260200161050c565b50505050905090810190601f1680156105515780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50336000908152600160208190526040822060048101805484835592820184905560028201849055600391820184905592909255815490919060001981019081106105a657fe5b600091825260209091200154600380546001600160a01b0390921691839081106105cc57fe5b6000918252602082200180546001600160a01b0319166001600160a01b0393909316929092179091556003805483926001929091600019810190811061060e57fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190206004015560038054906106499060001983016108e7565b50604051339083156108fc029084906000818181858888f19350505050158015610677573d6000803e3d6000fd5b505090565b60008061068761047a565b6001600160a01b038416600090815260016020526040902060038181015460029092015492935002018111156106d3576001600160a01b03831660009081526001602052604090205491505b50919050565b60006106e43361045f565b60408051808201909152601581527f546f6b656e7320616c7265616479206c6f636b656400000000000000000000006020820152901561076957604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561052457818101518382015260200161050c565b5060408051808201909152601381527f416d6f756e742063616e206e6f7420626520300000000000000000000000000060208201523415156107f057604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561052457818101518382015260200161050c565b506040518060a0016040528034815260200143815260200161081061047a565b8152600160208083018290526003805480840182557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810180546001600160a01b0319163390811790915560409586019190915260008181528484528590208651815592860151938301939093559284015160028201556060840151928101929092556080909201516004909101557fd4665e3049283582ba6f9eba07a5b3e12dab49e02da99e8927a47af5d134bea5346108c961047a565b6040805192835260208301919091528051918290030190a250600190565b81548183558181111561090b5760008381526020902061090b918101908301610910565b505050565b61048c91905b8082111561092a5760008155600101610916565b509056fea165627a7a723058200e81e1eb104190580cc42b21e0b43d3502d96d9baee36bb198c690918dcf319d0029` // DeployStakeLockContract deploys a new Ethereum contract, binding an instance of StakeLockContract to it. func DeployStakeLockContract(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *StakeLockContract, error) { @@ -268,16 +268,18 @@ func (_StakeLockContract *StakeLockContractCallerSession) GetUnlockableTokens(_o // ListLockedAddresses is a free data retrieval call binding the contract method 0x63b12515. // -// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, uint256[] blockNums, uint256[] lockPeriodCounts) +// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) func (_StakeLockContract *StakeLockContractCaller) ListLockedAddresses(opts *bind.CallOpts) (struct { LockedAddresses []common.Address BlockNums []*big.Int LockPeriodCounts []*big.Int + Amounts []*big.Int }, error) { ret := new(struct { LockedAddresses []common.Address BlockNums []*big.Int LockPeriodCounts []*big.Int + Amounts []*big.Int }) out := ret err := _StakeLockContract.contract.Call(opts, out, "listLockedAddresses") @@ -286,22 +288,24 @@ func (_StakeLockContract *StakeLockContractCaller) ListLockedAddresses(opts *bin // ListLockedAddresses is a free data retrieval call binding the contract method 0x63b12515. // -// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, uint256[] blockNums, uint256[] lockPeriodCounts) +// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) func (_StakeLockContract *StakeLockContractSession) ListLockedAddresses() (struct { LockedAddresses []common.Address BlockNums []*big.Int LockPeriodCounts []*big.Int + Amounts []*big.Int }, error) { return _StakeLockContract.Contract.ListLockedAddresses(&_StakeLockContract.CallOpts) } // ListLockedAddresses is a free data retrieval call binding the contract method 0x63b12515. // -// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, uint256[] blockNums, uint256[] lockPeriodCounts) +// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) func (_StakeLockContract *StakeLockContractCallerSession) ListLockedAddresses() (struct { LockedAddresses []common.Address BlockNums []*big.Int LockPeriodCounts []*big.Int + Amounts []*big.Int }, error) { return _StakeLockContract.Contract.ListLockedAddresses(&_StakeLockContract.CallOpts) } diff --git a/contracts/StakeLockContract.sol b/contracts/StakeLockContract.sol index 25f67c435..509846afd 100644 --- a/contracts/StakeLockContract.sol +++ b/contracts/StakeLockContract.sol @@ -118,14 +118,16 @@ contract StakeLockContract { function listLockedAddresses() public view - returns (address[] memory lockedAddresses, uint256[] memory blockNums, uint256[] memory lockPeriodCounts) + returns (address[] memory lockedAddresses, uint256[] memory blockNums, uint256[] memory lockPeriodCounts, uint256[] memory amounts) { lockedAddresses = addressList; blockNums = new uint256[](addressList.length); lockPeriodCounts = new uint256[](addressList.length); + amounts = new uint256[](addressList.length); for (uint i = 0; i < lockedAddresses.length; i++) { blockNums[i] = locked[lockedAddresses[i]]._blockNum; lockPeriodCounts[i] = locked[lockedAddresses[i]]._lockPeriodCount; + amounts[i] = locked[lockedAddresses[i]]._amount; } } } diff --git a/node/contract.go b/node/contract.go index a57e273ad..1a2a1aed8 100644 --- a/node/contract.go +++ b/node/contract.go @@ -6,6 +6,9 @@ import ( "math/big" "strings" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common/math" + "github.com/harmony-one/harmony/contracts" "github.com/harmony-one/harmony/internal/utils" @@ -61,6 +64,55 @@ func (node *Node) generateDeployedStakingContractAddress(contractAddress common. return crypto.CreateAddress(contractAddress, uint64(nonce)) } +// QueryStakeInfo queries the stake info from the stake contract. +func (node *Node) QueryStakeInfo() *StakeInfo { + abi, err := abi.JSON(strings.NewReader(contracts.StakeLockContractABI)) + if err != nil { + utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) + } + bytesData, err := abi.Pack("listLockedAddresses") + if err != nil { + utils.GetLogInstance().Error("Failed to generate ABI function bytes data", "error", err) + } + + priKey := contract_constants.GenesisBeaconAccountPriKey + deployerAddress := crypto.PubkeyToAddress(priKey.PublicKey) + + state, err := node.blockchain.State() + + stakingContractAddress := crypto.CreateAddress(deployerAddress, uint64(0)) + tx := types.NewTransaction( + state.GetNonce(deployerAddress), + stakingContractAddress, + 0, + nil, + math.MaxUint64, + nil, + bytesData, + ) + signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, priKey) + if err != nil { + utils.GetLogInstance().Error("Failed to sign contract call tx", "error", err) + return nil + } + output, err := node.ContractCaller.CallContract(signedTx) + + if err != nil { + utils.GetLogInstance().Error("Failed to call staking contract", "error", err) + return nil + } + + ret := &StakeInfo{} + + err = abi.Unpack(ret, "listLockedAddresses", output) + + if err != nil { + utils.GetLogInstance().Error("Failed to unpack stake info", "error", err) + return nil + } + return ret +} + // CreateStakingWithdrawTransaction creates a new withdraw stake transaction func (node *Node) CreateStakingWithdrawTransaction(stake string) (*types.Transaction, error) { //These should be read from somewhere. diff --git a/node/node.go b/node/node.go index 32624d2f3..0ec455403 100644 --- a/node/node.go +++ b/node/node.go @@ -5,6 +5,7 @@ import ( "crypto/ecdsa" "encoding/binary" "fmt" + "math/big" "os" "sync" "time" @@ -137,7 +138,7 @@ type Node struct { serviceManager *service.Manager //Staked Accounts and Contract - CurrentStakes map[common.Address]int64 //This will save the latest information about staked nodes. + CurrentStakes map[common.Address]*big.Int //This will save the latest information about staked nodes. StakingContractAddress common.Address WithdrawStakeFunc []byte @@ -251,7 +252,7 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, db ethdb.Database) *N // Setup one time smart contracts node.AddFaucetContractToPendingTransactions() - node.CurrentStakes = make(map[common.Address]int64) + node.CurrentStakes = make(map[common.Address]*big.Int) node.AddStakingContractToPendingTransactions() //This will save the latest information about staked nodes in current staked node.DepositToStakingAccounts() } diff --git a/node/node_handler.go b/node/node_handler.go index 9b8db9446..803d66f75 100644 --- a/node/node_handler.go +++ b/node/node_handler.go @@ -304,7 +304,7 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block) { if node.NodeConfig.Role() == nodeconfig.BeaconLeader { utils.GetLogInstance().Info("Updating staking list") - node.UpdateStakingList(newBlock) + node.UpdateStakingList(node.QueryStakeInfo()) node.printStakingList() } } diff --git a/node/staking.go b/node/staking.go index 72a1f3462..ec52d23e0 100644 --- a/node/staking.go +++ b/node/staking.go @@ -2,22 +2,18 @@ package node import ( "crypto/ecdsa" - "math" "math/big" "os" - "strings" - "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/harmony-one/harmony/core" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - "github.com/harmony-one/harmony/contracts" "github.com/harmony-one/harmony/internal/utils/contract" "github.com/harmony-one/harmony/internal/utils" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/harmony-one/harmony/core/types" - contract_constants "github.com/harmony-one/harmony/internal/utils/contract" ) //constants related to staking @@ -26,117 +22,41 @@ import ( //Refer: https://solidity.readthedocs.io/en/develop/abi-spec.html const ( - // DepositFuncSignature is the func signature for deposit method - DepositFuncSignature = "0xd0e30db0" - withdrawFuncSignature = "0x2e1a7d4d" - funcSingatureBytes = 4 + funcSingatureBytes = 4 + lockPeriodInEpochs = 3 // This should be in sync with contracts/StakeLockContract.sol ) -// UpdateStakingList updates the stakes of every node. -// TODO: read directly from smart contract, or at least check the receipt also for incompleted transaction. -func (node *Node) UpdateStakingList(block *types.Block) error { - signerType := types.HomesteadSigner{} - txns := block.Transactions() - for i := range txns { - txn := txns[i] - toAddress := txn.To() - if toAddress != nil && *toAddress != node.StakingContractAddress { //Not a address aimed at the staking contract. - utils.GetLogInstance().Info("Mismatched Staking Contract Address", "expected", node.StakingContractAddress.Hex(), "got", toAddress.Hex()) - continue - } - currentSender, _ := types.Sender(signerType, txn) - _, isPresent := node.CurrentStakes[currentSender] - data := txn.Data() - switch funcSignature := decodeFuncSign(data); funcSignature { - case DepositFuncSignature: //deposit, currently: 0xd0e30db0 - amount := txn.Value() - value := amount.Int64() - if isPresent { - //This means the node has increased its stake. - node.CurrentStakes[currentSender] += value - } else { - //This means its a new node that is staking the first time. - node.CurrentStakes[currentSender] = value - } - case withdrawFuncSignature: //withdraw, currently: 0x2e1a7d4d - value := decodeStakeCall(data) - if isPresent { - if node.CurrentStakes[currentSender] > value { - node.CurrentStakes[currentSender] -= value - } else if node.CurrentStakes[currentSender] == value { - delete(node.CurrentStakes, currentSender) - } else { - continue //Overdraft protection. - } - } else { - continue //no-op: a node that is not staked cannot withdraw stake. - } - default: - continue //no-op if its not deposit or withdaw - } - } - return nil +// StakeInfo is the struct for the return value of listLockedAddresses func in stake contract. +type StakeInfo struct { + LockedAddresses []common.Address + BlockNums []*big.Int + LockPeriodCounts []*big.Int + Amounts []*big.Int } -// UpdateStakingListWithABI updates staking information by querying the staking smart contract. -func (node *Node) UpdateStakingListWithABI() { - abi, err := abi.JSON(strings.NewReader(contracts.StakeLockContractABI)) - if err != nil { - utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) - } - bytesData, err := abi.Pack("listLockedAddresses") - if err != nil { - utils.GetLogInstance().Error("Failed to generate ABI function bytes data", "error", err) - } - - priKey := contract_constants.GenesisBeaconAccountPriKey - deployerAddress := crypto.PubkeyToAddress(priKey.PublicKey) +// UpdateStakingList updates staking information by querying the staking smart contract. +func (node *Node) UpdateStakingList(stakeInfo *StakeInfo) { + node.CurrentStakes = make(map[common.Address]*big.Int) + if stakeInfo != nil { + for i, addr := range stakeInfo.LockedAddresses { + blockNum := stakeInfo.BlockNums[i] + lockPeriodCount := stakeInfo.LockPeriodCounts[i] + amount := stakeInfo.Amounts[i] - state, err := node.blockchain.State() + startEpoch := core.GetEpochFromBlockNumber(blockNum.Uint64()) + curEpoch := core.GetEpochFromBlockNumber(node.blockchain.CurrentBlock().NumberU64()) - stakingContractAddress := crypto.CreateAddress(deployerAddress, uint64(0)) - tx := types.NewTransaction( - state.GetNonce(deployerAddress), - stakingContractAddress, - 0, - nil, - math.MaxUint64, - nil, - bytesData, - ) - signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, priKey) - if err != nil { - utils.GetLogInstance().Error("Failed to sign contract call tx", "error", err) - return - } - output, err := node.ContractCaller.CallContract(signedTx) - - if err != nil { - utils.GetLogInstance().Error("Failed to call staking contract", "error", err) - return - } - - ret := new(struct { - LockedAddresses []common.Address - BlockNums []*big.Int - LockPeriodCounts []*big.Int - }) - - err = abi.Unpack(ret, "listLockedAddresses", output) - - if err != nil { - utils.GetLogInstance().Error("[ABI] Failed to unpack contract result", "error", err, "output", output) - } else { - utils.GetLogInstance().Info("\n") - utils.GetLogInstance().Info("ABI [START] ------------------------------------") - utils.GetLogInstance().Info("", "result", ret) - utils.GetLogInstance().Info("ABI [END} ------------------------------------") - utils.GetLogInstance().Info("\n") + if startEpoch == curEpoch { + continue // The token are counted into stakes at the beginning of next epoch. + } + if curEpoch-startEpoch <= lockPeriodCount.Uint64()*lockPeriodInEpochs { + node.CurrentStakes[addr] = amount + } + } } } func (node *Node) printStakingList() { - node.UpdateStakingListWithABI() utils.GetLogInstance().Info("\n") utils.GetLogInstance().Info("CURRENT STAKING INFO [START] ------------------------------------") for addr, stake := range node.CurrentStakes { diff --git a/node/staking_test.go b/node/staking_test.go index 30b5c2f9e..277da155c 100644 --- a/node/staking_test.go +++ b/node/staking_test.go @@ -5,107 +5,50 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" "github.com/harmony-one/harmony/consensus" - "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p/p2pimpl" - "golang.org/x/crypto/sha3" ) -func TestUpdateStakingDeposit(t *testing.T) { - _, pubKey := utils.GenKey("1", "2") - leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey} - validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"} - priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") - host, err := p2pimpl.NewHost(&leader, priKey) - if err != nil { - t.Fatalf("newhost failure: %v", err) - } - consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader) - - node := New(host, consensus, nil) - node.CurrentStakes = make(map[common.Address]int64) - - DepositContractPriKey, _ := crypto.GenerateKey() //DepositContractPriKey is pk for contract - DepositContractAddress := crypto.PubkeyToAddress(DepositContractPriKey.PublicKey) //DepositContractAddress is the address for the contract - node.StakingContractAddress = DepositContractAddress - node.AccountKey, _ = crypto.GenerateKey() - Address := crypto.PubkeyToAddress(node.AccountKey.PublicKey) - callingFunction := "0xd0e30db0" - amount := new(big.Int) - amount.SetString("10", 10) - dataEnc := common.FromHex(callingFunction) //Deposit Does not take a argument, stake is transferred via amount. - tx1, err := types.SignTx(types.NewTransaction(0, DepositContractAddress, node.Consensus.ShardID, amount, params.TxGasContractCreation*10, nil, dataEnc), types.HomesteadSigner{}, node.AccountKey) +var ( + amount = big.NewInt(10) + blockNum = big.NewInt(15000) + lockPeriodCount = big.NewInt(1) + testAddress = common.Address{123} +) - var txs []*types.Transaction - txs = append(txs, tx1) - header := &types.Header{Extra: []byte("hello")} - block := types.NewBlock(header, txs, nil) - node.UpdateStakingList(block) - if len(node.CurrentStakes) == 0 { - t.Error("New node's stake was not added") - } - value, ok := node.CurrentStakes[Address] - if !ok { - t.Error("The correct address was not added") - } - if value != 10 { - t.Error("The correct stake value was not added") - } -} +func TestUpdateStakingList(t *testing.T) { -func TestUpdateStakingWithdrawal(t *testing.T) { _, pubKey := utils.GenKey("1", "2") - leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey} - validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"} + leader := p2p.Peer{IP: "127.0.0.1", Port: "9882", PubKey: pubKey} + validator := p2p.Peer{IP: "127.0.0.1", Port: "9885"} priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") host, err := p2pimpl.NewHost(&leader, priKey) if err != nil { t.Fatalf("newhost failure: %v", err) } consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader) - node := New(host, consensus, nil) - node.CurrentStakes = make(map[common.Address]int64) - - DepositContractPriKey, _ := crypto.GenerateKey() //DepositContractPriKey is pk for contract - DepositContractAddress := crypto.PubkeyToAddress(DepositContractPriKey.PublicKey) //DepositContractAddress is the address for the contract - node.StakingContractAddress = DepositContractAddress - node.AccountKey, _ = crypto.GenerateKey() - Address := crypto.PubkeyToAddress(node.AccountKey.PublicKey) - initialStake := int64(1010) - node.CurrentStakes[Address] = initialStake //initial stake - withdrawFnSignature := []byte("withdraw(uint256)") - hash := sha3.NewLegacyKeccak256() - hash.Write(withdrawFnSignature) - methodID := hash.Sum(nil)[:4] + for i := 0; i < 5; i++ { + selectedTxs := node.getTransactionsForNewBlock(MaxNumberOfTransactionsPerBlock) + node.Worker.CommitTransactions(selectedTxs) + block, _ := node.Worker.Commit() - amount := "10" - stakeToWithdraw := new(big.Int) - stakeToWithdraw.SetString(amount, 10) - paddedAmount := common.LeftPadBytes(stakeToWithdraw.Bytes(), 32) + node.AddNewBlock(block) + } - remainingStakeShouldBe := initialStake - stakeToWithdraw.Int64() + stakeInfo := &StakeInfo{ + []common.Address{testAddress}, + []*big.Int{blockNum}, + []*big.Int{lockPeriodCount}, + []*big.Int{amount}, + } - var dataEnc []byte - dataEnc = append(dataEnc, methodID...) - dataEnc = append(dataEnc, paddedAmount...) - tx, err := types.SignTx(types.NewTransaction(0, DepositContractAddress, node.Consensus.ShardID, big.NewInt(0), params.TxGasContractCreation*10, nil, dataEnc), types.HomesteadSigner{}, node.AccountKey) + node.UpdateStakingList(stakeInfo) - var txs []*types.Transaction - txs = append(txs, tx) - header := &types.Header{Extra: []byte("hello")} - block := types.NewBlock(header, txs, nil) - node.UpdateStakingList(block) - currentStake, ok := node.CurrentStakes[Address] - if !ok { - t.Error("The correct address was not present") - } - if currentStake != remainingStakeShouldBe { - t.Error("The correct stake value was not subtracted") + if node.CurrentStakes[testAddress].Cmp(amount) != 0 { + t.Error("Stake Info is not updated correctly") } } From 0dad1daeb0f84de9a8f1d525b0f284f2d1db23fc Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 14:16:16 -0800 Subject: [PATCH 03/15] Add go gen --- contracts/contracts.go | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 contracts/contracts.go diff --git a/contracts/contracts.go b/contracts/contracts.go new file mode 100644 index 000000000..f5ce43147 --- /dev/null +++ b/contracts/contracts.go @@ -0,0 +1,3 @@ +package contracts + +//go:generate abigen -sol StakeLockContract.sol -pkg contracts -out StakeLockContract.go From 30c0d721f9f3c68895524f66db8676246ac978ff Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 16:31:23 -0800 Subject: [PATCH 04/15] Add install_solc.sh --- .travis.yml | 1 + contracts/StakeLockContract.go | 2 +- scripts/install_solc.sh | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 scripts/install_solc.sh diff --git a/.travis.yml b/.travis.yml index 89651aeb1..31693e39a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,7 @@ install: - go get github.com/golang/mock/mockgen - go get github.com/golang/protobuf/protoc-gen-go - ./scripts/install_protoc.sh -V 3.6.1 + - ./scripts/install_solc.sh - ./scripts/travis_checker.sh - go build -v ./... script: diff --git a/contracts/StakeLockContract.go b/contracts/StakeLockContract.go index 0c0e9e430..26ea2a3d8 100644 --- a/contracts/StakeLockContract.go +++ b/contracts/StakeLockContract.go @@ -31,7 +31,7 @@ var ( const StakeLockContractABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"listLockedAddresses\",\"outputs\":[{\"name\":\"lockedAddresses\",\"type\":\"address[]\"},{\"name\":\"blockNums\",\"type\":\"uint256[]\"},{\"name\":\"lockPeriodCounts\",\"type\":\"uint256[]\"},{\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_of\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"currentEpoch\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unlock\",\"outputs\":[{\"name\":\"unlockableTokens\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_of\",\"type\":\"address\"}],\"name\":\"getUnlockableTokens\",\"outputs\":[{\"name\":\"unlockableTokens\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"lock\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_of\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"Unlocked\",\"type\":\"event\"}]" // StakeLockContractBin is the compiled bytecode used for deploying new contracts. -const StakeLockContractBin = `0x6080604052600560005534801561001557600080fd5b5061095a806100256000396000f3fe6080604052600436106100555760003560e01c806363b125151461005a57806370a082311461019257806376671808146101d7578063a69df4b5146101ec578063ab4a2eb314610201578063f83d08ba14610234575b600080fd5b34801561006657600080fd5b5061006f610250565b6040518080602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b838110156100bb5781810151838201526020016100a3565b50505050905001858103845288818151815260200191508051906020019060200280838360005b838110156100fa5781810151838201526020016100e2565b50505050905001858103835287818151815260200191508051906020019060200280838360005b83811015610139578181015183820152602001610121565b50505050905001858103825286818151815260200191508051906020019060200280838360005b83811015610178578181015183820152602001610160565b505050509050019850505050505050505060405180910390f35b34801561019e57600080fd5b506101c5600480360360208110156101b557600080fd5b50356001600160a01b031661045f565b60408051918252519081900360200190f35b3480156101e357600080fd5b506101c561047a565b3480156101f857600080fd5b506101c561048f565b34801561020d57600080fd5b506101c56004803603602081101561022457600080fd5b50356001600160a01b031661067c565b61023c6106d9565b604080519115158252519081900360200190f35b60608060608060038054806020026020016040519081016040528092919081815260200182805480156102ac57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161028e575b505050505093506003805490506040519080825280602002602001820160405280156102e2578160200160208202803883390190505b506003546040805182815260208084028201019091529194508015610311578160200160208202803883390190505b506003546040805182815260208084028201019091529193508015610340578160200160208202803883390190505b50905060005b84518110156104585760016000868381518110151561036157fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060010154848281518110151561039d57fe5b6020908102909101015284516001906000908790849081106103bb57fe5b906020019060200201516001600160a01b03166001600160a01b031681526020019081526020016000206003015483828151811015156103f757fe5b60209081029091010152845160019060009087908490811061041557fe5b60209081029091018101516001600160a01b0316825281019190915260400160002054825183908390811061044657fe5b60209081029091010152600101610346565b5090919293565b6001600160a01b031660009081526001602052604090205490565b600080544381151561048857fe5b0490505b90565b600061049a3361067c565b60408051808201909152601481527f4e6f20746f6b656e7320756e6c6f636b61626c65000000000000000000000000602082015290915081151561055f57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561052457818101518382015260200161050c565b50505050905090810190601f1680156105515780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50336000908152600160208190526040822060048101805484835592820184905560028201849055600391820184905592909255815490919060001981019081106105a657fe5b600091825260209091200154600380546001600160a01b0390921691839081106105cc57fe5b6000918252602082200180546001600160a01b0319166001600160a01b0393909316929092179091556003805483926001929091600019810190811061060e57fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190206004015560038054906106499060001983016108e7565b50604051339083156108fc029084906000818181858888f19350505050158015610677573d6000803e3d6000fd5b505090565b60008061068761047a565b6001600160a01b038416600090815260016020526040902060038181015460029092015492935002018111156106d3576001600160a01b03831660009081526001602052604090205491505b50919050565b60006106e43361045f565b60408051808201909152601581527f546f6b656e7320616c7265616479206c6f636b656400000000000000000000006020820152901561076957604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561052457818101518382015260200161050c565b5060408051808201909152601381527f416d6f756e742063616e206e6f7420626520300000000000000000000000000060208201523415156107f057604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561052457818101518382015260200161050c565b506040518060a0016040528034815260200143815260200161081061047a565b8152600160208083018290526003805480840182557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810180546001600160a01b0319163390811790915560409586019190915260008181528484528590208651815592860151938301939093559284015160028201556060840151928101929092556080909201516004909101557fd4665e3049283582ba6f9eba07a5b3e12dab49e02da99e8927a47af5d134bea5346108c961047a565b6040805192835260208301919091528051918290030190a250600190565b81548183558181111561090b5760008381526020902061090b918101908301610910565b505050565b61048c91905b8082111561092a5760008155600101610916565b509056fea165627a7a723058200e81e1eb104190580cc42b21e0b43d3502d96d9baee36bb198c690918dcf319d0029` +const StakeLockContractBin = `0x6080604052600560005534801561001557600080fd5b5061095a806100256000396000f3fe6080604052600436106100555760003560e01c806363b125151461005a57806370a082311461019257806376671808146101d7578063a69df4b5146101ec578063ab4a2eb314610201578063f83d08ba14610234575b600080fd5b34801561006657600080fd5b5061006f610250565b6040518080602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b838110156100bb5781810151838201526020016100a3565b50505050905001858103845288818151815260200191508051906020019060200280838360005b838110156100fa5781810151838201526020016100e2565b50505050905001858103835287818151815260200191508051906020019060200280838360005b83811015610139578181015183820152602001610121565b50505050905001858103825286818151815260200191508051906020019060200280838360005b83811015610178578181015183820152602001610160565b505050509050019850505050505050505060405180910390f35b34801561019e57600080fd5b506101c5600480360360208110156101b557600080fd5b50356001600160a01b031661045f565b60408051918252519081900360200190f35b3480156101e357600080fd5b506101c561047a565b3480156101f857600080fd5b506101c561048f565b34801561020d57600080fd5b506101c56004803603602081101561022457600080fd5b50356001600160a01b031661067c565b61023c6106d9565b604080519115158252519081900360200190f35b60608060608060038054806020026020016040519081016040528092919081815260200182805480156102ac57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161028e575b505050505093506003805490506040519080825280602002602001820160405280156102e2578160200160208202803883390190505b506003546040805182815260208084028201019091529194508015610311578160200160208202803883390190505b506003546040805182815260208084028201019091529193508015610340578160200160208202803883390190505b50905060005b84518110156104585760016000868381518110151561036157fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060010154848281518110151561039d57fe5b6020908102909101015284516001906000908790849081106103bb57fe5b906020019060200201516001600160a01b03166001600160a01b031681526020019081526020016000206003015483828151811015156103f757fe5b60209081029091010152845160019060009087908490811061041557fe5b60209081029091018101516001600160a01b0316825281019190915260400160002054825183908390811061044657fe5b60209081029091010152600101610346565b5090919293565b6001600160a01b031660009081526001602052604090205490565b600080544381151561048857fe5b0490505b90565b600061049a3361067c565b60408051808201909152601481527f4e6f20746f6b656e7320756e6c6f636b61626c65000000000000000000000000602082015290915081151561055f57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561052457818101518382015260200161050c565b50505050905090810190601f1680156105515780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50336000908152600160208190526040822060048101805484835592820184905560028201849055600391820184905592909255815490919060001981019081106105a657fe5b600091825260209091200154600380546001600160a01b0390921691839081106105cc57fe5b6000918252602082200180546001600160a01b0319166001600160a01b0393909316929092179091556003805483926001929091600019810190811061060e57fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190206004015560038054906106499060001983016108e7565b50604051339083156108fc029084906000818181858888f19350505050158015610677573d6000803e3d6000fd5b505090565b60008061068761047a565b6001600160a01b038416600090815260016020526040902060038181015460029092015492935002018111156106d3576001600160a01b03831660009081526001602052604090205491505b50919050565b60006106e43361045f565b60408051808201909152601581527f546f6b656e7320616c7265616479206c6f636b656400000000000000000000006020820152901561076957604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561052457818101518382015260200161050c565b5060408051808201909152601381527f416d6f756e742063616e206e6f7420626520300000000000000000000000000060208201523415156107f057604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561052457818101518382015260200161050c565b506040518060a0016040528034815260200143815260200161081061047a565b8152600160208083018290526003805480840182557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810180546001600160a01b0319163390811790915560409586019190915260008181528484528590208651815592860151938301939093559284015160028201556060840151928101929092556080909201516004909101557fd4665e3049283582ba6f9eba07a5b3e12dab49e02da99e8927a47af5d134bea5346108c961047a565b6040805192835260208301919091528051918290030190a250600190565b81548183558181111561090b5760008381526020902061090b918101908301610910565b505050565b61048c91905b8082111561092a5760008155600101610916565b509056fea165627a7a723058209f27dc5388d4508d0aeccbbf0ae74929289525f4918465e7eee508195182385c0029` // DeployStakeLockContract deploys a new Ethereum contract, binding an instance of StakeLockContract to it. func DeployStakeLockContract(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *StakeLockContract, error) { diff --git a/scripts/install_solc.sh b/scripts/install_solc.sh new file mode 100644 index 000000000..6484e12b2 --- /dev/null +++ b/scripts/install_solc.sh @@ -0,0 +1,3 @@ +add-apt-repository ppa:ethereum/ethereum +apt-get update +apt-get -y install solc From c7db55df32ec2d9145c562424559dfc4a5e4ea3a Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 16:50:20 -0800 Subject: [PATCH 05/15] change permission for install_solc.sh --- scripts/install_solc.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/install_solc.sh b/scripts/install_solc.sh index 6484e12b2..df1bd62ff 100644 --- a/scripts/install_solc.sh +++ b/scripts/install_solc.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + add-apt-repository ppa:ethereum/ethereum apt-get update apt-get -y install solc From 5ad09ffda4e178e5480c14f32465649f65fd7ad6 Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 16:56:35 -0800 Subject: [PATCH 06/15] add comment for StakeInfo --- node/staking.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/staking.go b/node/staking.go index ec52d23e0..fc62d5d11 100644 --- a/node/staking.go +++ b/node/staking.go @@ -30,7 +30,7 @@ const ( type StakeInfo struct { LockedAddresses []common.Address BlockNums []*big.Int - LockPeriodCounts []*big.Int + LockPeriodCounts []*big.Int // The number of locking period the token will be locked. Amounts []*big.Int } From 25bbac641149b541454e5aad59895b266f92b505 Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 17:05:44 -0800 Subject: [PATCH 07/15] change permission of install solc --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 31693e39a..b28250bfc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,7 @@ install: - go get github.com/golang/mock/mockgen - go get github.com/golang/protobuf/protoc-gen-go - ./scripts/install_protoc.sh -V 3.6.1 + - chmod -x ./scripts/install_solc.sh - ./scripts/install_solc.sh - ./scripts/travis_checker.sh - go build -v ./... From fe8316ba34081bdd275431dd69dde30ec907563a Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 17:14:24 -0800 Subject: [PATCH 08/15] Change permission for install_solc.sh --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b28250bfc..31693e39a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,6 @@ install: - go get github.com/golang/mock/mockgen - go get github.com/golang/protobuf/protoc-gen-go - ./scripts/install_protoc.sh -V 3.6.1 - - chmod -x ./scripts/install_solc.sh - ./scripts/install_solc.sh - ./scripts/travis_checker.sh - go build -v ./... From 5ee4d7368d4ef401d87a1cadf64301b72b6bc766 Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 17:45:52 -0800 Subject: [PATCH 09/15] Make install_solc executable --- scripts/install_solc.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/install_solc.sh diff --git a/scripts/install_solc.sh b/scripts/install_solc.sh old mode 100644 new mode 100755 From 4585d5d63620dac0d4b5993c6fe582dc2225bf7d Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 18:12:39 -0800 Subject: [PATCH 10/15] add sudo --- scripts/install_solc.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) mode change 100755 => 100644 scripts/install_solc.sh diff --git a/scripts/install_solc.sh b/scripts/install_solc.sh old mode 100755 new mode 100644 index df1bd62ff..c84162518 --- a/scripts/install_solc.sh +++ b/scripts/install_solc.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -add-apt-repository ppa:ethereum/ethereum -apt-get update -apt-get -y install solc +sudo add-apt-repository ppa:ethereum/ethereum +sudo apt-get update +sudo apt-get -y install solc From 9dd43920883fb3b545bb1710f5e0998b591e627e Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 18:14:50 -0800 Subject: [PATCH 11/15] change permission --- scripts/install_solc.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/install_solc.sh diff --git a/scripts/install_solc.sh b/scripts/install_solc.sh old mode 100644 new mode 100755 From b213e890d3a8739b3ff49cd8415db7384e476f21 Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 18:52:32 -0800 Subject: [PATCH 12/15] auto yes --- scripts/install_solc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100755 => 100644 scripts/install_solc.sh diff --git a/scripts/install_solc.sh b/scripts/install_solc.sh old mode 100755 new mode 100644 index c84162518..467aed4aa --- a/scripts/install_solc.sh +++ b/scripts/install_solc.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -sudo add-apt-repository ppa:ethereum/ethereum -sudo apt-get update +sudo add-apt-repository -y ppa:ethereum/ethereum +sudo apt-get -y update sudo apt-get -y install solc From 89cdf5ccc8013ae3931a97d65a930513e32c07d7 Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 18:53:22 -0800 Subject: [PATCH 13/15] change permission --- scripts/install_solc.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/install_solc.sh diff --git a/scripts/install_solc.sh b/scripts/install_solc.sh old mode 100644 new mode 100755 From 948ba3b82499bee1df576847553092939a69ed72 Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 19:14:12 -0800 Subject: [PATCH 14/15] remove install_solc in travis for now --- .travis.yml | 1 - scripts/install_solc.sh | 0 2 files changed, 1 deletion(-) mode change 100755 => 100644 scripts/install_solc.sh diff --git a/.travis.yml b/.travis.yml index 31693e39a..89651aeb1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,6 @@ install: - go get github.com/golang/mock/mockgen - go get github.com/golang/protobuf/protoc-gen-go - ./scripts/install_protoc.sh -V 3.6.1 - - ./scripts/install_solc.sh - ./scripts/travis_checker.sh - go build -v ./... script: diff --git a/scripts/install_solc.sh b/scripts/install_solc.sh old mode 100755 new mode 100644 From 4cd9a2d1017cfc905b015c6cb509c9f138c5eb53 Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 7 Mar 2019 23:11:35 -0800 Subject: [PATCH 15/15] fix lint, remove go gen --- contracts/contracts.go | 3 --- node/staking.go | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 contracts/contracts.go diff --git a/contracts/contracts.go b/contracts/contracts.go deleted file mode 100644 index f5ce43147..000000000 --- a/contracts/contracts.go +++ /dev/null @@ -1,3 +0,0 @@ -package contracts - -//go:generate abigen -sol StakeLockContract.sol -pkg contracts -out StakeLockContract.go diff --git a/node/staking.go b/node/staking.go index fc62d5d11..e34a99671 100644 --- a/node/staking.go +++ b/node/staking.go @@ -30,7 +30,7 @@ const ( type StakeInfo struct { LockedAddresses []common.Address BlockNums []*big.Int - LockPeriodCounts []*big.Int // The number of locking period the token will be locked. + LockPeriodCounts []*big.Int // The number of locking period the token will be locked. Amounts []*big.Int }