diff --git a/api/service/staking/service.go b/api/service/staking/service.go index 761fad675..7b38af433 100644 --- a/api/service/staking/service.go +++ b/api/service/staking/service.go @@ -47,6 +47,7 @@ type Service struct { stopChan chan struct{} stoppedChan chan struct{} accountKey *ecdsa.PrivateKey + blsAddress [20]byte stakingAmount int64 state State beaconChain *core.BlockChain @@ -54,12 +55,13 @@ type Service struct { } // New returns staking service. -func New(host p2p.Host, accountKey *ecdsa.PrivateKey, beaconChain *core.BlockChain) *Service { +func New(host p2p.Host, accountKey *ecdsa.PrivateKey, beaconChain *core.BlockChain, blsAddress [20]byte) *Service { return &Service{ host: host, stopChan: make(chan struct{}), stoppedChan: make(chan struct{}), accountKey: accountKey, + blsAddress: blsAddress, stakingAmount: StakingAmount, beaconChain: beaconChain, } @@ -184,7 +186,8 @@ func (s *Service) createRawStakingMessage() []byte { if err != nil { utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) } - bytesData, err := abi.Pack("lock") + // TODO: the bls address should be signed by the bls private key + bytesData, err := abi.Pack("lock", s.blsAddress) if err != nil { utils.GetLogInstance().Error("Failed to generate ABI function bytes data", "error", err) } diff --git a/contracts/StakeLockContract.go b/contracts/StakeLockContract.go index 26ea2a3d8..641085cb6 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[]\"},{\"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\"}]" +const StakeLockContractABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"listLockedAddresses\",\"outputs\":[{\"name\":\"lockedAddresses\",\"type\":\"address[]\"},{\"name\":\"blsAddresses\",\"type\":\"bytes20[]\"},{\"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\":\"_blsAddress\",\"type\":\"bytes20\"}],\"name\":\"lock\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":true,\"stateMutability\":\"payable\",\"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\"},{\"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 = `0x6080604052600560005534801561001557600080fd5b5061095a806100256000396000f3fe6080604052600436106100555760003560e01c806363b125151461005a57806370a082311461019257806376671808146101d7578063a69df4b5146101ec578063ab4a2eb314610201578063f83d08ba14610234575b600080fd5b34801561006657600080fd5b5061006f610250565b6040518080602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b838110156100bb5781810151838201526020016100a3565b50505050905001858103845288818151815260200191508051906020019060200280838360005b838110156100fa5781810151838201526020016100e2565b50505050905001858103835287818151815260200191508051906020019060200280838360005b83811015610139578181015183820152602001610121565b50505050905001858103825286818151815260200191508051906020019060200280838360005b83811015610178578181015183820152602001610160565b505050509050019850505050505050505060405180910390f35b34801561019e57600080fd5b506101c5600480360360208110156101b557600080fd5b50356001600160a01b031661045f565b60408051918252519081900360200190f35b3480156101e357600080fd5b506101c561047a565b3480156101f857600080fd5b506101c561048f565b34801561020d57600080fd5b506101c56004803603602081101561022457600080fd5b50356001600160a01b031661067c565b61023c6106d9565b604080519115158252519081900360200190f35b60608060608060038054806020026020016040519081016040528092919081815260200182805480156102ac57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161028e575b505050505093506003805490506040519080825280602002602001820160405280156102e2578160200160208202803883390190505b506003546040805182815260208084028201019091529194508015610311578160200160208202803883390190505b506003546040805182815260208084028201019091529193508015610340578160200160208202803883390190505b50905060005b84518110156104585760016000868381518110151561036157fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060010154848281518110151561039d57fe5b6020908102909101015284516001906000908790849081106103bb57fe5b906020019060200201516001600160a01b03166001600160a01b031681526020019081526020016000206003015483828151811015156103f757fe5b60209081029091010152845160019060009087908490811061041557fe5b60209081029091018101516001600160a01b0316825281019190915260400160002054825183908390811061044657fe5b60209081029091010152600101610346565b5090919293565b6001600160a01b031660009081526001602052604090205490565b600080544381151561048857fe5b0490505b90565b600061049a3361067c565b60408051808201909152601481527f4e6f20746f6b656e7320756e6c6f636b61626c65000000000000000000000000602082015290915081151561055f57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561052457818101518382015260200161050c565b50505050905090810190601f1680156105515780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50336000908152600160208190526040822060048101805484835592820184905560028201849055600391820184905592909255815490919060001981019081106105a657fe5b600091825260209091200154600380546001600160a01b0390921691839081106105cc57fe5b6000918252602082200180546001600160a01b0319166001600160a01b0393909316929092179091556003805483926001929091600019810190811061060e57fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190206004015560038054906106499060001983016108e7565b50604051339083156108fc029084906000818181858888f19350505050158015610677573d6000803e3d6000fd5b505090565b60008061068761047a565b6001600160a01b038416600090815260016020526040902060038181015460029092015492935002018111156106d3576001600160a01b03831660009081526001602052604090205491505b50919050565b60006106e43361045f565b60408051808201909152601581527f546f6b656e7320616c7265616479206c6f636b656400000000000000000000006020820152901561076957604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561052457818101518382015260200161050c565b5060408051808201909152601381527f416d6f756e742063616e206e6f7420626520300000000000000000000000000060208201523415156107f057604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360008381101561052457818101518382015260200161050c565b506040518060a0016040528034815260200143815260200161081061047a565b8152600160208083018290526003805480840182557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810180546001600160a01b0319163390811790915560409586019190915260008181528484528590208651815592860151938301939093559284015160028201556060840151928101929092556080909201516004909101557fd4665e3049283582ba6f9eba07a5b3e12dab49e02da99e8927a47af5d134bea5346108c961047a565b6040805192835260208301919091528051918290030190a250600190565b81548183558181111561090b5760008381526020902061090b918101908301610910565b505050565b61048c91905b8082111561092a5760008155600101610916565b509056fea165627a7a723058209f27dc5388d4508d0aeccbbf0ae74929289525f4918465e7eee508195182385c0029` +const StakeLockContractBin = `0x6080604052600560005534801561001557600080fd5b50610b21806100256000396000f3fe6080604052600436106100555760003560e01c806363b125151461005a57806370a08231146101d7578063766718081461021c5780639de746a514610231578063a69df4b51461026c578063ab4a2eb314610281575b600080fd5b34801561006657600080fd5b5061006f6102b4565b60405180806020018060200180602001806020018060200186810386528b818151815260200191508051906020019060200280838360005b838110156100bf5781810151838201526020016100a7565b5050505090500186810385528a818151815260200191508051906020019060200280838360005b838110156100fe5781810151838201526020016100e6565b50505050905001868103845289818151815260200191508051906020019060200280838360005b8381101561013d578181015183820152602001610125565b50505050905001868103835288818151815260200191508051906020019060200280838360005b8381101561017c578181015183820152602001610164565b50505050905001868103825287818151815260200191508051906020019060200280838360005b838110156101bb5781810151838201526020016101a3565b505050509050019a505050505050505050505060405180910390f35b3480156101e357600080fd5b5061020a600480360360208110156101fa57600080fd5b50356001600160a01b031661055c565b60408051918252519081900360200190f35b34801561022857600080fd5b5061020a610577565b6102586004803603602081101561024757600080fd5b50356001600160601b03191661058c565b604080519115158252519081900360200190f35b34801561027857600080fd5b5061020a610890565b34801561028d57600080fd5b5061020a600480360360208110156102a457600080fd5b50356001600160a01b0316610a51565b6060806060806060600380548060200260200160405190810160405280929190818152602001828054801561031257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116102f4575b50505050509450600380549050604051908082528060200260200182016040528015610348578160200160208202803883390190505b506003546040805182815260208084028201019091529195508015610377578160200160208202803883390190505b5060035460408051828152602080840282010190915291945080156103a6578160200160208202803883390190505b5060035460408051828152602080840282010190915291935080156103d5578160200160208202803883390190505b50905060005b8551811015610554576001600087838151811015156103f657fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060010154848281518110151561043257fe5b60209081029091010152855160019060009088908490811061045057fe5b60209081029091018101516001600160a01b0316825281019190915260400160002060050154855160609190911b9086908390811061048b57fe5b6001600160601b031990921660209283029091019091015285516001906000908890849081106104b757fe5b906020019060200201516001600160a01b03166001600160a01b031681526020019081526020016000206003015483828151811015156104f357fe5b60209081029091010152855160019060009088908490811061051157fe5b60209081029091018101516001600160a01b0316825281019190915260400160002054825183908390811061054257fe5b602090810290910101526001016103db565b509091929394565b6001600160a01b031660009081526001602052604090205490565b600080544381151561058557fe5b0490505b90565b60408051808201909152601f81527f424c5320616464726573732073686f756c64206e6f7420626520656d7074790060208201526000906001600160601b03198316151561065b57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610620578181015183820152602001610608565b50505050905090810190601f16801561064d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506106653361055c565b60408051808201909152601581527f546f6b656e7320616c7265616479206c6f636b65640000000000000000000000602082015290156106ea57604051600160e51b62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610620578181015183820152602001610608565b5060408051808201909152601381527f416d6f756e742063616e206e6f74206265203000000000000000000000000000602082015234151561077157604051600160e51b62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610620578181015183820152602001610608565b506040518060c00160405280348152602001438152602001610791610577565b8152600160208083018290526003805480840182557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810180546001600160a01b0319908116339081179092556040808801939093526001600160601b03198a16606097880152600082815286865283902088518155948801519585019590955590860151600284015585850151918301919091556080850151600483015560a090940151600590910180549190931c91161790557fd4665e3049283582ba6f9eba07a5b3e12dab49e02da99e8927a47af5d134bea534610870610577565b6040805192835260208301919091528051918290030190a2506001919050565b600061089b33610a51565b60408051808201909152601481527f4e6f20746f6b656e7320756e6c6f636b61626c65000000000000000000000000602082015290915081151561092457604051600160e51b62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610620578181015183820152602001610608565b50336000908152600160208190526040822060048101805484835592820184905560028201849055600380830185905593905560050180546001600160a01b03191690558154909190600019810190811061097b57fe5b600091825260209091200154600380546001600160a01b0390921691839081106109a157fe5b6000918252602082200180546001600160a01b0319166001600160a01b039390931692909217909155600380548392600192909160001981019081106109e357fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020600401556003805490610a1e906000198301610aae565b50604051339083156108fc029084906000818181858888f19350505050158015610a4c573d6000803e3d6000fd5b505090565b600080610a5c610577565b6001600160a01b03841660009081526001602052604090206003818101546002909201549293500201811115610aa8576001600160a01b03831660009081526001602052604090205491505b50919050565b815481835581811115610ad257600083815260209020610ad2918101908301610ad7565b505050565b61058991905b80821115610af15760008155600101610add565b509056fea165627a7a72305820de21205eb52d566f7d604e6f7fafe84f5f070db28cf3918cb8a9ab98590b922a0029` // 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,15 +268,17 @@ 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, uint256[] amounts) +// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, bytes20[] blsAddresses, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) func (_StakeLockContract *StakeLockContractCaller) ListLockedAddresses(opts *bind.CallOpts) (struct { LockedAddresses []common.Address + BlsAddresses [][20]byte BlockNums []*big.Int LockPeriodCounts []*big.Int Amounts []*big.Int }, error) { ret := new(struct { LockedAddresses []common.Address + BlsAddresses [][20]byte BlockNums []*big.Int LockPeriodCounts []*big.Int Amounts []*big.Int @@ -288,9 +290,10 @@ 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, uint256[] amounts) +// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, bytes20[] blsAddresses, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) func (_StakeLockContract *StakeLockContractSession) ListLockedAddresses() (struct { LockedAddresses []common.Address + BlsAddresses [][20]byte BlockNums []*big.Int LockPeriodCounts []*big.Int Amounts []*big.Int @@ -300,9 +303,10 @@ func (_StakeLockContract *StakeLockContractSession) ListLockedAddresses() (struc // ListLockedAddresses is a free data retrieval call binding the contract method 0x63b12515. // -// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) +// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, bytes20[] blsAddresses, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) func (_StakeLockContract *StakeLockContractCallerSession) ListLockedAddresses() (struct { LockedAddresses []common.Address + BlsAddresses [][20]byte BlockNums []*big.Int LockPeriodCounts []*big.Int Amounts []*big.Int @@ -310,25 +314,25 @@ func (_StakeLockContract *StakeLockContractCallerSession) ListLockedAddresses() return _StakeLockContract.Contract.ListLockedAddresses(&_StakeLockContract.CallOpts) } -// Lock is a paid mutator transaction binding the contract method 0xf83d08ba. +// Lock is a paid mutator transaction binding the contract method 0x9de746a5. // -// Solidity: function lock() returns(bool) -func (_StakeLockContract *StakeLockContractTransactor) Lock(opts *bind.TransactOpts) (*types.Transaction, error) { - return _StakeLockContract.contract.Transact(opts, "lock") +// Solidity: function lock(bytes20 _blsAddress) returns(bool) +func (_StakeLockContract *StakeLockContractTransactor) Lock(opts *bind.TransactOpts, _blsAddress [20]byte) (*types.Transaction, error) { + return _StakeLockContract.contract.Transact(opts, "lock", _blsAddress) } -// Lock is a paid mutator transaction binding the contract method 0xf83d08ba. +// Lock is a paid mutator transaction binding the contract method 0x9de746a5. // -// Solidity: function lock() returns(bool) -func (_StakeLockContract *StakeLockContractSession) Lock() (*types.Transaction, error) { - return _StakeLockContract.Contract.Lock(&_StakeLockContract.TransactOpts) +// Solidity: function lock(bytes20 _blsAddress) returns(bool) +func (_StakeLockContract *StakeLockContractSession) Lock(_blsAddress [20]byte) (*types.Transaction, error) { + return _StakeLockContract.Contract.Lock(&_StakeLockContract.TransactOpts, _blsAddress) } -// Lock is a paid mutator transaction binding the contract method 0xf83d08ba. +// Lock is a paid mutator transaction binding the contract method 0x9de746a5. // -// Solidity: function lock() returns(bool) -func (_StakeLockContract *StakeLockContractTransactorSession) Lock() (*types.Transaction, error) { - return _StakeLockContract.Contract.Lock(&_StakeLockContract.TransactOpts) +// Solidity: function lock(bytes20 _blsAddress) returns(bool) +func (_StakeLockContract *StakeLockContractTransactorSession) Lock(_blsAddress [20]byte) (*types.Transaction, error) { + return _StakeLockContract.Contract.Lock(&_StakeLockContract.TransactOpts, _blsAddress) } // Unlock is a paid mutator transaction binding the contract method 0xa69df4b5. diff --git a/contracts/StakeLockContract.sol b/contracts/StakeLockContract.sol index 509846afd..8ac610280 100644 --- a/contracts/StakeLockContract.sol +++ b/contracts/StakeLockContract.sol @@ -7,6 +7,7 @@ contract StakeLockContract { string internal constant ALREADY_LOCKED = 'Tokens already locked'; string internal constant NO_TOKEN_UNLOCKABLE = 'No tokens unlockable'; string internal constant AMOUNT_ZERO = 'Amount can not be 0'; + string internal constant EMPTY_BLS_ADDRESS = 'BLS address should not be empty'; uint256 internal constant LOCK_PERIOD_IN_EPOCHS = 3; // Final locking period TBD. @@ -21,6 +22,8 @@ contract StakeLockContract { uint256 _epochNum; // The epoch when the token was locked uint256 _lockPeriodCount; // The number of locking period the token will be locked. uint256 _index; // The index in the addressList + bytes20 _blsAddress; // The address of BLS account used for consensus message signing. + // TODO: the bls address should be signed by the bls key to prove the ownership. } /** @@ -37,19 +40,21 @@ contract StakeLockContract { /** * @dev Locks a specified amount of tokens against an address * starting at the specific epoch + * @param _blsAddress The address of BLS key for consensus message signing */ - function lock() + function lock(bytes20 _blsAddress) public payable returns (bool) { // If tokens are already locked, then functions extendLock or // increaseLockAmount should be used to make any changes + require(_blsAddress != 0, EMPTY_BLS_ADDRESS); require(balanceOf(msg.sender) == 0, ALREADY_LOCKED); require(msg.value != 0, AMOUNT_ZERO); // By default, the tokens can only be locked for one locking period. - locked[msg.sender] = lockedToken(msg.value, block.number, currentEpoch(), 1, addressList.push(msg.sender) - 1); + locked[msg.sender] = lockedToken(msg.value, block.number, currentEpoch(), 1, addressList.push(msg.sender) - 1, _blsAddress); emit Locked(msg.sender, msg.value, currentEpoch()); return true; @@ -118,14 +123,16 @@ contract StakeLockContract { function listLockedAddresses() public view - returns (address[] memory lockedAddresses, uint256[] memory blockNums, uint256[] memory lockPeriodCounts, uint256[] memory amounts) + returns (address[] memory lockedAddresses, bytes20[] memory blsAddresses, uint256[] memory blockNums, uint256[] memory lockPeriodCounts, uint256[] memory amounts) { lockedAddresses = addressList; + blsAddresses = new bytes20[](addressList.length); 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; + blsAddresses[i] = locked[lockedAddresses[i]]._blsAddress; lockPeriodCounts[i] = locked[lockedAddresses[i]]._lockPeriodCount; amounts[i] = locked[lockedAddresses[i]]._amount; } diff --git a/node/contract.go b/node/contract.go index 46e35771e..2edc1bd15 100644 --- a/node/contract.go +++ b/node/contract.go @@ -59,7 +59,7 @@ func (node *Node) generateDeployedStakingContractAddress(contractAddress common. } // QueryStakeInfo queries the stake info from the stake contract. -func (node *Node) QueryStakeInfo() *StakeInfo { +func (node *Node) QueryStakeInfo() *StakeInfoReturnValue { abi, err := abi.JSON(strings.NewReader(contracts.StakeLockContractABI)) if err != nil { utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) @@ -96,7 +96,7 @@ func (node *Node) QueryStakeInfo() *StakeInfo { return nil } - ret := &StakeInfo{} + ret := &StakeInfoReturnValue{} err = abi.Unpack(ret, "listLockedAddresses", output) diff --git a/node/node.go b/node/node.go index 2a7c6a976..61b2089c0 100644 --- a/node/node.go +++ b/node/node.go @@ -5,7 +5,6 @@ import ( "crypto/ecdsa" "encoding/binary" "fmt" - "math/big" "os" "sync" "time" @@ -138,7 +137,7 @@ type Node struct { serviceManager *service.Manager //Staked Accounts and Contract - CurrentStakes map[common.Address]*big.Int //This will save the latest information about staked nodes. + CurrentStakes map[common.Address]*StakeInfo //This will save the latest information about staked nodes. StakingContractAddress common.Address WithdrawStakeFunc []byte @@ -252,7 +251,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]*big.Int) + node.CurrentStakes = make(map[common.Address]*StakeInfo) node.AddStakingContractToPendingTransactions() //This will save the latest information about staked nodes in current staked } diff --git a/node/service_setup.go b/node/service_setup.go index 0943a8a1a..4f9367428 100644 --- a/node/service_setup.go +++ b/node/service_setup.go @@ -79,7 +79,7 @@ func (node *Node) setupForNewNode() { nodeConfig, chanPeer := node.initNodeConfiguration() // Register staking service. - node.serviceManager.RegisterService(service.Staking, staking.New(node.host, node.AccountKey, node.beaconChain)) + node.serviceManager.RegisterService(service.Staking, staking.New(node.host, node.AccountKey, node.beaconChain, node.NodeConfig.ConsensusPubKey.GetAddress())) // Register peer discovery service. "0" is the beacon shard ID node.serviceManager.RegisterService(service.PeerDiscovery, discovery.New(node.host, nodeConfig, chanPeer, node.AddBeaconPeer)) // Register networkinfo service. "0" is the beacon shard ID diff --git a/node/staking.go b/node/staking.go index 424c85b34..a609f689d 100644 --- a/node/staking.go +++ b/node/staking.go @@ -24,22 +24,30 @@ const ( lockPeriodInEpochs = 3 // This should be in sync with contracts/StakeLockContract.sol ) -// StakeInfo is the struct for the return value of listLockedAddresses func in stake contract. -type StakeInfo struct { +// StakeInfoReturnValue is the struct for the return value of listLockedAddresses func in stake contract. +type StakeInfoReturnValue struct { LockedAddresses []common.Address + BlsAddresses [][20]byte BlockNums []*big.Int LockPeriodCounts []*big.Int // The number of locking period the token will be locked. Amounts []*big.Int } +// StakeInfo stores the staking information for a staker. +type StakeInfo struct { + BlsAddress [20]byte + BlockNum *big.Int + LockPeriodCount *big.Int // The number of locking period the token will be locked. + Amount *big.Int +} + // 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] +func (node *Node) UpdateStakingList(stakeInfoReturnValue *StakeInfoReturnValue) { + node.CurrentStakes = make(map[common.Address]*StakeInfo) + if stakeInfoReturnValue != nil { + for i, addr := range stakeInfoReturnValue.LockedAddresses { + blockNum := stakeInfoReturnValue.BlockNums[i] + lockPeriodCount := stakeInfoReturnValue.LockPeriodCounts[i] startEpoch := core.GetEpochFromBlockNumber(blockNum.Uint64()) curEpoch := core.GetEpochFromBlockNumber(node.blockchain.CurrentBlock().NumberU64()) @@ -48,7 +56,12 @@ func (node *Node) UpdateStakingList(stakeInfo *StakeInfo) { continue // The token are counted into stakes at the beginning of next epoch. } if curEpoch-startEpoch <= lockPeriodCount.Uint64()*lockPeriodInEpochs { - node.CurrentStakes[addr] = amount + node.CurrentStakes[addr] = &StakeInfo{ + stakeInfoReturnValue.BlsAddresses[i], + blockNum, + lockPeriodCount, + stakeInfoReturnValue.Amounts[i], + } } } } @@ -57,8 +70,8 @@ func (node *Node) UpdateStakingList(stakeInfo *StakeInfo) { func (node *Node) printStakingList() { utils.GetLogInstance().Info("\n") utils.GetLogInstance().Info("CURRENT STAKING INFO [START] ------------------------------------") - for addr, stake := range node.CurrentStakes { - utils.GetLogInstance().Info("", "Address", addr, "Stake", stake) + for addr, stakeInfo := range node.CurrentStakes { + utils.GetLogInstance().Info("", "Address", addr, "StakeInfo", stakeInfo) } utils.GetLogInstance().Info("CURRENT STAKING INFO [END} ------------------------------------") utils.GetLogInstance().Info("\n") diff --git a/node/staking_test.go b/node/staking_test.go index 3cf01ca21..f23446109 100644 --- a/node/staking_test.go +++ b/node/staking_test.go @@ -16,6 +16,7 @@ var ( blockNum = big.NewInt(15000) lockPeriodCount = big.NewInt(1) testAddress = common.Address{123} + testBlsAddress = common.Address{132}.Bytes() // [20]byte ) func TestUpdateStakingList(t *testing.T) { @@ -39,8 +40,9 @@ func TestUpdateStakingList(t *testing.T) { node.AddNewBlock(block) } - stakeInfo := &StakeInfo{ + stakeInfo := &StakeInfoReturnValue{ []common.Address{testAddress}, + [][20]byte{testAddress}, []*big.Int{blockNum}, []*big.Int{lockPeriodCount}, []*big.Int{amount}, @@ -48,7 +50,7 @@ func TestUpdateStakingList(t *testing.T) { node.UpdateStakingList(stakeInfo) - if node.CurrentStakes[testAddress].Cmp(amount) != 0 { + if node.CurrentStakes[testAddress].Amount.Cmp(amount) != 0 { t.Error("Stake Info is not updated correctly") } }