From 6044b76068bc7ba975a81f9ee188832fc9e43b3c Mon Sep 17 00:00:00 2001 From: Rongjian Lan Date: Thu, 28 Mar 2019 11:24:03 -0700 Subject: [PATCH] migrate bls identity from address to public key Use shard info for committee pub keys rather than pong message Make code backward compatible --- api/proto/discovery/pingpong.go | 1 - api/service/consensus/service.go | 1 + consensus/consensus.go | 54 +++++++++++++------ consensus/consensus_leader.go | 32 +++++------ consensus/consensus_leader_msg_test.go | 6 ++- consensus/consensus_test.go | 4 +- consensus/consensus_validator.go | 2 +- contracts/Lottery.go | 22 ++++++-- contracts/StakeLockContract.go | 50 +++++++++-------- contracts/StakeLockContract.sol | 28 ++++++---- contracts/gen.sh | 2 +- contracts/structs/structs.go | 8 ++- core/blockchain.go | 8 +-- core/resharding.go | 30 +++-------- core/resharding_test.go | 74 ++++++++++++++++++-------- core/types/shard_state.go | 17 ++++-- core/types/shard_state_test.go | 66 +++++++++++++++-------- drand/drand.go | 39 ++++++++++---- drand/drand_leader.go | 16 +++--- internal/utils/utils.go | 6 +-- internal/utils/utils_test.go | 6 +-- node/node.go | 26 ++++++++- node/node_handler.go | 31 ++++++----- node/node_newblock.go | 1 + node/service_setup.go | 4 +- node/staking.go | 8 ++- node/staking_test.go | 8 ++- 27 files changed, 356 insertions(+), 194 deletions(-) diff --git a/api/proto/discovery/pingpong.go b/api/proto/discovery/pingpong.go index ccebd4fc2..ed73de499 100644 --- a/api/proto/discovery/pingpong.go +++ b/api/proto/discovery/pingpong.go @@ -95,7 +95,6 @@ func NewPongMessage(peers []p2p.Peer, pubKeys []*bls.PublicKey, leaderKey *bls.P } pong.LeaderPubKey = leaderKey.Serialize() - // utils.GetLogInstance().Info("[NewPongMessage]", "keys", len(pong.PubKeys), "peers", len(pong.Peers), "leaderPubKey", utils.GetAddressHex(leaderKey)) return pong } diff --git a/api/service/consensus/service.go b/api/service/consensus/service.go index 6754bbd7b..6bb31cd5c 100644 --- a/api/service/consensus/service.go +++ b/api/service/consensus/service.go @@ -24,6 +24,7 @@ func New(blockChannel chan *types.Block, consensus *consensus.Consensus, startCh // StartService starts consensus service. func (s *Service) StartService() { + utils.GetLogInstance().Info("Starting consensus service.") s.stopChan = make(chan struct{}) s.stoppedChan = make(chan struct{}) s.consensus.WaitForNewBlock(s.blockChannel, s.stopChan, s.stoppedChan, s.startChan) diff --git a/consensus/consensus.go b/consensus/consensus.go index 5d4cca2fd..5e9efb82c 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -33,8 +33,8 @@ type Consensus struct { state State // Commits collected from validators. - prepareSigs map[string]*bls.Sign // key is the validator's address - commitSigs map[string]*bls.Sign // key is the validator's address + prepareSigs map[common.Address]*bls.Sign // key is the validator's address + commitSigs map[common.Address]*bls.Sign // key is the validator's address aggregatedPrepareSig *bls.Sign aggregatedCommitSig *bls.Sign prepareBitmap *bls_cosi.Mask @@ -55,8 +55,9 @@ type Consensus struct { // Public keys of the committee including leader and validators PublicKeys []*bls.PublicKey - - pubKeyLock sync.Mutex + // The addresses of my committee + CommitteeAddresses map[common.Address]bool + pubKeyLock sync.Mutex // private/public keys of current node priKey *bls.SecretKey @@ -65,7 +66,7 @@ type Consensus struct { // Whether I am leader. False means I am validator IsLeader bool // Leader or validator address in hex - SelfAddress string + SelfAddress common.Address // Consensus Id (View Id) - 4 byte consensusID uint32 // Blockhash - 32 byte @@ -167,12 +168,15 @@ func New(host p2p.Host, ShardID uint32, peers []p2p.Peer, leader p2p.Peer, blsPr } consensus.leader = leader + consensus.CommitteeAddresses = map[common.Address]bool{} for _, peer := range peers { - consensus.validators.Store(utils.GetAddressHex(peer.ConsensusPubKey), peer) + consensus.validators.Store(utils.GetBlsAddress(peer.ConsensusPubKey).Hex(), peer) + + consensus.CommitteeAddresses[utils.GetBlsAddress(peer.ConsensusPubKey)] = true } - consensus.prepareSigs = map[string]*bls.Sign{} - consensus.commitSigs = map[string]*bls.Sign{} + consensus.prepareSigs = map[common.Address]*bls.Sign{} + consensus.commitSigs = map[common.Address]*bls.Sign{} // Initialize cosign bitmap allPublicKeys := make([]*bls.PublicKey, 0) @@ -193,7 +197,7 @@ func New(host p2p.Host, ShardID uint32, peers []p2p.Peer, leader p2p.Peer, blsPr // For now use socket address as ID // TODO: populate Id derived from address - consensus.SelfAddress = utils.GetAddressHex(selfPeer.ConsensusPubKey) + consensus.SelfAddress = utils.GetBlsAddress(selfPeer.ConsensusPubKey) if blsPriKey != nil { consensus.priKey = blsPriKey @@ -276,6 +280,7 @@ func (consensus *Consensus) ToggleConsensusCheck() { } // GetPeerByAddress the validator peer based on validator Address. +// TODO: deprecate this, as validators network info shouldn't known to everyone func (consensus *Consensus) GetPeerByAddress(validatorAddress string) *p2p.Peer { v, ok := consensus.validators.Load(validatorAddress) if !ok { @@ -290,6 +295,12 @@ func (consensus *Consensus) GetPeerByAddress(validatorAddress string) *p2p.Peer return &value } +// IsValidatorInCommittee returns whether the given validator BLS address is part of my committee +func (consensus *Consensus) IsValidatorInCommittee(validatorBlsAddress common.Address) bool { + _, ok := consensus.CommitteeAddresses[validatorBlsAddress] + return ok +} + // Verify the signature of the message are valid from the signer's public key. func verifyMessageSig(signerPubKey *bls.PublicKey, message *msg_pb.Message) error { signature := message.Signature @@ -374,8 +385,8 @@ func (consensus *Consensus) GetCommitSigsArray() []*bls.Sign { // ResetState resets the state of the consensus func (consensus *Consensus) ResetState() { consensus.state = Finished - consensus.prepareSigs = map[string]*bls.Sign{} - consensus.commitSigs = map[string]*bls.Sign{} + consensus.prepareSigs = map[common.Address]*bls.Sign{} + consensus.commitSigs = map[common.Address]*bls.Sign{} prepareBitmap, _ := bls_cosi.NewMask(consensus.PublicKeys, consensus.leader.ConsensusPubKey) commitBitmap, _ := bls_cosi.NewMask(consensus.PublicKeys, consensus.leader.ConsensusPubKey) @@ -407,10 +418,13 @@ func (consensus *Consensus) AddPeers(peers []*p2p.Peer) int { count := 0 for _, peer := range peers { - _, ok := consensus.validators.LoadOrStore(utils.GetAddressHex(peer.ConsensusPubKey), *peer) + _, ok := consensus.validators.LoadOrStore(utils.GetBlsAddress(peer.ConsensusPubKey).Hex(), *peer) if !ok { consensus.pubKeyLock.Lock() - consensus.PublicKeys = append(consensus.PublicKeys, peer.ConsensusPubKey) + if _, ok := consensus.CommitteeAddresses[peer.ConsensusPubKey.GetAddress()]; !ok { + consensus.PublicKeys = append(consensus.PublicKeys, peer.ConsensusPubKey) + consensus.CommitteeAddresses[peer.ConsensusPubKey.GetAddress()] = true + } consensus.pubKeyLock.Unlock() } count++ @@ -486,7 +500,7 @@ func (consensus *Consensus) DebugPrintValidators() { consensus.validators.Range(func(k, v interface{}) bool { if p, ok := v.(p2p.Peer); ok { str2 := fmt.Sprintf("%s", p.ConsensusPubKey.Serialize()) - utils.GetLogInstance().Debug("validator:", "IP", p.IP, "Port", p.Port, "address", utils.GetAddressHex(p.ConsensusPubKey), "Key", str2) + utils.GetLogInstance().Debug("validator:", "IP", p.IP, "Port", p.Port, "address", utils.GetBlsAddress(p.ConsensusPubKey), "Key", str2) count++ return true } @@ -499,6 +513,12 @@ func (consensus *Consensus) DebugPrintValidators() { func (consensus *Consensus) UpdatePublicKeys(pubKeys []*bls.PublicKey) int { consensus.pubKeyLock.Lock() consensus.PublicKeys = append(pubKeys[:0:0], pubKeys...) + consensus.CommitteeAddresses = map[common.Address]bool{} + for _, pubKey := range consensus.PublicKeys { + consensus.CommitteeAddresses[utils.GetBlsAddress(pubKey)] = true + } + // TODO: use pubkey to identify leader rather than p2p.Peer. + consensus.leader = p2p.Peer{ConsensusPubKey: pubKeys[0]} consensus.pubKeyLock.Unlock() return len(consensus.PublicKeys) @@ -593,7 +613,7 @@ func accumulateRewards(config *params.ChainConfig, state *state.DB, header *type } // GetSelfAddress returns the address in hex -func (consensus *Consensus) GetSelfAddress() string { +func (consensus *Consensus) GetSelfAddress() common.Address { return consensus.SelfAddress } @@ -637,8 +657,8 @@ func (consensus *Consensus) GetLeaderPubKey() *bls.PublicKey { return consensus.leader.ConsensusPubKey } -// GetNumPeers returns the length of PublicKeys -func (consensus *Consensus) GetNumPeers() int { +// GetNumValidators returns the length of PublicKeys +func (consensus *Consensus) GetNumValidators() int { return len(consensus.PublicKeys) } diff --git a/consensus/consensus_leader.go b/consensus/consensus_leader.go index 79c965e60..ffc3b4ced 100644 --- a/consensus/consensus_leader.go +++ b/consensus/consensus_leader.go @@ -147,13 +147,13 @@ func (consensus *Consensus) startConsensus(newBlock *types.Block) { func (consensus *Consensus) processPrepareMessage(message *msg_pb.Message) { consensusMsg := message.GetConsensus() - pubKey, err := bls_cosi.BytesToBlsPublicKey(consensusMsg.SenderPubkey) + validatorPubKey, err := bls_cosi.BytesToBlsPublicKey(consensusMsg.SenderPubkey) if err != nil { utils.GetLogInstance().Debug("Failed to deserialize BLS public key", "error", err) return } - addrBytes := pubKey.GetAddress() - validatorAddress := common.BytesToAddress(addrBytes[:]).Hex() + addrBytes := validatorPubKey.GetAddress() + validatorAddress := common.BytesToAddress(addrBytes[:]) prepareSig := consensusMsg.Payload @@ -163,14 +163,12 @@ func (consensus *Consensus) processPrepareMessage(message *msg_pb.Message) { consensus.mutex.Lock() defer consensus.mutex.Unlock() - validatorPeer := consensus.GetPeerByAddress(validatorAddress) - - if validatorPeer == nil { + if !consensus.IsValidatorInCommittee(validatorAddress) { utils.GetLogInstance().Error("Invalid validator", "validatorAddress", validatorAddress) return } - if err := consensus.checkConsensusMessage(message, validatorPeer.ConsensusPubKey); err != nil { + if err := consensus.checkConsensusMessage(message, validatorPubKey); err != nil { utils.GetLogInstance().Debug("Failed to check the validator message", "error", err, "validatorAddress", validatorAddress) return } @@ -195,14 +193,14 @@ func (consensus *Consensus) processPrepareMessage(message *msg_pb.Message) { return } - if !sign.VerifyHash(validatorPeer.ConsensusPubKey, consensus.blockHash[:]) { + if !sign.VerifyHash(validatorPubKey, consensus.blockHash[:]) { utils.GetLogInstance().Error("Received invalid BLS signature", "validatorAddress", validatorAddress) return } utils.GetLogInstance().Debug("Received new prepare signature", "numReceivedSoFar", len(prepareSigs), "validatorAddress", validatorAddress, "PublicKeys", len(consensus.PublicKeys)) prepareSigs[validatorAddress] = &sign - prepareBitmap.SetKey(validatorPeer.ConsensusPubKey, true) // Set the bitmap indicating that this validator signed. + prepareBitmap.SetKey(validatorPubKey, true) // Set the bitmap indicating that this validator signed. targetState := PreparedDone if len(prepareSigs) >= ((len(consensus.PublicKeys)*2)/3+1) && consensus.state < targetState { @@ -228,27 +226,25 @@ func (consensus *Consensus) processPrepareMessage(message *msg_pb.Message) { func (consensus *Consensus) processCommitMessage(message *msg_pb.Message) { consensusMsg := message.GetConsensus() - pubKey, err := bls_cosi.BytesToBlsPublicKey(consensusMsg.SenderPubkey) + validatorPubKey, err := bls_cosi.BytesToBlsPublicKey(consensusMsg.SenderPubkey) if err != nil { utils.GetLogInstance().Debug("Failed to deserialize BLS public key", "error", err) return } - addrBytes := pubKey.GetAddress() - validatorAddress := common.BytesToAddress(addrBytes[:]).Hex() + addrBytes := validatorPubKey.GetAddress() + validatorAddress := common.BytesToAddress(addrBytes[:]) commitSig := consensusMsg.Payload consensus.mutex.Lock() defer consensus.mutex.Unlock() - validatorPeer := consensus.GetPeerByAddress(validatorAddress) - - if validatorPeer == nil { + if !consensus.IsValidatorInCommittee(validatorAddress) { utils.GetLogInstance().Error("Invalid validator", "validatorAddress", validatorAddress) return } - if err := consensus.checkConsensusMessage(message, validatorPeer.ConsensusPubKey); err != nil { + if err := consensus.checkConsensusMessage(message, validatorPubKey); err != nil { utils.GetLogInstance().Debug("Failed to check the validator message", "validatorAddress", validatorAddress) return } @@ -276,7 +272,7 @@ func (consensus *Consensus) processCommitMessage(message *msg_pb.Message) { return } aggSig := bls_cosi.AggregateSig(consensus.GetPrepareSigsArray()) - if !sign.VerifyHash(validatorPeer.ConsensusPubKey, append(aggSig.Serialize(), consensus.prepareBitmap.Bitmap...)) { + if !sign.VerifyHash(validatorPubKey, append(aggSig.Serialize(), consensus.prepareBitmap.Bitmap...)) { utils.GetLogInstance().Error("Received invalid BLS signature", "validatorAddress", validatorAddress) return } @@ -284,7 +280,7 @@ func (consensus *Consensus) processCommitMessage(message *msg_pb.Message) { utils.GetLogInstance().Debug("Received new commit message", "numReceivedSoFar", len(commitSigs), "validatorAddress", validatorAddress) commitSigs[validatorAddress] = &sign // Set the bitmap indicating that this validator signed. - commitBitmap.SetKey(validatorPeer.ConsensusPubKey, true) + commitBitmap.SetKey(validatorPubKey, true) targetState := CommittedDone if len(commitSigs) >= ((len(consensus.PublicKeys)*2)/3+1) && consensus.state != targetState { diff --git a/consensus/consensus_leader_msg_test.go b/consensus/consensus_leader_msg_test.go index b093a2c20..ef3217ba6 100644 --- a/consensus/consensus_leader_msg_test.go +++ b/consensus/consensus_leader_msg_test.go @@ -3,6 +3,8 @@ package consensus import ( "testing" + "github.com/ethereum/go-ethereum/common" + "github.com/harmony-one/harmony/crypto/bls" protobuf "github.com/golang/protobuf/proto" @@ -53,8 +55,8 @@ func TestConstructPreparedMessage(test *testing.T) { consensus.blockHash = [32]byte{} message := "test string" - consensus.prepareSigs["0"] = leaderPriKey.Sign(message) - consensus.prepareSigs["1"] = validatorPriKey.Sign(message) + consensus.prepareSigs[common.Address{}] = leaderPriKey.Sign(message) + consensus.prepareSigs[common.Address{}] = validatorPriKey.Sign(message) consensus.prepareBitmap.SetKey(leaderPubKey, true) consensus.prepareBitmap.SetKey(validatorPubKey, true) diff --git a/consensus/consensus_test.go b/consensus/consensus_test.go index 8b53fd810..1cc9dda6c 100644 --- a/consensus/consensus_test.go +++ b/consensus/consensus_test.go @@ -4,6 +4,8 @@ import ( "bytes" "testing" + "github.com/ethereum/go-ethereum/common" + "github.com/harmony-one/harmony/crypto/bls" msg_pb "github.com/harmony-one/harmony/api/proto/message" @@ -133,7 +135,7 @@ func TestSignAndMarshalConsensusMessage(t *testing.T) { consensus := New(host, 0, []p2p.Peer{leader, validator}, leader, bls.RandPrivateKey()) consensus.consensusID = 2 consensus.blockHash = blockHash - consensus.SelfAddress = "fake address" + consensus.SelfAddress = common.Address{} msg := &msg_pb.Message{} marshaledMessage, err := consensus.signAndMarshalConsensusMessage(msg) diff --git a/consensus/consensus_validator.go b/consensus/consensus_validator.go index 3763b9f34..c5614a940 100644 --- a/consensus/consensus_validator.go +++ b/consensus/consensus_validator.go @@ -68,7 +68,7 @@ func (consensus *Consensus) processAnnounceMessage(message *msg_pb.Message) { consensus.block = block if err := consensus.checkConsensusMessage(message, consensus.leader.ConsensusPubKey); err != nil { - utils.GetLogInstance().Debug("Failed to check the leader message", "key", utils.GetAddressHex(consensus.leader.ConsensusPubKey)) + utils.GetLogInstance().Debug("Failed to check the leader message", "key", utils.GetBlsAddress(consensus.leader.ConsensusPubKey)) return } diff --git a/contracts/Lottery.go b/contracts/Lottery.go index c48b4ec3b..8df9fee99 100644 --- a/contracts/Lottery.go +++ b/contracts/Lottery.go @@ -7,17 +7,31 @@ 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 ) // LotteryABI is the input ABI used to generate the binding from. const LotteryABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pickWinner\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getPlayers\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"enter\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"players\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]" // LotteryBin is the compiled bytecode used for deploying new contracts. -const LotteryBin = `0x608060405234801561001057600080fd5b5060008054600160a060020a03191633179055610568806100326000396000f3fe608060405260043610610066577c01000000000000000000000000000000000000000000000000000000006000350463481c6a75811461006b5780635d495aea1461009c5780638b5b9ccc146100a6578063e97dcb621461010b578063f71d96cb14610113575b600080fd5b34801561007757600080fd5b5061008061013d565b60408051600160a060020a039092168252519081900360200190f35b6100a461014c565b005b3480156100b257600080fd5b506100bb6102bf565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156100f75781810151838201526020016100df565b505050509050019250505060405180910390f35b6100a4610322565b34801561011f57600080fd5b506100806004803603602081101561013657600080fd5b5035610401565b600054600160a060020a031681565b60005460408051808201909152601381527f4f6e6c79206d616e616765722063616e20646f00000000000000000000000000602082015290600160a060020a03163314610231576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156101f65781810151838201526020016101de565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600154600090610240610429565b81151561024957fe5b06905060018181548110151561025b57fe5b6000918252602082200154604051600160a060020a0390911691303180156108fc02929091818181858888f1935050505015801561029d573d6000803e3d6000fd5b5060408051600081526020810191829052516102bb9160019161046d565b5050565b6060600180548060200260200160405190810160405280929190818152602001828054801561031757602002820191906000526020600020905b8154600160a060020a031681526001909101906020018083116102f9575b505050505090505b90565b67016345785d8a00003411606060405190810160405280602c8152602001610511602c91399015156103b0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382528381815181526020019150805190602001908083836000838110156101f65781810151838201526020016101de565b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601805473ffffffffffffffffffffffffffffffffffffffff191633179055565b600180548290811061040f57fe5b600091825260209091200154600160a060020a0316905081565b60408051426020808301919091526c010000000000000000000000003381028385015230026054830152825160488184030181526068909201909252805191012090565b8280548282559060005260206000209081019282156104cf579160200282015b828111156104cf578251825473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0390911617825560209092019160019091019061048d565b506104db9291506104df565b5090565b61031f91905b808211156104db57805473ffffffffffffffffffffffffffffffffffffffff191681556001016104e556fe54686520706c61796572206e6565647320746f207374616b65206174206c6561737420302e31206574686572a165627a7a72305820e9e057dfabaa0039b2b5c5a3eb3065c7a3058e47b289028b599918412f018e830029` +const LotteryBin = `0x608060405234801561001057600080fd5b50600080546001600160a01b031916331790556104ec806100326000396000f3fe60806040526004361061004a5760003560e01c8063481c6a751461004f5780635d495aea146100805780638b5b9ccc1461008a578063e97dcb62146100ef578063f71d96cb146100f7575b600080fd5b34801561005b57600080fd5b50610064610121565b604080516001600160a01b039092168252519081900360200190f35b610088610130565b005b34801561009657600080fd5b5061009f61028c565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156100db5781810151838201526020016100c3565b505050509050019250505060405180910390f35b6100886102ef565b34801561010357600080fd5b506100646004803603602081101561011a57600080fd5b50356103a9565b6000546001600160a01b031681565b60005460408051808201909152601381527f4f6e6c79206d616e616765722063616e20646f000000000000000000000000006020820152906001600160a01b031633146101fe57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b838110156101c35781810151838201526020016101ab565b50505050905090810190601f1680156101f05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060015460009061020d6103d1565b81151561021657fe5b06905060018181548110151561022857fe5b60009182526020822001546040516001600160a01b0390911691303180156108fc02929091818181858888f1935050505015801561026a573d6000803e3d6000fd5b5060408051600081526020810191829052516102889160019161040b565b5050565b606060018054806020026020016040519081016040528092919081815260200182805480156102e457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116102c6575b505050505090505b90565b67016345785d8a000034116040518060600160405280602c8152602001610495602c913990151561036557604051600160e51b62461bcd028152600401808060200182810382528381815181526020019150805190602001908083836000838110156101c35781810151838201526020016101ab565b506001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b03191633179055565b60018054829081106103b757fe5b6000918252602090912001546001600160a01b0316905081565b604080514260208083019190915233606090811b8385015230901b6054830152825160488184030181526068909201909252805191012090565b828054828255906000526020600020908101928215610460579160200282015b8281111561046057825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061042b565b5061046c929150610470565b5090565b6102ec91905b8082111561046c5780546001600160a01b031916815560010161047656fe54686520706c61796572206e6565647320746f207374616b65206174206c6561737420302e31206574686572a165627a7a72305820159638f94fdba6b1dc61d4071f6673028ee53a12a39d66f7ec00701aed93a0b60029` // DeployLottery deploys a new Ethereum contract, binding an instance of Lottery to it. func DeployLottery(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Lottery, error) { @@ -228,7 +242,7 @@ func (_Lottery *LotteryCallerSession) Manager() (common.Address, error) { // Players is a free data retrieval call binding the contract method 0xf71d96cb. // -// Solidity: function players( uint256) constant returns(address) +// Solidity: function players(uint256 ) constant returns(address) func (_Lottery *LotteryCaller) Players(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) { var ( ret0 = new(common.Address) @@ -240,14 +254,14 @@ func (_Lottery *LotteryCaller) Players(opts *bind.CallOpts, arg0 *big.Int) (comm // Players is a free data retrieval call binding the contract method 0xf71d96cb. // -// Solidity: function players( uint256) constant returns(address) +// Solidity: function players(uint256 ) constant returns(address) func (_Lottery *LotterySession) Players(arg0 *big.Int) (common.Address, error) { return _Lottery.Contract.Players(&_Lottery.CallOpts, arg0) } // Players is a free data retrieval call binding the contract method 0xf71d96cb. // -// Solidity: function players( uint256) constant returns(address) +// Solidity: function players(uint256 ) constant returns(address) func (_Lottery *LotteryCallerSession) Players(arg0 *big.Int) (common.Address, error) { return _Lottery.Contract.Players(&_Lottery.CallOpts, arg0) } diff --git a/contracts/StakeLockContract.go b/contracts/StakeLockContract.go index 641085cb6..8f689a75d 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\":\"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\"}]" +const StakeLockContractABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"listLockedAddresses\",\"outputs\":[{\"name\":\"lockedAddresses\",\"type\":\"address[]\"},{\"name\":\"blsPubicKeys1\",\"type\":\"bytes32[]\"},{\"name\":\"blsPubicKeys2\",\"type\":\"bytes32[]\"},{\"name\":\"blsPubicKeys3\",\"type\":\"bytes32[]\"},{\"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\":\"_blsPublicKey1\",\"type\":\"bytes32\"},{\"name\":\"_blsPublicKey2\",\"type\":\"bytes32\"},{\"name\":\"_blsPublicKey3\",\"type\":\"bytes32\"}],\"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 = `0x6080604052600560005534801561001557600080fd5b50610b21806100256000396000f3fe6080604052600436106100555760003560e01c806363b125151461005a57806370a08231146101d7578063766718081461021c5780639de746a514610231578063a69df4b51461026c578063ab4a2eb314610281575b600080fd5b34801561006657600080fd5b5061006f6102b4565b60405180806020018060200180602001806020018060200186810386528b818151815260200191508051906020019060200280838360005b838110156100bf5781810151838201526020016100a7565b5050505090500186810385528a818151815260200191508051906020019060200280838360005b838110156100fe5781810151838201526020016100e6565b50505050905001868103845289818151815260200191508051906020019060200280838360005b8381101561013d578181015183820152602001610125565b50505050905001868103835288818151815260200191508051906020019060200280838360005b8381101561017c578181015183820152602001610164565b50505050905001868103825287818151815260200191508051906020019060200280838360005b838110156101bb5781810151838201526020016101a3565b505050509050019a505050505050505050505060405180910390f35b3480156101e357600080fd5b5061020a600480360360208110156101fa57600080fd5b50356001600160a01b031661055c565b60408051918252519081900360200190f35b34801561022857600080fd5b5061020a610577565b6102586004803603602081101561024757600080fd5b50356001600160601b03191661058c565b604080519115158252519081900360200190f35b34801561027857600080fd5b5061020a610890565b34801561028d57600080fd5b5061020a600480360360208110156102a457600080fd5b50356001600160a01b0316610a51565b6060806060806060600380548060200260200160405190810160405280929190818152602001828054801561031257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116102f4575b50505050509450600380549050604051908082528060200260200182016040528015610348578160200160208202803883390190505b506003546040805182815260208084028201019091529195508015610377578160200160208202803883390190505b5060035460408051828152602080840282010190915291945080156103a6578160200160208202803883390190505b5060035460408051828152602080840282010190915291935080156103d5578160200160208202803883390190505b50905060005b8551811015610554576001600087838151811015156103f657fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060010154848281518110151561043257fe5b60209081029091010152855160019060009088908490811061045057fe5b60209081029091018101516001600160a01b0316825281019190915260400160002060050154855160609190911b9086908390811061048b57fe5b6001600160601b031990921660209283029091019091015285516001906000908890849081106104b757fe5b906020019060200201516001600160a01b03166001600160a01b031681526020019081526020016000206003015483828151811015156104f357fe5b60209081029091010152855160019060009088908490811061051157fe5b60209081029091018101516001600160a01b0316825281019190915260400160002054825183908390811061054257fe5b602090810290910101526001016103db565b509091929394565b6001600160a01b031660009081526001602052604090205490565b600080544381151561058557fe5b0490505b90565b60408051808201909152601f81527f424c5320616464726573732073686f756c64206e6f7420626520656d7074790060208201526000906001600160601b03198316151561065b57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610620578181015183820152602001610608565b50505050905090810190601f16801561064d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506106653361055c565b60408051808201909152601581527f546f6b656e7320616c7265616479206c6f636b65640000000000000000000000602082015290156106ea57604051600160e51b62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610620578181015183820152602001610608565b5060408051808201909152601381527f416d6f756e742063616e206e6f74206265203000000000000000000000000000602082015234151561077157604051600160e51b62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610620578181015183820152602001610608565b506040518060c00160405280348152602001438152602001610791610577565b8152600160208083018290526003805480840182557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810180546001600160a01b0319908116339081179092556040808801939093526001600160601b03198a16606097880152600082815286865283902088518155948801519585019590955590860151600284015585850151918301919091556080850151600483015560a090940151600590910180549190931c91161790557fd4665e3049283582ba6f9eba07a5b3e12dab49e02da99e8927a47af5d134bea534610870610577565b6040805192835260208301919091528051918290030190a2506001919050565b600061089b33610a51565b60408051808201909152601481527f4e6f20746f6b656e7320756e6c6f636b61626c65000000000000000000000000602082015290915081151561092457604051600160e51b62461bcd02815260040180806020018281038252838181518152602001915080519060200190808383600083811015610620578181015183820152602001610608565b50336000908152600160208190526040822060048101805484835592820184905560028201849055600380830185905593905560050180546001600160a01b03191690558154909190600019810190811061097b57fe5b600091825260209091200154600380546001600160a01b0390921691839081106109a157fe5b6000918252602082200180546001600160a01b0319166001600160a01b039390931692909217909155600380548392600192909160001981019081106109e357fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020600401556003805490610a1e906000198301610aae565b50604051339083156108fc029084906000818181858888f19350505050158015610a4c573d6000803e3d6000fd5b505090565b600080610a5c610577565b6001600160a01b03841660009081526001602052604090206003818101546002909201549293500201811115610aa8576001600160a01b03831660009081526001602052604090205491505b50919050565b815481835581811115610ad257600083815260209020610ad2918101908301610ad7565b505050565b61058991905b80821115610af15760008155600101610add565b509056fea165627a7a72305820de21205eb52d566f7d604e6f7fafe84f5f070db28cf3918cb8a9ab98590b922a0029` +const StakeLockContractBin = `0x6080604052600560005534801561001557600080fd5b50610c3c806100256000396000f3fe6080604052600436106100555760003560e01c806363b125151461005a57806370a082311461026157806376671808146102a6578063872588ba146102bb578063a69df4b5146102f8578063ab4a2eb31461030d575b600080fd5b34801561006657600080fd5b5061006f610340565b604051808060200180602001806020018060200180602001806020018060200188810388528f818151815260200191508051906020019060200280838360005b838110156100c75781810151838201526020016100af565b5050505090500188810387528e818151815260200191508051906020019060200280838360005b838110156101065781810151838201526020016100ee565b5050505090500188810386528d818151815260200191508051906020019060200280838360005b8381101561014557818101518382015260200161012d565b5050505090500188810385528c818151815260200191508051906020019060200280838360005b8381101561018457818101518382015260200161016c565b5050505090500188810384528b818151815260200191508051906020019060200280838360005b838110156101c35781810151838201526020016101ab565b5050505090500188810383528a818151815260200191508051906020019060200280838360005b838110156102025781810151838201526020016101ea565b50505050905001888103825289818151815260200191508051906020019060200280838360005b83811015610241578181015183820152602001610229565b505050509050019e50505050505050505050505050505060405180910390f35b34801561026d57600080fd5b506102946004803603602081101561028457600080fd5b50356001600160a01b03166106f2565b60408051918252519081900360200190f35b3480156102b257600080fd5b5061029461070d565b6102e4600480360360608110156102d157600080fd5b5080359060208101359060400135610722565b604080519115158252519081900360200190f35b34801561030457600080fd5b506102946109a4565b34801561031957600080fd5b506102946004803603602081101561033057600080fd5b50356001600160a01b0316610b6c565b606080606080606080606060038054806020026020016040519081016040528092919081815260200182805480156103a157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610383575b505050505096506003805490506040519080825280602002602001820160405280156103d7578160200160208202803883390190505b506003546040805182815260208084028201019091529197508015610406578160200160208202803883390190505b506003546040805182815260208084028201019091529196508015610435578160200160208202803883390190505b506003546040805182815260208084028201019091529195508015610464578160200160208202803883390190505b506003546040805182815260208084028201019091529194508015610493578160200160208202803883390190505b5060035460408051828152602080840282010190915291935080156104c2578160200160208202803883390190505b50905060005b87518110156106e8576001600089838151811015156104e357fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060010154848281518110151561051f57fe5b6020908102909101015287516001906000908a908490811061053d57fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060050154878281518110151561057957fe5b6020908102909101015287516001906000908a908490811061059757fe5b906020019060200201516001600160a01b03166001600160a01b031681526020019081526020016000206006015486828151811015156105d357fe5b6020908102909101015287516001906000908a90849081106105f157fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060070154858281518110151561062d57fe5b6020908102909101015287516001906000908a908490811061064b57fe5b906020019060200201516001600160a01b03166001600160a01b0316815260200190815260200160002060030154838281518110151561068757fe5b6020908102909101015287516001906000908a90849081106106a557fe5b60209081029091018101516001600160a01b031682528101919091526040016000205482518390839081106106d657fe5b602090810290910101526001016104c8565b5090919293949596565b6001600160a01b031660009081526001602052604090205490565b600080544381151561071b57fe5b0490505b90565b600061072d336106f2565b60408051808201909152601581527f546f6b656e7320616c7265616479206c6f636b65640000000000000000000000602082015290156107ee57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b838110156107b357818101518382015260200161079b565b50505050905090810190601f1680156107e05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060408051808201909152601381527f416d6f756e742063616e206e6f74206265203000000000000000000000000000602082015234151561087557604051600160e51b62461bcd028152600401808060200182810382528381815181526020019150805190602001908083836000838110156107b357818101518382015260200161079b565b5060405180610100016040528034815260200143815260200161089661070d565b8152600160208083018290526003805480840182557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810180546001600160a01b0319163390811790915560408087019290925260608087018c905260808088018c905260a09788018b90526000838152878752849020895181559589015196860196909655918701516002850155908601519183019190915591840151600482015591830151600583015560c0830151600683015560e0909201516007909101557fd4665e3049283582ba6f9eba07a5b3e12dab49e02da99e8927a47af5d134bea53461098261070d565b6040805192835260208301919091528051918290030190a25060019392505050565b60006109af33610b6c565b60408051808201909152601481527f4e6f20746f6b656e7320756e6c6f636b61626c650000000000000000000000006020820152909150811515610a3857604051600160e51b62461bcd028152600401808060200182810382528381815181526020019150805190602001908083836000838110156107b357818101518382015260200161079b565b50336000908152600160208190526040822060048101805484835592820184905560028201849055600380830185905590849055600582018490556006820184905560079091019290925581549091906000198101908110610a9657fe5b600091825260209091200154600380546001600160a01b039092169183908110610abc57fe5b6000918252602082200180546001600160a01b0319166001600160a01b03939093169290921790915560038054839260019290916000198101908110610afe57fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020600401556003805490610b39906000198301610bc9565b50604051339083156108fc029084906000818181858888f19350505050158015610b67573d6000803e3d6000fd5b505090565b600080610b7761070d565b6001600160a01b03841660009081526001602052604090206003818101546002909201549293500201811115610bc3576001600160a01b03831660009081526001602052604090205491505b50919050565b815481835581811115610bed57600083815260209020610bed918101908301610bf2565b505050565b61071f91905b80821115610c0c5760008155600101610bf8565b509056fea165627a7a72305820a5a16a162731a647a892a79ba1d8589b81a9855944e0e2dbced079c0211a8a720029` // 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,17 +268,21 @@ func (_StakeLockContract *StakeLockContractCallerSession) GetUnlockableTokens(_o // ListLockedAddresses is a free data retrieval call binding the contract method 0x63b12515. // -// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, bytes20[] blsAddresses, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) +// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, bytes32[] blsPubicKeys1, bytes32[] blsPubicKeys2, bytes32[] blsPubicKeys3, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) func (_StakeLockContract *StakeLockContractCaller) ListLockedAddresses(opts *bind.CallOpts) (struct { LockedAddresses []common.Address - BlsAddresses [][20]byte + BlsPubicKeys1 [][32]byte + BlsPubicKeys2 [][32]byte + BlsPubicKeys3 [][32]byte BlockNums []*big.Int LockPeriodCounts []*big.Int Amounts []*big.Int }, error) { ret := new(struct { LockedAddresses []common.Address - BlsAddresses [][20]byte + BlsPubicKeys1 [][32]byte + BlsPubicKeys2 [][32]byte + BlsPubicKeys3 [][32]byte BlockNums []*big.Int LockPeriodCounts []*big.Int Amounts []*big.Int @@ -290,10 +294,12 @@ 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, bytes20[] blsAddresses, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) +// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, bytes32[] blsPubicKeys1, bytes32[] blsPubicKeys2, bytes32[] blsPubicKeys3, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) func (_StakeLockContract *StakeLockContractSession) ListLockedAddresses() (struct { LockedAddresses []common.Address - BlsAddresses [][20]byte + BlsPubicKeys1 [][32]byte + BlsPubicKeys2 [][32]byte + BlsPubicKeys3 [][32]byte BlockNums []*big.Int LockPeriodCounts []*big.Int Amounts []*big.Int @@ -303,10 +309,12 @@ func (_StakeLockContract *StakeLockContractSession) ListLockedAddresses() (struc // ListLockedAddresses is a free data retrieval call binding the contract method 0x63b12515. // -// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, bytes20[] blsAddresses, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) +// Solidity: function listLockedAddresses() constant returns(address[] lockedAddresses, bytes32[] blsPubicKeys1, bytes32[] blsPubicKeys2, bytes32[] blsPubicKeys3, uint256[] blockNums, uint256[] lockPeriodCounts, uint256[] amounts) func (_StakeLockContract *StakeLockContractCallerSession) ListLockedAddresses() (struct { LockedAddresses []common.Address - BlsAddresses [][20]byte + BlsPubicKeys1 [][32]byte + BlsPubicKeys2 [][32]byte + BlsPubicKeys3 [][32]byte BlockNums []*big.Int LockPeriodCounts []*big.Int Amounts []*big.Int @@ -314,25 +322,25 @@ func (_StakeLockContract *StakeLockContractCallerSession) ListLockedAddresses() return _StakeLockContract.Contract.ListLockedAddresses(&_StakeLockContract.CallOpts) } -// Lock is a paid mutator transaction binding the contract method 0x9de746a5. +// Lock is a paid mutator transaction binding the contract method 0x872588ba. // -// 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) +// Solidity: function lock(bytes32 _blsPublicKey1, bytes32 _blsPublicKey2, bytes32 _blsPublicKey3) returns(bool) +func (_StakeLockContract *StakeLockContractTransactor) Lock(opts *bind.TransactOpts, _blsPublicKey1 [32]byte, _blsPublicKey2 [32]byte, _blsPublicKey3 [32]byte) (*types.Transaction, error) { + return _StakeLockContract.contract.Transact(opts, "lock", _blsPublicKey1, _blsPublicKey2, _blsPublicKey3) } -// Lock is a paid mutator transaction binding the contract method 0x9de746a5. +// Lock is a paid mutator transaction binding the contract method 0x872588ba. // -// Solidity: function lock(bytes20 _blsAddress) returns(bool) -func (_StakeLockContract *StakeLockContractSession) Lock(_blsAddress [20]byte) (*types.Transaction, error) { - return _StakeLockContract.Contract.Lock(&_StakeLockContract.TransactOpts, _blsAddress) +// Solidity: function lock(bytes32 _blsPublicKey1, bytes32 _blsPublicKey2, bytes32 _blsPublicKey3) returns(bool) +func (_StakeLockContract *StakeLockContractSession) Lock(_blsPublicKey1 [32]byte, _blsPublicKey2 [32]byte, _blsPublicKey3 [32]byte) (*types.Transaction, error) { + return _StakeLockContract.Contract.Lock(&_StakeLockContract.TransactOpts, _blsPublicKey1, _blsPublicKey2, _blsPublicKey3) } -// Lock is a paid mutator transaction binding the contract method 0x9de746a5. +// Lock is a paid mutator transaction binding the contract method 0x872588ba. // -// Solidity: function lock(bytes20 _blsAddress) returns(bool) -func (_StakeLockContract *StakeLockContractTransactorSession) Lock(_blsAddress [20]byte) (*types.Transaction, error) { - return _StakeLockContract.Contract.Lock(&_StakeLockContract.TransactOpts, _blsAddress) +// Solidity: function lock(bytes32 _blsPublicKey1, bytes32 _blsPublicKey2, bytes32 _blsPublicKey3) returns(bool) +func (_StakeLockContract *StakeLockContractTransactorSession) Lock(_blsPublicKey1 [32]byte, _blsPublicKey2 [32]byte, _blsPublicKey3 [32]byte) (*types.Transaction, error) { + return _StakeLockContract.Contract.Lock(&_StakeLockContract.TransactOpts, _blsPublicKey1, _blsPublicKey2, _blsPublicKey3) } // Unlock is a paid mutator transaction binding the contract method 0xa69df4b5. diff --git a/contracts/StakeLockContract.sol b/contracts/StakeLockContract.sol index 8ac610280..739bf7e05 100644 --- a/contracts/StakeLockContract.sol +++ b/contracts/StakeLockContract.sol @@ -7,7 +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'; + string internal constant EMPTY_BLS_PUBKEY = 'BLS public key should not be empty'; uint256 internal constant LOCK_PERIOD_IN_EPOCHS = 3; // Final locking period TBD. @@ -22,8 +22,10 @@ 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. + bytes32 _blsPublicKey1; // The BLS public key divided into 3 32bytes chucks used for consensus message signing. + bytes32 _blsPublicKey2; + bytes32 _blsPublicKey3; + // TODO: the BLS public key should be signed by the bls key to prove the ownership. } /** @@ -40,21 +42,23 @@ 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 + * @param _blsPublicKey1 The first part of BLS public key for consensus message signing + * @param _blsPublicKey2 The second part of BLS public key for consensus message signing + * @param _blsPublicKey3 The third part of BLS public key for consensus message signing */ - function lock(bytes20 _blsAddress) + function lock(bytes32 _blsPublicKey1, bytes32 _blsPublicKey2, bytes32 _blsPublicKey3) 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(_blsPublicKey != 0, EMPTY_BLS_PUBKEY); 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, _blsAddress); + locked[msg.sender] = lockedToken(msg.value, block.number, currentEpoch(), 1, addressList.push(msg.sender) - 1, _blsPublicKey1, _blsPublicKey2, _blsPublicKey3); emit Locked(msg.sender, msg.value, currentEpoch()); return true; @@ -123,16 +127,20 @@ contract StakeLockContract { function listLockedAddresses() public view - returns (address[] memory lockedAddresses, bytes20[] memory blsAddresses, uint256[] memory blockNums, uint256[] memory lockPeriodCounts, uint256[] memory amounts) + returns (address[] memory lockedAddresses, bytes32[] memory blsPubicKeys1, bytes32[] memory blsPubicKeys2, bytes32[] memory blsPubicKeys3, uint256[] memory blockNums, uint256[] memory lockPeriodCounts, uint256[] memory amounts) { lockedAddresses = addressList; - blsAddresses = new bytes20[](addressList.length); + blsPubicKeys1 = new bytes32[](addressList.length); + blsPubicKeys2 = new bytes32[](addressList.length); + blsPubicKeys3 = new bytes32[](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; + blsPubicKeys1[i] = locked[lockedAddresses[i]]._blsPublicKey1; + blsPubicKeys2[i] = locked[lockedAddresses[i]]._blsPublicKey2; + blsPubicKeys3[i] = locked[lockedAddresses[i]]._blsPublicKey3; lockPeriodCounts[i] = locked[lockedAddresses[i]]._lockPeriodCount; amounts[i] = locked[lockedAddresses[i]]._amount; } diff --git a/contracts/gen.sh b/contracts/gen.sh index 3c5d52a58..cc7ed0d33 100755 --- a/contracts/gen.sh +++ b/contracts/gen.sh @@ -1,3 +1,3 @@ abigen -sol Lottery.sol -out Lottery.go --pkg contracts # abigen -sol Faucet.sol -out Faucet.go --pkg contracts -# abigen -sol StakeLockContract.sol -out StakeLockContract.go --pkg contracts +abigen -sol StakeLockContract.sol -out StakeLockContract.go --pkg contracts diff --git a/contracts/structs/structs.go b/contracts/structs/structs.go index 273a4391a..4251175b7 100644 --- a/contracts/structs/structs.go +++ b/contracts/structs/structs.go @@ -3,13 +3,17 @@ package structs import ( "math/big" + "github.com/harmony-one/harmony/core/types" + "github.com/ethereum/go-ethereum/common" ) // StakeInfoReturnValue is the struct for the return value of listLockedAddresses func in stake contract. type StakeInfoReturnValue struct { LockedAddresses []common.Address - BlsAddresses [][20]byte + BlsPubicKeys1 [][32]byte + BlsPubicKeys2 [][32]byte + BlsPubicKeys3 [][32]byte BlockNums []*big.Int LockPeriodCounts []*big.Int // The number of locking period the token will be locked. Amounts []*big.Int @@ -17,7 +21,7 @@ type StakeInfoReturnValue struct { // StakeInfo stores the staking information for a staker. type StakeInfo struct { - BlsAddress [20]byte + BlsPublicKey types.BlsPublicKey BlockNum *big.Int LockPeriodCount *big.Int // The number of locking period the token will be locked. Amount *big.Int diff --git a/core/blockchain.go b/core/blockchain.go index c3f43c932..31e4f55c4 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -70,7 +70,7 @@ const ( // BlocksPerEpoch is the number of blocks in one epoch // currently set to small number for testing // in future, this need to be adjusted dynamically instead of constant - BlocksPerEpoch = 10 + BlocksPerEpoch = 5 // BlockChainVersion ensures that an incompatible database forces a resync from scratch. BlockChainVersion = 3 @@ -1740,12 +1740,12 @@ func (bc *BlockChain) StoreNewShardState(block *types.Block, stakeInfo *map[comm hash := block.Hash() number := block.NumberU64() rawdb.WriteShardState(bc.db, hash, number, shardState) - utils.GetLogInstance().Debug("[Resharding] Saved new shard state successfully") + utils.GetLogInstance().Debug("[Resharding] Saved new shard state successfully", "epoch", GetEpochFromBlockNumber(block.NumberU64())) for _, shard := range shardState { - output := shard.Leader.BlsAddress + output := shard.Leader.BlsPublicKey.Hex() output = output + " \n" for _, node := range shard.NodeList { - output = output + node.BlsAddress + " \n" + output = output + node.BlsPublicKey.Hex() + " \n" } utils.GetLogInstance().Debug(fmt.Sprintf("[Resharding][shard: %d] Leader: %s", shard.ShardID, output)) } diff --git a/core/resharding.go b/core/resharding.go index b6ae3fd6b..e773ae6a5 100644 --- a/core/resharding.go +++ b/core/resharding.go @@ -148,22 +148,6 @@ func CalculateNewShardState(bc *BlockChain, epoch uint64, stakeInfo *map[common. return GetInitShardState() } ss := GetShardingStateFromBlockChain(bc, epoch-1) - if epoch == FirstEpoch { - newNodes := []types.NodeID{} - - for addr, stakeInfo := range *stakeInfo { - blsAddr := common.BytesToAddress(stakeInfo.BlsAddress[:]) - newNodes = append(newNodes, types.NodeID{addr.Hex(), blsAddr.Hex()}) - } - rand.Seed(int64(ss.rnd)) - Shuffle(newNodes) - utils.GetLogInstance().Info("[resharding] New Nodes", "data", newNodes) - for i, nid := range newNodes { - id := i%(GenesisShardNum-1) + 1 // assign the node to one of the empty shard - ss.shardState[id].NodeList = append(ss.shardState[id].NodeList, nid) - } - return ss.shardState - } newNodeList := ss.UpdateShardingState(stakeInfo) utils.GetLogInstance().Info("Cuckoo Rate", "percentage", CuckooRate) ss.Reshard(newNodeList, CuckooRate) @@ -172,11 +156,11 @@ func CalculateNewShardState(bc *BlockChain, epoch uint64, stakeInfo *map[common. // UpdateShardingState remove the unstaked nodes and returns the newly staked node Ids. func (ss *ShardingState) UpdateShardingState(stakeInfo *map[common.Address]*structs.StakeInfo) []types.NodeID { - oldAddresses := make(map[string]bool) // map of bls addresses + oldBlsPublicKeys := make(map[types.BlsPublicKey]bool) // map of bls public keys for _, shard := range ss.shardState { newNodeList := shard.NodeList[:0] for _, nodeID := range shard.NodeList { - oldAddresses[nodeID.BlsAddress] = true + oldBlsPublicKeys[nodeID.BlsPublicKey] = true _, ok := (*stakeInfo)[common.HexToAddress(nodeID.EcdsaAddress)] if ok { newNodeList = append(newNodeList, nodeID) @@ -189,9 +173,9 @@ func (ss *ShardingState) UpdateShardingState(stakeInfo *map[common.Address]*stru newAddresses := []types.NodeID{} for addr, info := range *stakeInfo { - _, ok := oldAddresses[addr.Hex()] + _, ok := oldBlsPublicKeys[info.BlsPublicKey] if !ok { - newAddresses = append(newAddresses, types.NodeID{addr.Hex(), common.BytesToAddress(info.BlsAddress[:]).Hex()}) + newAddresses = append(newAddresses, types.NodeID{addr.Hex(), info.BlsPublicKey}) } } return newAddresses @@ -206,10 +190,10 @@ func GetInitShardState() types.ShardState { index := i*GenesisShardSize + j // The initial account to use for genesis nodes priKey := bls.SecretKey{} priKey.SetHexString(contract.GenesisBLSAccounts[index].Private) - addrBytes := priKey.GetPublicKey().GetAddress() - blsAddr := common.BytesToAddress(addrBytes[:]).Hex() + pubKey := [96]byte{} + copy(pubKey[:], priKey.GetPublicKey().Serialize()[:]) // TODO: directly read address for bls too - curNodeID := types.NodeID{contract.GenesisAccounts[index].Address, blsAddr} + curNodeID := types.NodeID{contract.GenesisAccounts[index].Address, pubKey} if j == 0 { com.Leader = curNodeID } diff --git a/core/resharding_test.go b/core/resharding_test.go index f3750fa23..3a655dc1c 100644 --- a/core/resharding_test.go +++ b/core/resharding_test.go @@ -10,6 +10,32 @@ import ( "github.com/stretchr/testify/assert" ) +var ( + blsPubKey1 = [96]byte{} + blsPubKey2 = [96]byte{} + blsPubKey3 = [96]byte{} + blsPubKey4 = [96]byte{} + blsPubKey5 = [96]byte{} + blsPubKey6 = [96]byte{} + blsPubKey7 = [96]byte{} + blsPubKey8 = [96]byte{} + blsPubKey9 = [96]byte{} + blsPubKey10 = [96]byte{} +) + +func init() { + copy(blsPubKey1[:], []byte("random key 1")) + copy(blsPubKey2[:], []byte("random key 2")) + copy(blsPubKey3[:], []byte("random key 3")) + copy(blsPubKey4[:], []byte("random key 4")) + copy(blsPubKey5[:], []byte("random key 5")) + copy(blsPubKey6[:], []byte("random key 6")) + copy(blsPubKey7[:], []byte("random key 7")) + copy(blsPubKey8[:], []byte("random key 8")) + copy(blsPubKey9[:], []byte("random key 9")) + copy(blsPubKey10[:], []byte("random key 10")) +} + func fakeGetInitShardState(numberOfShards, numOfNodes int) types.ShardState { rand.Seed(int64(InitialSeed)) shardState := types.ShardState{} @@ -18,7 +44,9 @@ func fakeGetInitShardState(numberOfShards, numOfNodes int) types.ShardState { com := types.Committee{ShardID: sid} for j := 0; j < numOfNodes; j++ { nid := strconv.Itoa(int(rand.Int63())) - com.NodeList = append(com.NodeList, types.NodeID{nid, nid}) + blsPubKey := [96]byte{} + copy(blsPubKey1[:], []byte(nid)) + com.NodeList = append(com.NodeList, types.NodeID{nid, blsPubKey}) } shardState = append(shardState, com) } @@ -31,7 +59,9 @@ func fakeNewNodeList(seed int64) []types.NodeID { nodeList := []types.NodeID{} for i := 0; i < numNewNodes; i++ { nid := strconv.Itoa(int(rand.Int63())) - nodeList = append(nodeList, types.NodeID{nid, nid}) + blsPubKey := [96]byte{} + copy(blsPubKey1[:], []byte(nid)) + nodeList = append(nodeList, types.NodeID{nid, blsPubKey}) } return nodeList } @@ -43,16 +73,16 @@ func TestFakeNewNodeList(t *testing.T) { func TestShuffle(t *testing.T) { nodeList := []types.NodeID{ - {"node1", "node1"}, - {"node2", "node2"}, - {"node3", "node3"}, - {"node4", "node4"}, - {"node5", "node5"}, - {"node6", "node6"}, - {"node7", "node7"}, - {"node8", "node8"}, - {"node9", "node9"}, - {"node10", "node10"}, + {"node1", blsPubKey1}, + {"node2", blsPubKey2}, + {"node3", blsPubKey3}, + {"node4", blsPubKey4}, + {"node5", blsPubKey5}, + {"node6", blsPubKey6}, + {"node7", blsPubKey7}, + {"node8", blsPubKey8}, + {"node9", blsPubKey9}, + {"node10", blsPubKey10}, } cpList := []types.NodeID{} @@ -83,18 +113,18 @@ func TestUpdateShardState(t *testing.T) { shardState := fakeGetInitShardState(6, 10) ss := &ShardingState{epoch: 1, rnd: 42, shardState: shardState, numShards: len(shardState)} newNodeList := []types.NodeID{ - {"node1", "node1"}, - {"node2", "node2"}, - {"node3", "node3"}, - {"node4", "node4"}, - {"node5", "node5"}, - {"node6", "node6"}, + {"node1", blsPubKey1}, + {"node2", blsPubKey2}, + {"node3", blsPubKey3}, + {"node4", blsPubKey4}, + {"node5", blsPubKey5}, + {"node6", blsPubKey6}, } ss.Reshard(newNodeList, 0.2) assert.Equal(t, 6, ss.numShards) for _, shard := range ss.shardState { - assert.Equal(t, shard.Leader.BlsAddress, shard.NodeList[0].BlsAddress) + assert.Equal(t, shard.Leader.BlsPublicKey, shard.NodeList[0].BlsPublicKey) } } @@ -102,9 +132,9 @@ func TestAssignNewNodes(t *testing.T) { shardState := fakeGetInitShardState(2, 2) ss := &ShardingState{epoch: 1, rnd: 42, shardState: shardState, numShards: len(shardState)} newNodes := []types.NodeID{ - {"node1", "node1"}, - {"node2", "node2"}, - {"node3", "node3"}, + {"node1", blsPubKey1}, + {"node2", blsPubKey2}, + {"node3", blsPubKey3}, } ss.assignNewNodes(newNodes) diff --git a/core/types/shard_state.go b/core/types/shard_state.go index f77f7de11..0c9a9dd9e 100644 --- a/core/types/shard_state.go +++ b/core/types/shard_state.go @@ -1,8 +1,9 @@ package types import ( + "bytes" + "encoding/hex" "sort" - "strings" "github.com/ethereum/go-ethereum/common" "golang.org/x/crypto/sha3" @@ -11,10 +12,13 @@ import ( // ShardState is the collection of all committees type ShardState []Committee +// BlsPublicKey defines the bls public key +type BlsPublicKey [96]byte + // NodeID represents node id (BLS address). type NodeID struct { EcdsaAddress string - BlsAddress string + BlsPublicKey BlsPublicKey } // Committee contains the active nodes in one shard @@ -24,6 +28,11 @@ type Committee struct { NodeList []NodeID } +// Hex returns the hex string of bls public key +func (pk BlsPublicKey) Hex() string { + return hex.EncodeToString(pk[:]) +} + // GetHashFromNodeList will sort the list, then use Keccak256 to hash the list // notice that the input nodeList will be modified (sorted) func GetHashFromNodeList(nodeList []NodeID) []byte { @@ -58,10 +67,10 @@ func (ss ShardState) Hash() (h common.Hash) { // CompareNodeID compares two nodes by their ID; used to sort node list func CompareNodeID(n1 NodeID, n2 NodeID) int { - return strings.Compare(n1.BlsAddress, n2.BlsAddress) + return bytes.Compare(n1.BlsPublicKey[:], n2.BlsPublicKey[:]) } // Serialize serialize NodeID into bytes func (n NodeID) Serialize() []byte { - return []byte(n.BlsAddress) + return append(n.BlsPublicKey[:], []byte(n.EcdsaAddress)...) } diff --git a/core/types/shard_state_test.go b/core/types/shard_state_test.go index b9be93dd5..871dbabf2 100644 --- a/core/types/shard_state_test.go +++ b/core/types/shard_state_test.go @@ -5,16 +5,38 @@ import ( "testing" ) +var ( + blsPubKey1 = [96]byte{} + blsPubKey2 = [96]byte{} + blsPubKey3 = [96]byte{} + blsPubKey4 = [96]byte{} + blsPubKey5 = [96]byte{} + blsPubKey6 = [96]byte{} + blsPubKey11 = [96]byte{} + blsPubKey22 = [96]byte{} +) + +func init() { + copy(blsPubKey1[:], []byte("random key 1")) + copy(blsPubKey2[:], []byte("random key 2")) + copy(blsPubKey3[:], []byte("random key 3")) + copy(blsPubKey4[:], []byte("random key 4")) + copy(blsPubKey5[:], []byte("random key 5")) + copy(blsPubKey6[:], []byte("random key 6")) + copy(blsPubKey11[:], []byte("random key 11")) + copy(blsPubKey22[:], []byte("random key 22")) +} + func TestGetHashFromNodeList(t *testing.T) { l1 := []NodeID{ - {"node1", "node1"}, - {"node2", "node2"}, - {"node3", "node3"}, + {"node1", blsPubKey1}, + {"node2", blsPubKey2}, + {"node3", blsPubKey3}, } l2 := []NodeID{ - {"node2", "node2"}, - {"node1", "node1"}, - {"node3", "node3"}, + {"node2", blsPubKey2}, + {"node1", blsPubKey1}, + {"node3", blsPubKey3}, } h1 := GetHashFromNodeList(l1) h2 := GetHashFromNodeList(l2) @@ -27,20 +49,20 @@ func TestGetHashFromNodeList(t *testing.T) { func TestHash(t *testing.T) { com1 := Committee{ ShardID: 22, - Leader: NodeID{"node11", "node11"}, + Leader: NodeID{"node11", blsPubKey11}, NodeList: []NodeID{ - {"node11", "node11"}, - {"node22", "node22"}, - {"node1", "node1"}, + {"node11", blsPubKey11}, + {"node22", blsPubKey22}, + {"node1", blsPubKey1}, }, } com2 := Committee{ ShardID: 2, - Leader: NodeID{"node4", "node4"}, + Leader: NodeID{"node4", blsPubKey4}, NodeList: []NodeID{ - {"node4", "node4"}, - {"node5", "node5"}, - {"node6", "node6"}, + {"node4", blsPubKey4}, + {"node5", blsPubKey5}, + {"node6", blsPubKey6}, }, } shardState1 := ShardState{com1, com2} @@ -48,20 +70,20 @@ func TestHash(t *testing.T) { com3 := Committee{ ShardID: 2, - Leader: NodeID{"node4", "node4"}, + Leader: NodeID{"node4", blsPubKey4}, NodeList: []NodeID{ - {"node6", "node6"}, - {"node5", "node5"}, - {"node4", "node4"}, + {"node6", blsPubKey6}, + {"node5", blsPubKey5}, + {"node4", blsPubKey4}, }, } com4 := Committee{ ShardID: 22, - Leader: NodeID{"node11", "node11"}, + Leader: NodeID{"node11", blsPubKey11}, NodeList: []NodeID{ - {"node1", "node1"}, - {"node11", "node11"}, - {"node22", "node22"}, + {"node1", blsPubKey1}, + {"node11", blsPubKey11}, + {"node22", blsPubKey22}, }, } diff --git a/drand/drand.go b/drand/drand.go index f30f0e847..c5ad61513 100644 --- a/drand/drand.go +++ b/drand/drand.go @@ -5,6 +5,8 @@ import ( "errors" "sync" + "github.com/ethereum/go-ethereum/common" + protobuf "github.com/golang/protobuf/proto" "github.com/harmony-one/bls/ffi/go/bls" msg_pb "github.com/harmony-one/harmony/api/proto/message" @@ -18,7 +20,7 @@ import ( // DRand is the main struct which contains state for the distributed randomness protocol. type DRand struct { - vrfs *map[string][]byte // Key is the address hex + vrfs *map[common.Address][]byte // Key is the address hex bitmap *bls_cosi.Mask pRand *[32]byte rand *[32]byte @@ -38,7 +40,9 @@ type DRand struct { // Public keys of the committee including leader and validators PublicKeys []*bls.PublicKey - pubKeyLock sync.Mutex + // The addresses of my committee + CommitteeAddresses map[common.Address]bool + pubKeyLock sync.Mutex // private/public keys of current node priKey *bls.SecretKey @@ -52,7 +56,7 @@ type DRand struct { IsLeader bool // Leader or validator address - SelfAddress string + SelfAddress common.Address // The p2p host used to send/receive p2p messages host p2p.Host @@ -84,11 +88,13 @@ func New(host p2p.Host, ShardID uint32, peers []p2p.Peer, leader p2p.Peer, confi } dRand.leader = leader + dRand.CommitteeAddresses = map[common.Address]bool{} for _, peer := range peers { - dRand.validators.Store(utils.GetAddressHex(peer.ConsensusPubKey), peer) + dRand.validators.Store(utils.GetBlsAddress(peer.ConsensusPubKey).Hex(), peer) + dRand.CommitteeAddresses[utils.GetBlsAddress(peer.ConsensusPubKey)] = true } - dRand.vrfs = &map[string][]byte{} + dRand.vrfs = &map[common.Address][]byte{} // Initialize cosign bitmap allPublicKeys := make([]*bls.PublicKey, 0) @@ -106,7 +112,7 @@ func New(host p2p.Host, ShardID uint32, peers []p2p.Peer, leader p2p.Peer, confi dRand.rand = nil // For now use socket address as ID - dRand.SelfAddress = utils.GetAddressHex(selfPeer.ConsensusPubKey) + dRand.SelfAddress = utils.GetBlsAddress(selfPeer.ConsensusPubKey) // Set private key for myself so that I can sign messages. if blsPriKey != nil { @@ -129,10 +135,13 @@ func (dRand *DRand) AddPeers(peers []*p2p.Peer) int { count := 0 for _, peer := range peers { - _, ok := dRand.validators.LoadOrStore(utils.GetAddressHex(peer.ConsensusPubKey), *peer) + _, ok := dRand.validators.LoadOrStore(utils.GetBlsAddress(peer.ConsensusPubKey).Hex(), *peer) if !ok { dRand.pubKeyLock.Lock() - dRand.PublicKeys = append(dRand.PublicKeys, peer.ConsensusPubKey) + if _, ok := dRand.CommitteeAddresses[peer.ConsensusPubKey.GetAddress()]; !ok { + dRand.PublicKeys = append(dRand.PublicKeys, peer.ConsensusPubKey) + dRand.CommitteeAddresses[peer.ConsensusPubKey.GetAddress()] = true + } dRand.pubKeyLock.Unlock() // utils.GetLogInstance().Debug("[DRAND]", "AddPeers", *peer) } @@ -226,9 +235,15 @@ func (dRand *DRand) getValidatorPeerByAddress(validatorAddress string) *p2p.Peer return &value } +// IsValidatorInCommittee returns whether the given validator BLS address is part of my committee +func (dRand *DRand) IsValidatorInCommittee(validatorBlsAddress common.Address) bool { + _, ok := dRand.CommitteeAddresses[validatorBlsAddress] + return ok +} + // ResetState resets the state of the randomness protocol func (dRand *DRand) ResetState() { - dRand.vrfs = &map[string][]byte{} + dRand.vrfs = &map[common.Address][]byte{} bitmap, _ := bls_cosi.NewMask(dRand.PublicKeys, dRand.leader.ConsensusPubKey) dRand.bitmap = bitmap @@ -246,6 +261,12 @@ func (dRand *DRand) SetLeaderPubKey(k []byte) error { func (dRand *DRand) UpdatePublicKeys(pubKeys []*bls.PublicKey) int { dRand.pubKeyLock.Lock() dRand.PublicKeys = append(pubKeys[:0:0], pubKeys...) + dRand.CommitteeAddresses = map[common.Address]bool{} + for _, pubKey := range dRand.PublicKeys { + dRand.CommitteeAddresses[utils.GetBlsAddress(pubKey)] = true + } + // TODO: use pubkey to identify leader rather than p2p.Peer. + dRand.leader = p2p.Peer{ConsensusPubKey: pubKeys[0]} dRand.pubKeyLock.Unlock() return len(dRand.PublicKeys) diff --git a/drand/drand_leader.go b/drand/drand_leader.go index 765898c39..0aaaa8b19 100644 --- a/drand/drand_leader.go +++ b/drand/drand_leader.go @@ -4,7 +4,6 @@ import ( "bytes" "time" - "github.com/ethereum/go-ethereum/common" "github.com/harmony-one/harmony/crypto/bls" protobuf "github.com/golang/protobuf/proto" @@ -116,10 +115,13 @@ func (dRand *DRand) processCommitMessage(message *msg_pb.Message) { utils.GetLogInstance().Debug("Failed to deserialize BLS public key", "error", err) return } - addrBytes := senderPubKey.GetAddress() - validatorAddress := common.BytesToAddress(addrBytes[:]).Hex() + validatorAddress := utils.GetBlsAddress(senderPubKey) + + if !dRand.IsValidatorInCommittee(validatorAddress) { + utils.GetLogInstance().Error("Invalid validator", "validatorAddress", validatorAddress) + return + } - validatorPeer := dRand.getValidatorPeerByAddress(validatorAddress) vrfs := dRand.vrfs if len((*vrfs)) >= ((len(dRand.PublicKeys))/3 + 1) { utils.GetLogInstance().Debug("Received additional randomness commit message", "validatorAddress", validatorAddress) @@ -127,9 +129,9 @@ func (dRand *DRand) processCommitMessage(message *msg_pb.Message) { } // Verify message signature - err = verifyMessageSig(validatorPeer.ConsensusPubKey, message) + err = verifyMessageSig(senderPubKey, message) if err != nil { - utils.GetLogInstance().Warn("[DRAND] failed to verify the message signature", "Error", err, "PubKey", validatorPeer.ConsensusPubKey) + utils.GetLogInstance().Warn("[DRAND] failed to verify the message signature", "Error", err, "PubKey", senderPubKey) return } @@ -149,7 +151,7 @@ func (dRand *DRand) processCommitMessage(message *msg_pb.Message) { utils.GetLogInstance().Debug("Received new VRF commit", "numReceivedSoFar", len((*vrfs)), "validatorAddress", validatorAddress, "PublicKeys", len(dRand.PublicKeys)) (*vrfs)[validatorAddress] = drandMsg.Payload - dRand.bitmap.SetKey(validatorPeer.ConsensusPubKey, true) // Set the bitmap indicating that this validator signed. + dRand.bitmap.SetKey(senderPubKey, true) // Set the bitmap indicating that this validator signed. if len((*vrfs)) >= ((len(dRand.PublicKeys))/3 + 1) { // Construct pRand and initiate consensus on it diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 1ab8d5a7b..a81fc2bb0 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -226,10 +226,10 @@ func IsPrivateIP(ip net.IP) bool { return false } -// GetAddressHex returns the hex string of the address of consensus pubKey. -func GetAddressHex(key *bls.PublicKey) string { +// GetBlsAddress returns the address of consensus BLS pubKey. +func GetBlsAddress(key *bls.PublicKey) common.Address { addr := common.Address{} addrBytes := key.GetAddress() addr.SetBytes(addrBytes[:]) - return addr.Hex() + return addr } diff --git a/internal/utils/utils_test.go b/internal/utils/utils_test.go index dd69793f9..c61eb993f 100644 --- a/internal/utils/utils_test.go +++ b/internal/utils/utils_test.go @@ -207,7 +207,7 @@ func TestStringsToPeers(t *testing.T) { } } -func TestGetAddressHex(t *testing.T) { +func TestGetBlsAddress(t *testing.T) { pubKey1 := pki.GetBLSPrivateKeyFromInt(333).GetPublicKey() pubKey2 := pki.GetBLSPrivateKeyFromInt(1024).GetPublicKey() tests := []struct { @@ -225,8 +225,8 @@ func TestGetAddressHex(t *testing.T) { } for _, test := range tests { - result := GetAddressHex(test.key) - if result != test.expected { + result := GetBlsAddress(test.key) + if result.Hex() != test.expected { t.Errorf("Hex Of %v is: %v, got: %v", test.key, test.expected, result) } } diff --git a/node/node.go b/node/node.go index 6626d7e33..fb4c6fc89 100644 --- a/node/node.go +++ b/node/node.go @@ -8,6 +8,8 @@ import ( "sync" "time" + "github.com/harmony-one/bls/ffi/go/bls" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" @@ -256,8 +258,6 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, db ethdb.Database, is os.Exit(1) } node.blockchain = chain - // Store the genesis shard state into db. - node.blockchain.StoreNewShardState(node.blockchain.CurrentBlock(), nil) node.BlockChannel = make(chan *types.Block) node.ConfirmedBlockChannel = make(chan *types.Block) @@ -278,6 +278,7 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, db ethdb.Database, is } else { node.AddContractKeyAndAddress() } + } node.ContractCaller = contracts.NewContractCaller(&db, node.blockchain, params.TestChainConfig) @@ -311,6 +312,26 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, db ethdb.Database, is return &node } +// InitGenesisShardState initialize genesis shard state and update committee pub keys for consensus and drand +func (node *Node) InitGenesisShardState() { + // Store the genesis shard state into db. + shardState := node.blockchain.StoreNewShardState(node.blockchain.CurrentBlock(), nil) + // Update validator public keys + for _, shard := range shardState { + if shard.ShardID == node.Consensus.ShardID { + pubKeys := []*bls.PublicKey{} + for _, node := range shard.NodeList { + blsPubKey := &bls.PublicKey{} + blsPubKey.Deserialize(node.BlsPublicKey[:]) + pubKeys = append(pubKeys, blsPubKey) + } + node.Consensus.UpdatePublicKeys(pubKeys) + node.DRand.UpdatePublicKeys(pubKeys) + break + } + } +} + // AddPeers adds neighbors nodes func (node *Node) AddPeers(peers []*p2p.Peer) int { count := 0 @@ -327,6 +348,7 @@ func (node *Node) AddPeers(peers []*p2p.Peer) int { // Only leader needs to add the peer info into consensus // Validators will receive the updated peer info from Leader via pong message + // TODO: remove this after fully migrating to beacon chain-based committee membership if count > 0 && node.NodeConfig.IsLeader() { node.Consensus.AddPeers(peers) // TODO: make peers into a context object shared by consensus and drand diff --git a/node/node_handler.go b/node/node_handler.go index b8d11158c..53ee06d98 100644 --- a/node/node_handler.go +++ b/node/node_handler.go @@ -3,6 +3,7 @@ package node import ( "bytes" "context" + "encoding/hex" "fmt" "math" "os" @@ -98,10 +99,10 @@ func (node *Node) messageHandler(content []byte, sender string) { case proto.Consensus: msgPayload, _ := proto.GetConsensusMessagePayload(content) if consensusObj.IsLeader { - // utils.GetLogInstance().Info("NET: Leader received consensus message") + utils.GetLogInstance().Info("NET: Leader received consensus message") consensusObj.ProcessMessageLeader(msgPayload) } else { - // utils.GetLogInstance().Info("NET: Validator received consensus message") + utils.GetLogInstance().Info("NET: Validator received consensus message") consensusObj.ProcessMessageValidator(msgPayload) // TODO(minhdoan): add logic to check if the current blockchain is not sync with other consensus // we should switch to other state rather than DoingConsensus. @@ -303,10 +304,10 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block) { if shardState != nil { myShard := uint32(math.MaxUint32) isLeader := false - blsAddr := node.Consensus.SelfAddress + myBlsPubKey := node.Consensus.PubKey.Serialize() for _, shard := range shardState { for _, nodeID := range shard.NodeList { - if nodeID.BlsAddress == blsAddr { + if bytes.Compare(nodeID.BlsPublicKey[:], myBlsPubKey) == 0 { myShard = shard.ShardID isLeader = shard.Leader == nodeID } @@ -327,12 +328,12 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block) { } } if node.blockchain.ShardID() == myShard { - utils.GetLogInstance().Info(fmt.Sprintf("[Resharded][epoch:%d] I stay at shard %d, %s", core.GetEpochFromBlockNumber(newBlock.NumberU64()), myShard, aboutLeader), "BlsAddress", blsAddr) + utils.GetLogInstance().Info(fmt.Sprintf("[Resharded][epoch:%d] I stay at shard %d, %s", core.GetEpochFromBlockNumber(newBlock.NumberU64()), myShard, aboutLeader), "BlsPubKey", hex.EncodeToString(myBlsPubKey)) } else { - utils.GetLogInstance().Info(fmt.Sprintf("[Resharded][epoch:%d] I got resharded to shard %d, %s", core.GetEpochFromBlockNumber(newBlock.NumberU64()), myShard, aboutLeader), "BlsAddress", blsAddr) + utils.GetLogInstance().Info(fmt.Sprintf("[Resharded][epoch:%d] I got resharded to shard %d from shard %d, %s", core.GetEpochFromBlockNumber(newBlock.NumberU64()), myShard, node.blockchain.ShardID(), aboutLeader), "BlsPubKey", hex.EncodeToString(myBlsPubKey)) } } else { - utils.GetLogInstance().Info(fmt.Sprintf("[Resharded][epoch:%d] Somehow I got kicked out", core.GetEpochFromBlockNumber(newBlock.NumberU64())), "BlsAddress", blsAddr) + utils.GetLogInstance().Info(fmt.Sprintf("[Resharded][epoch:%d] Somehow I got kicked out", core.GetEpochFromBlockNumber(newBlock.NumberU64())), "BlsPubKey", hex.EncodeToString(myBlsPubKey)) } } } @@ -388,7 +389,7 @@ func (node *Node) pingMessageHandler(msgPayload []byte, sender string) int { node.ClientPeer = peer } else { node.AddPeers([]*p2p.Peer{peer}) - utils.GetLogInstance().Info("Add Peer to Node", "Address", node.Consensus.GetSelfAddress(), "Peer", peer, "# Peers", node.Consensus.GetNumPeers()) + utils.GetLogInstance().Info("Add Peer to Node", "Address", node.Consensus.GetSelfAddress(), "Peer", peer, "# Peers", node.Consensus.GetNumValidators()) } return 1 @@ -396,6 +397,7 @@ func (node *Node) pingMessageHandler(msgPayload []byte, sender string) int { // SendPongMessage is the a goroutine to periodcally send pong message to all peers func (node *Node) SendPongMessage() { + utils.GetLogInstance().Info("Starting Pong routing") tick := time.NewTicker(2 * time.Second) tick2 := time.NewTicker(120 * time.Second) @@ -410,10 +412,11 @@ func (node *Node) SendPongMessage() { case <-tick.C: peers := node.Consensus.GetValidatorPeers() numPeersNow := len(peers) - numPubKeysNow := node.Consensus.GetNumPeers() + numPubKeysNow := node.Consensus.GetNumValidators() // no peers, wait for another tick - if numPeersNow == 0 || numPubKeysNow == 0 { + if numPubKeysNow == 0 { + utils.GetLogInstance().Info("[PONG] no peers, continue", "numPeers", numPeers, "numPeersNow", numPeersNow) continue } // new peers added @@ -440,6 +443,7 @@ func (node *Node) SendPongMessage() { // only need to notify consensus leader once to start the consensus if firstTime { // Leader stops sending ping message + time.Sleep(5 * time.Second) node.serviceManager.TakeAction(&service.Action{Action: service.Stop, ServiceType: service.PeerDiscovery}) node.startConsensus <- struct{}{} firstTime = false @@ -480,17 +484,18 @@ func (node *Node) pongMessageHandler(msgPayload []byte) int { // set the leader pub key is the first thing to do // otherwise, we may not be able to validate the consensus messages received // which will result in first consensus timeout + // TODO: remove this after fully migrating to beacon chain-based committee membership err = node.Consensus.SetLeaderPubKey(pong.LeaderPubKey) if err != nil { utils.GetLogInstance().Error("Unmarshal Consensus Leader PubKey Failed", "error", err) } else { - utils.GetLogInstance().Info("Set Consensus Leader PubKey", "key", utils.GetAddressHex(node.Consensus.GetLeaderPubKey())) + utils.GetLogInstance().Info("Set Consensus Leader PubKey", "key", node.Consensus.GetLeaderPubKey()) } err = node.DRand.SetLeaderPubKey(pong.LeaderPubKey) if err != nil { utils.GetLogInstance().Error("Unmarshal DRand Leader PubKey Failed", "error", err) } else { - utils.GetLogInstance().Info("Set DRand Leader PubKey", "key", utils.GetAddressHex(node.Consensus.GetLeaderPubKey())) + utils.GetLogInstance().Info("Set DRand Leader PubKey", "key", node.Consensus.GetLeaderPubKey()) } peers := make([]*p2p.Peer, 0) @@ -541,5 +546,7 @@ func (node *Node) pongMessageHandler(msgPayload []byte) int { data["peer"] = p2p.GroupAction{Name: node.NodeConfig.GetShardGroupID(), Action: p2p.ActionPause} node.serviceManager.TakeAction(&service.Action{Action: service.Notify, ServiceType: service.PeerDiscovery, Params: data}) + + // TODO: remove this after fully migrating to beacon chain-based committee membership return node.Consensus.UpdatePublicKeys(publicKeys) + node.DRand.UpdatePublicKeys(publicKeys) } diff --git a/node/node_newblock.go b/node/node_newblock.go index 23a2020db..83f55ac84 100644 --- a/node/node_newblock.go +++ b/node/node_newblock.go @@ -63,6 +63,7 @@ func (node *Node) WaitForConsensusReady(readySignal chan struct{}, stopChan chan // TODO(minhdoan): only happens for beaconchain node.addNewShardStateHash(block) newBlock = block + utils.GetLogInstance().Debug("Successfully proposed new block", "blockNum", block.NumberU64(), "numTxs", block.Transactions().Len()) break } } diff --git a/node/service_setup.go b/node/service_setup.go index 4fd8fd033..b0de806f1 100644 --- a/node/service_setup.go +++ b/node/service_setup.go @@ -26,7 +26,7 @@ func (node *Node) setupForShardLeader() { node.serviceManager.RegisterService(service.NetworkInfo, networkinfo.New(node.host, node.NodeConfig.GetShardGroupID(), chanPeer, nil)) // Register explorer service. - node.serviceManager.RegisterService(service.SupportExplorer, explorer.New(&node.SelfPeer, node.Consensus.GetNumPeers)) + node.serviceManager.RegisterService(service.SupportExplorer, explorer.New(&node.SelfPeer, node.Consensus.GetNumValidators)) // Register consensus service. node.serviceManager.RegisterService(service.Consensus, consensus.New(node.BlockChannel, node.Consensus, node.startConsensus)) // Register new block service. @@ -70,7 +70,7 @@ func (node *Node) setupForBeaconLeader() { // Register randomness service node.serviceManager.RegisterService(service.Randomness, randomness.New(node.DRand)) // Register explorer service. - node.serviceManager.RegisterService(service.SupportExplorer, explorer.New(&node.SelfPeer, node.Consensus.GetNumPeers)) + node.serviceManager.RegisterService(service.SupportExplorer, explorer.New(&node.SelfPeer, node.Consensus.GetNumValidators)) } func (node *Node) setupForBeaconValidator() { diff --git a/node/staking.go b/node/staking.go index 2dba4772b..4b8922c18 100644 --- a/node/staking.go +++ b/node/staking.go @@ -5,6 +5,8 @@ import ( "math/big" "os" + "github.com/harmony-one/harmony/core/types" + "github.com/harmony-one/harmony/contracts/structs" "github.com/harmony-one/harmony/core" @@ -44,8 +46,12 @@ func (node *Node) UpdateStakingList(stakeInfoReturnValue *structs.StakeInfoRetur } // True if the token is still staked within the locking period. if curEpoch-startEpoch <= lockPeriodCount.Uint64()*lockPeriodInEpochs { + blsPubKey := types.BlsPublicKey{} + copy(blsPubKey[:32], stakeInfoReturnValue.BlsPubicKeys1[i][:]) + copy(blsPubKey[32:64], stakeInfoReturnValue.BlsPubicKeys2[i][:]) + copy(blsPubKey[64:96], stakeInfoReturnValue.BlsPubicKeys2[i][:]) node.CurrentStakes[addr] = &structs.StakeInfo{ - stakeInfoReturnValue.BlsAddresses[i], + blsPubKey, blockNum, lockPeriodCount, stakeInfoReturnValue.Amounts[i], diff --git a/node/staking_test.go b/node/staking_test.go index 71e56b161..c1dc7735e 100644 --- a/node/staking_test.go +++ b/node/staking_test.go @@ -20,7 +20,9 @@ var ( blockNum = big.NewInt(15000) lockPeriodCount = big.NewInt(1) testAddress = common.Address{123} - testBlsAddress = common.Address{132}.Bytes() // [20]byte + testBlsPubKey1 = [32]byte{} + testBlsPubKey2 = [32]byte{} + testBlsPubKey3 = [32]byte{} ) func TestUpdateStakingList(t *testing.T) { @@ -45,7 +47,9 @@ func TestUpdateStakingList(t *testing.T) { stakeInfo := &structs.StakeInfoReturnValue{ []common.Address{testAddress}, - [][20]byte{testAddress}, + [][32]byte{testBlsPubKey1}, + [][32]byte{testBlsPubKey2}, + [][32]byte{testBlsPubKey3}, []*big.Int{blockNum}, []*big.Int{lockPeriodCount}, []*big.Int{amount},