From 815c07511247921a6436957c3c8be8463e2675c4 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Sat, 11 Jul 2020 10:48:25 +0300 Subject: [PATCH 1/6] consensus: update dbft, use millisecond-precision time, add CV reason --- go.mod | 2 +- go.sum | 4 ++-- pkg/consensus/change_view.go | 19 ++++++++++++++----- pkg/consensus/change_view_test.go | 4 ++-- pkg/consensus/consensus_test.go | 2 +- pkg/consensus/payload_test.go | 6 +++--- pkg/consensus/recovery_message.go | 8 ++++---- pkg/consensus/recovery_request.go | 10 +++++----- pkg/consensus/recovery_request_test.go | 4 ++-- 9 files changed, 34 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index de9fc5226..b6c004c6d 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/go-yaml/yaml v2.1.0+incompatible github.com/gorilla/websocket v1.4.2 github.com/mr-tron/base58 v1.1.2 - github.com/nspcc-dev/dbft v0.0.0-20200623100921-5a182c20965e + github.com/nspcc-dev/dbft v0.0.0-20200711144034-c526ccc6f570 github.com/nspcc-dev/rfc6979 v0.2.0 github.com/pierrec/lz4 v2.5.2+incompatible github.com/pkg/errors v0.8.1 diff --git a/go.sum b/go.sum index 4950195d0..57963dec3 100644 --- a/go.sum +++ b/go.sum @@ -137,8 +137,8 @@ github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a h1:ajvxgEe9qY4vvoSm github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk= github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1 h1:yEx9WznS+rjE0jl0dLujCxuZSIb+UTjF+005TJu/nNI= github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ= -github.com/nspcc-dev/dbft v0.0.0-20200623100921-5a182c20965e h1:QOT9slflIkEKb5wY0ZUC0dCmCgoqGlhOAh9+xWMIxfg= -github.com/nspcc-dev/dbft v0.0.0-20200623100921-5a182c20965e/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E= +github.com/nspcc-dev/dbft v0.0.0-20200711144034-c526ccc6f570 h1:EHBwlOyd2m06C3dnxhpPokpYqlNg7u5ZX/uPBhjYuZ4= +github.com/nspcc-dev/dbft v0.0.0-20200711144034-c526ccc6f570/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E= github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg= github.com/nspcc-dev/neofs-crypto v0.2.0 h1:ftN+59WqxSWz/RCgXYOfhmltOOqU+udsNQSvN6wkFck= github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= diff --git a/pkg/consensus/change_view.go b/pkg/consensus/change_view.go index 30ecf4eb0..a292619e9 100644 --- a/pkg/consensus/change_view.go +++ b/pkg/consensus/change_view.go @@ -8,19 +8,22 @@ import ( // changeView represents dBFT ChangeView message. type changeView struct { newViewNumber byte - timestamp uint32 + timestamp uint64 + reason payload.ChangeViewReason } var _ payload.ChangeView = (*changeView)(nil) // EncodeBinary implements io.Serializable interface. func (c *changeView) EncodeBinary(w *io.BinWriter) { - w.WriteU32LE(c.timestamp) + w.WriteU64LE(c.timestamp) + w.WriteB(byte(c.reason)) } // DecodeBinary implements io.Serializable interface. func (c *changeView) DecodeBinary(r *io.BinReader) { - c.timestamp = r.ReadU32LE() + c.timestamp = r.ReadU64LE() + c.reason = payload.ChangeViewReason(r.ReadB()) } // NewViewNumber implements payload.ChangeView interface. @@ -30,7 +33,13 @@ func (c changeView) NewViewNumber() byte { return c.newViewNumber } func (c *changeView) SetNewViewNumber(view byte) { c.newViewNumber = view } // Timestamp implements payload.ChangeView interface. -func (c changeView) Timestamp() uint32 { return c.timestamp } +func (c changeView) Timestamp() uint64 { return c.timestamp * 1000000 } // SetTimestamp implements payload.ChangeView interface. -func (c *changeView) SetTimestamp(ts uint32) { c.timestamp = ts } +func (c *changeView) SetTimestamp(ts uint64) { c.timestamp = ts / 1000000 } + +// Reason implements payload.ChangeView interface. +func (c changeView) Reason() payload.ChangeViewReason { return c.reason } + +// SetReason implements payload.ChangeView interface. +func (c *changeView) SetReason(reason payload.ChangeViewReason) { c.reason = reason } diff --git a/pkg/consensus/change_view_test.go b/pkg/consensus/change_view_test.go index 4d1142f39..70fd117ec 100644 --- a/pkg/consensus/change_view_test.go +++ b/pkg/consensus/change_view_test.go @@ -9,8 +9,8 @@ import ( func TestChangeView_Setters(t *testing.T) { var c changeView - c.SetTimestamp(123) - require.EqualValues(t, 123, c.Timestamp()) + c.SetTimestamp(123 * 1000000) + require.EqualValues(t, 123*1000000, c.Timestamp()) c.SetNewViewNumber(2) require.EqualValues(t, 2, c.NewViewNumber()) diff --git a/pkg/consensus/consensus_test.go b/pkg/consensus/consensus_test.go index 902a31546..f6221894c 100644 --- a/pkg/consensus/consensus_test.go +++ b/pkg/consensus/consensus_test.go @@ -63,7 +63,7 @@ func TestService_GetVerified(t *testing.T) { p.SetPayload(&prepareRequest{transactionHashes: hashes}) } else { p.SetType(payload.ChangeViewType) - p.SetPayload(&changeView{newViewNumber: 1, timestamp: uint32(time.Now().Unix())}) + p.SetPayload(&changeView{newViewNumber: 1, timestamp: uint64(time.Now().UnixNano() / 1000000)}) } p.SetHeight(1) p.SetValidatorIndex(uint16(i)) diff --git a/pkg/consensus/payload_test.go b/pkg/consensus/payload_test.go index 45d44c6cc..6dc2b0985 100644 --- a/pkg/consensus/payload_test.go +++ b/pkg/consensus/payload_test.go @@ -224,7 +224,7 @@ func randomMessage(t *testing.T, mt messageType) io.Serializable { switch mt { case changeViewType: return &changeView{ - timestamp: rand.Uint32(), + timestamp: rand.Uint64(), } case prepareRequestType: return randomPrepareRequest(t) @@ -235,7 +235,7 @@ func randomMessage(t *testing.T, mt messageType) io.Serializable { random.Fill(c.signature[:]) return &c case recoveryRequestType: - return &recoveryRequest{timestamp: rand.Uint32()} + return &recoveryRequest{timestamp: rand.Uint64()} case recoveryMessageType: return randomRecoveryMessage(t) default: @@ -289,7 +289,7 @@ func randomRecoveryMessage(t *testing.T) *recoveryMessage { }, changeViewPayloads: []*changeViewCompact{ { - Timestamp: rand.Uint32(), + Timestamp: rand.Uint64(), ValidatorIndex: 3, OriginalViewNumber: 3, InvocationScript: random.Bytes(4), diff --git a/pkg/consensus/recovery_message.go b/pkg/consensus/recovery_message.go index 8e894b884..a9ce3f569 100644 --- a/pkg/consensus/recovery_message.go +++ b/pkg/consensus/recovery_message.go @@ -21,7 +21,7 @@ type ( changeViewCompact struct { ValidatorIndex uint16 OriginalViewNumber byte - Timestamp uint32 + Timestamp uint64 InvocationScript []byte } @@ -95,7 +95,7 @@ func (m *recoveryMessage) EncodeBinary(w *io.BinWriter) { func (p *changeViewCompact) DecodeBinary(r *io.BinReader) { p.ValidatorIndex = r.ReadU16LE() p.OriginalViewNumber = r.ReadB() - p.Timestamp = r.ReadU32LE() + p.Timestamp = r.ReadU64LE() p.InvocationScript = r.ReadVarBytes(1024) } @@ -103,7 +103,7 @@ func (p *changeViewCompact) DecodeBinary(r *io.BinReader) { func (p *changeViewCompact) EncodeBinary(w *io.BinWriter) { w.WriteU16LE(p.ValidatorIndex) w.WriteB(p.OriginalViewNumber) - w.WriteU32LE(p.Timestamp) + w.WriteU64LE(p.Timestamp) w.WriteVarBytes(p.InvocationScript) } @@ -164,7 +164,7 @@ func (m *recoveryMessage) AddPayload(p payload.ConsensusPayload) { m.changeViewPayloads = append(m.changeViewPayloads, &changeViewCompact{ ValidatorIndex: p.ValidatorIndex(), OriginalViewNumber: p.ViewNumber(), - Timestamp: p.GetChangeView().Timestamp(), + Timestamp: p.GetChangeView().Timestamp() / 1000000, InvocationScript: p.(*Payload).Witness.InvocationScript, }) case payload.CommitType: diff --git a/pkg/consensus/recovery_request.go b/pkg/consensus/recovery_request.go index d40c6f9e4..630775b86 100644 --- a/pkg/consensus/recovery_request.go +++ b/pkg/consensus/recovery_request.go @@ -7,23 +7,23 @@ import ( // recoveryRequest represents dBFT RecoveryRequest message. type recoveryRequest struct { - timestamp uint32 + timestamp uint64 } var _ payload.RecoveryRequest = (*recoveryRequest)(nil) // DecodeBinary implements io.Serializable interface. func (m *recoveryRequest) DecodeBinary(r *io.BinReader) { - m.timestamp = r.ReadU32LE() + m.timestamp = r.ReadU64LE() } // EncodeBinary implements io.Serializable interface. func (m *recoveryRequest) EncodeBinary(w *io.BinWriter) { - w.WriteU32LE(m.timestamp) + w.WriteU64LE(m.timestamp) } // Timestamp implements payload.RecoveryRequest interface. -func (m *recoveryRequest) Timestamp() uint32 { return m.timestamp } +func (m *recoveryRequest) Timestamp() uint64 { return m.timestamp * 1000000 } // SetTimestamp implements payload.RecoveryRequest interface. -func (m *recoveryRequest) SetTimestamp(ts uint32) { m.timestamp = ts } +func (m *recoveryRequest) SetTimestamp(ts uint64) { m.timestamp = ts / 1000000 } diff --git a/pkg/consensus/recovery_request_test.go b/pkg/consensus/recovery_request_test.go index e061711ff..8bae99aa6 100644 --- a/pkg/consensus/recovery_request_test.go +++ b/pkg/consensus/recovery_request_test.go @@ -9,6 +9,6 @@ import ( func TestRecoveryRequest_Setters(t *testing.T) { var r recoveryRequest - r.SetTimestamp(123) - require.EqualValues(t, 123, r.Timestamp()) + r.SetTimestamp(123 * 1000000) + require.EqualValues(t, 123*1000000, r.Timestamp()) } From ae497228f06ef2ac466fd08ac7be0b2ef66853d0 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Sat, 11 Jul 2020 12:29:06 +0300 Subject: [PATCH 2/6] core: use native NEO GetValidators for bc.GetValidators NextBlockValidators are updated before the new block persist, so we need to use GetValidators to get the list corresponding to the current state of the chain. --- pkg/core/blockchain.go | 2 +- pkg/core/native/native_neo.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index bbfa38219..7446799de 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1242,7 +1242,7 @@ func (bc *Blockchain) GetStandByValidators() keys.PublicKeys { // GetValidators returns next block validators. func (bc *Blockchain) GetValidators() ([]*keys.PublicKey, error) { - return bc.contracts.NEO.GetNextBlockValidatorsInternal(bc, bc.dao) + return bc.contracts.NEO.GetValidatorsInternal(bc, bc.dao) } // GetEnrollments returns all registered validators. diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 6d169eaa4..75930277e 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -142,7 +142,7 @@ func (n *NEO) Initialize(ic *interop.Context) error { // OnPersist implements Contract interface. func (n *NEO) OnPersist(ic *interop.Context) error { - pubs, err := n.getValidatorsInternal(ic.Chain, ic.DAO) + pubs, err := n.GetValidatorsInternal(ic.Chain, ic.DAO) if err != nil { return err } @@ -385,8 +385,8 @@ func (n *NEO) getRegisteredValidatorsCall(ic *interop.Context, _ []stackitem.Ite return stackitem.NewArray(arr) } -// getValidatorsInternal returns a list of current validators. -func (n *NEO) getValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) (keys.PublicKeys, error) { +// GetValidatorsInternal returns a list of current validators. +func (n *NEO) GetValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) (keys.PublicKeys, error) { if vals := n.validators.Load().(keys.PublicKeys); vals != nil { return vals, nil } @@ -442,7 +442,7 @@ func (n *NEO) getValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) (ke } func (n *NEO) getValidators(ic *interop.Context, _ []stackitem.Item) stackitem.Item { - result, err := n.getValidatorsInternal(ic.Chain, ic.DAO) + result, err := n.GetValidatorsInternal(ic.Chain, ic.DAO) if err != nil { panic(err) } @@ -470,7 +470,7 @@ func (n *NEO) GetNextBlockValidatorsInternal(bc blockchainer.Blockchainer, d dao func (n *NEO) getNextBlockValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) (keys.PublicKeys, error) { si := d.GetStorageItem(n.ContractID, nextValidatorsKey) if si == nil { - return n.getValidatorsInternal(bc, d) + return n.GetValidatorsInternal(bc, d) } pubs := keys.PublicKeys{} err := pubs.DecodeBytes(si.Value) From 2278cd5700e773974ad03d010d4ad3dc06daf49c Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Sat, 11 Jul 2020 12:32:53 +0300 Subject: [PATCH 3/6] consensus: drop NextConsensus from the prepareRequest Follow neo-project/neo#744 to make our requests compatible with C# node. --- pkg/consensus/consensus.go | 22 ++++++++++++---------- pkg/consensus/payload_test.go | 1 - pkg/consensus/prepare_request.go | 7 ++----- pkg/consensus/prepare_request_test.go | 2 +- pkg/consensus/recovery_message_test.go | 1 - 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index c0a74e666..7fee372c9 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -464,15 +464,8 @@ func (s *service) getValidators(_ ...block.Transaction) []crypto.PublicKey { return pubs } -func (s *service) getConsensusAddress(validators ...crypto.PublicKey) (h util.Uint160) { - pubs := convertKeys(validators) - - script, err := smartcontract.CreateMultiSigRedeemScript(s.dbft.M(), pubs) - if err != nil { - return - } - - return crypto.Hash160(script) +func (s *service) getConsensusAddress(validators ...crypto.PublicKey) util.Uint160 { + return util.Uint160{} } func convertKeys(validators []crypto.PublicKey) (pubs []*keys.PublicKey) { @@ -493,7 +486,16 @@ func (s *service) newBlockFromContext(ctx *dbft.Context) block.Block { block.Block.Network = s.network block.Block.Timestamp = ctx.Timestamp / 1000000 block.Block.Index = ctx.BlockIndex - block.Block.NextConsensus = ctx.NextConsensus + + validators, err := s.Chain.GetValidators() + if err != nil { + return nil + } + script, err := smartcontract.CreateMultiSigRedeemScript(len(validators)-(len(validators)-1)/3, validators) + if err != nil { + return nil + } + block.Block.NextConsensus = crypto.Hash160(script) block.Block.PrevHash = ctx.PrevHash block.Block.Version = ctx.Version block.Block.ConsensusData.Nonce = ctx.Nonce diff --git a/pkg/consensus/payload_test.go b/pkg/consensus/payload_test.go index 6dc2b0985..1cbe97a3b 100644 --- a/pkg/consensus/payload_test.go +++ b/pkg/consensus/payload_test.go @@ -256,7 +256,6 @@ func randomPrepareRequest(t *testing.T) *prepareRequest { for i := 0; i < txCount; i++ { req.transactionHashes[i] = random.Uint256() } - req.nextConsensus = random.Uint160() return req } diff --git a/pkg/consensus/prepare_request.go b/pkg/consensus/prepare_request.go index fb1d314f9..26be085ad 100644 --- a/pkg/consensus/prepare_request.go +++ b/pkg/consensus/prepare_request.go @@ -11,7 +11,6 @@ type prepareRequest struct { timestamp uint64 nonce uint64 transactionHashes []util.Uint256 - nextConsensus util.Uint160 } var _ payload.PrepareRequest = (*prepareRequest)(nil) @@ -20,7 +19,6 @@ var _ payload.PrepareRequest = (*prepareRequest)(nil) func (p *prepareRequest) EncodeBinary(w *io.BinWriter) { w.WriteU64LE(p.timestamp) w.WriteU64LE(p.nonce) - w.WriteBytes(p.nextConsensus[:]) w.WriteArray(p.transactionHashes) } @@ -28,7 +26,6 @@ func (p *prepareRequest) EncodeBinary(w *io.BinWriter) { func (p *prepareRequest) DecodeBinary(r *io.BinReader) { p.timestamp = r.ReadU64LE() p.nonce = r.ReadU64LE() - r.ReadBytes(p.nextConsensus[:]) r.ReadArray(&p.transactionHashes) } @@ -51,7 +48,7 @@ func (p *prepareRequest) TransactionHashes() []util.Uint256 { return p.transacti func (p *prepareRequest) SetTransactionHashes(hs []util.Uint256) { p.transactionHashes = hs } // NextConsensus implements payload.PrepareRequest interface. -func (p *prepareRequest) NextConsensus() util.Uint160 { return p.nextConsensus } +func (p *prepareRequest) NextConsensus() util.Uint160 { return util.Uint160{} } // SetNextConsensus implements payload.PrepareRequest interface. -func (p *prepareRequest) SetNextConsensus(nc util.Uint160) { p.nextConsensus = nc } +func (p *prepareRequest) SetNextConsensus(_ util.Uint160) {} diff --git a/pkg/consensus/prepare_request_test.go b/pkg/consensus/prepare_request_test.go index 4b91e6cfb..188e32d97 100644 --- a/pkg/consensus/prepare_request_test.go +++ b/pkg/consensus/prepare_request_test.go @@ -20,7 +20,7 @@ func TestPrepareRequest_Setters(t *testing.T) { require.EqualValues(t, 1000000, p.Timestamp()) p.SetNextConsensus(util.Uint160{5, 6, 7}) - require.Equal(t, util.Uint160{5, 6, 7}, p.NextConsensus()) + require.Equal(t, util.Uint160{}, p.NextConsensus()) p.SetNonce(8765) require.EqualValues(t, 8765, p.Nonce()) diff --git a/pkg/consensus/recovery_message_test.go b/pkg/consensus/recovery_message_test.go index 203edf45c..54544edb0 100644 --- a/pkg/consensus/recovery_message_test.go +++ b/pkg/consensus/recovery_message_test.go @@ -31,7 +31,6 @@ func TestRecoveryMessage_Setters(t *testing.T) { timestamp: 87, nonce: 321, transactionHashes: []util.Uint256{{1}}, - nextConsensus: util.Uint160{1, 2}, } p1 := new(Payload) p1.message = &message{} From 7eef8950612b37f83da2f3639d32fd61800a6670 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Sat, 11 Jul 2020 13:10:57 +0300 Subject: [PATCH 4/6] consensus: use GetNextBlockValidators where appropriate GetValidators without parameter is called upon DBFT initialization and it should receive validators for the next block (that will create it), parameterized GetValidators is used for NextConsensus calculation where we need a list for the current state of the chain. --- pkg/consensus/consensus.go | 8 ++++++-- pkg/core/blockchain.go | 7 ++++++- pkg/core/blockchainer/blockchainer.go | 1 + pkg/network/helper_test.go | 3 +++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index 7fee372c9..be9545cff 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -446,12 +446,16 @@ func (s *service) getVerifiedTx() []block.Transaction { return res } -func (s *service) getValidators(_ ...block.Transaction) []crypto.PublicKey { +func (s *service) getValidators(txes ...block.Transaction) []crypto.PublicKey { var ( pKeys []*keys.PublicKey err error ) - pKeys, err = s.Chain.GetValidators() + if txes == nil { + pKeys, err = s.Chain.GetNextBlockValidators() + } else { + pKeys, err = s.Chain.GetValidators() + } if err != nil { s.log.Error("error while trying to get validators", zap.Error(err)) } diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 7446799de..a8646e571 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1240,11 +1240,16 @@ func (bc *Blockchain) GetStandByValidators() keys.PublicKeys { return bc.sbValidators.Copy() } -// GetValidators returns next block validators. +// GetValidators returns current validators. func (bc *Blockchain) GetValidators() ([]*keys.PublicKey, error) { return bc.contracts.NEO.GetValidatorsInternal(bc, bc.dao) } +// GetNextBlockValidators returns next block validators. +func (bc *Blockchain) GetNextBlockValidators() ([]*keys.PublicKey, error) { + return bc.contracts.NEO.GetNextBlockValidatorsInternal(bc, bc.dao) +} + // GetEnrollments returns all registered validators. func (bc *Blockchain) GetEnrollments() ([]state.Validator, error) { return bc.contracts.NEO.GetRegisteredValidators(bc.dao) diff --git a/pkg/core/blockchainer/blockchainer.go b/pkg/core/blockchainer/blockchainer.go index ce723614b..9dcac9e33 100644 --- a/pkg/core/blockchainer/blockchainer.go +++ b/pkg/core/blockchainer/blockchainer.go @@ -36,6 +36,7 @@ type Blockchainer interface { HasTransaction(util.Uint256) bool GetAccountState(util.Uint160) *state.Account GetAppExecResult(util.Uint256) (*state.AppExecResult, error) + GetNextBlockValidators() ([]*keys.PublicKey, error) GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog GetNEP5Balances(util.Uint160) *state.NEP5Balances GetValidators() ([]*keys.PublicKey, error) diff --git a/pkg/network/helper_test.go b/pkg/network/helper_test.go index cc7dbcb7c..6004c44a4 100644 --- a/pkg/network/helper_test.go +++ b/pkg/network/helper_test.go @@ -77,6 +77,9 @@ func (chain testChain) GetHeader(hash util.Uint256) (*block.Header, error) { func (chain testChain) GetAccountState(util.Uint160) *state.Account { panic("TODO") } +func (chain testChain) GetNextBlockValidators() ([]*keys.PublicKey, error) { + panic("TODO") +} func (chain testChain) GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog { panic("TODO") } From 579630a3fa7e1c8ccfa86a04e0080458eb889c82 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Sat, 11 Jul 2020 14:07:48 +0300 Subject: [PATCH 5/6] native: don't expose internal slices to the outside world They should be hidden. --- pkg/core/native/native_neo.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 75930277e..747025315 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -388,13 +388,13 @@ func (n *NEO) getRegisteredValidatorsCall(ic *interop.Context, _ []stackitem.Ite // GetValidatorsInternal returns a list of current validators. func (n *NEO) GetValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) (keys.PublicKeys, error) { if vals := n.validators.Load().(keys.PublicKeys); vals != nil { - return vals, nil + return vals.Copy(), nil } standByValidators := bc.GetStandByValidators() si := d.GetStorageItem(n.ContractID, validatorsCountKey) if si == nil { n.validators.Store(standByValidators) - return standByValidators, nil + return standByValidators.Copy(), nil } validatorsCount, err := ValidatorsCountFromBytes(si.Value) if err != nil { From a43e374ac6282ada67d71d4090204d24ec921a76 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Sat, 11 Jul 2020 15:22:14 +0300 Subject: [PATCH 6/6] consensus: replace magic 1000000 with something more meaningful --- pkg/consensus/block.go | 2 +- pkg/consensus/change_view.go | 4 ++-- pkg/consensus/change_view_test.go | 4 ++-- pkg/consensus/consensus.go | 5 ++++- pkg/consensus/consensus_test.go | 2 +- pkg/consensus/prepare_request.go | 4 ++-- pkg/consensus/recovery_message.go | 2 +- pkg/consensus/recovery_request.go | 4 ++-- pkg/consensus/recovery_request_test.go | 4 ++-- 9 files changed, 17 insertions(+), 14 deletions(-) diff --git a/pkg/consensus/block.go b/pkg/consensus/block.go index cc4a77f99..390846fc6 100644 --- a/pkg/consensus/block.go +++ b/pkg/consensus/block.go @@ -65,7 +65,7 @@ func (n *neoBlock) PrevHash() util.Uint256 { return n.Block.PrevHash } func (n *neoBlock) MerkleRoot() util.Uint256 { return n.Block.MerkleRoot } // Timestamp implements block.Block interface. -func (n *neoBlock) Timestamp() uint64 { return n.Block.Timestamp * 1000000 } +func (n *neoBlock) Timestamp() uint64 { return n.Block.Timestamp * nsInMs } // Index implements block.Block interface. func (n *neoBlock) Index() uint32 { return n.Block.Index } diff --git a/pkg/consensus/change_view.go b/pkg/consensus/change_view.go index a292619e9..fedc72c8e 100644 --- a/pkg/consensus/change_view.go +++ b/pkg/consensus/change_view.go @@ -33,10 +33,10 @@ func (c changeView) NewViewNumber() byte { return c.newViewNumber } func (c *changeView) SetNewViewNumber(view byte) { c.newViewNumber = view } // Timestamp implements payload.ChangeView interface. -func (c changeView) Timestamp() uint64 { return c.timestamp * 1000000 } +func (c changeView) Timestamp() uint64 { return c.timestamp * nsInMs } // SetTimestamp implements payload.ChangeView interface. -func (c *changeView) SetTimestamp(ts uint64) { c.timestamp = ts / 1000000 } +func (c *changeView) SetTimestamp(ts uint64) { c.timestamp = ts / nsInMs } // Reason implements payload.ChangeView interface. func (c changeView) Reason() payload.ChangeViewReason { return c.reason } diff --git a/pkg/consensus/change_view_test.go b/pkg/consensus/change_view_test.go index 70fd117ec..eaad6b2db 100644 --- a/pkg/consensus/change_view_test.go +++ b/pkg/consensus/change_view_test.go @@ -9,8 +9,8 @@ import ( func TestChangeView_Setters(t *testing.T) { var c changeView - c.SetTimestamp(123 * 1000000) - require.EqualValues(t, 123*1000000, c.Timestamp()) + c.SetTimestamp(123 * nsInMs) + require.EqualValues(t, 123*nsInMs, c.Timestamp()) c.SetNewViewNumber(2) require.EqualValues(t, 2, c.NewViewNumber()) diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index be9545cff..921da8659 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -32,6 +32,9 @@ const cacheMaxCapacity = 100 // defaultTimePerBlock is a period between blocks which is used in NEO. const defaultTimePerBlock = 15 * time.Second +// Number of nanoseconds in millisecond. +const nsInMs = 1000000 + // Service represents consensus instance. type Service interface { // Start initializes dBFT and starts event loop for consensus service. @@ -488,7 +491,7 @@ func (s *service) newBlockFromContext(ctx *dbft.Context) block.Block { } block.Block.Network = s.network - block.Block.Timestamp = ctx.Timestamp / 1000000 + block.Block.Timestamp = ctx.Timestamp / nsInMs block.Block.Index = ctx.BlockIndex validators, err := s.Chain.GetValidators() diff --git a/pkg/consensus/consensus_test.go b/pkg/consensus/consensus_test.go index f6221894c..569c1acac 100644 --- a/pkg/consensus/consensus_test.go +++ b/pkg/consensus/consensus_test.go @@ -63,7 +63,7 @@ func TestService_GetVerified(t *testing.T) { p.SetPayload(&prepareRequest{transactionHashes: hashes}) } else { p.SetType(payload.ChangeViewType) - p.SetPayload(&changeView{newViewNumber: 1, timestamp: uint64(time.Now().UnixNano() / 1000000)}) + p.SetPayload(&changeView{newViewNumber: 1, timestamp: uint64(time.Now().UnixNano() / nsInMs)}) } p.SetHeight(1) p.SetValidatorIndex(uint16(i)) diff --git a/pkg/consensus/prepare_request.go b/pkg/consensus/prepare_request.go index 26be085ad..cded41ed2 100644 --- a/pkg/consensus/prepare_request.go +++ b/pkg/consensus/prepare_request.go @@ -30,10 +30,10 @@ func (p *prepareRequest) DecodeBinary(r *io.BinReader) { } // Timestamp implements payload.PrepareRequest interface. -func (p *prepareRequest) Timestamp() uint64 { return p.timestamp * 1000000 } +func (p *prepareRequest) Timestamp() uint64 { return p.timestamp * nsInMs } // SetTimestamp implements payload.PrepareRequest interface. -func (p *prepareRequest) SetTimestamp(ts uint64) { p.timestamp = ts / 1000000 } +func (p *prepareRequest) SetTimestamp(ts uint64) { p.timestamp = ts / nsInMs } // Nonce implements payload.PrepareRequest interface. func (p *prepareRequest) Nonce() uint64 { return p.nonce } diff --git a/pkg/consensus/recovery_message.go b/pkg/consensus/recovery_message.go index a9ce3f569..817e241e8 100644 --- a/pkg/consensus/recovery_message.go +++ b/pkg/consensus/recovery_message.go @@ -164,7 +164,7 @@ func (m *recoveryMessage) AddPayload(p payload.ConsensusPayload) { m.changeViewPayloads = append(m.changeViewPayloads, &changeViewCompact{ ValidatorIndex: p.ValidatorIndex(), OriginalViewNumber: p.ViewNumber(), - Timestamp: p.GetChangeView().Timestamp() / 1000000, + Timestamp: p.GetChangeView().Timestamp() / nsInMs, InvocationScript: p.(*Payload).Witness.InvocationScript, }) case payload.CommitType: diff --git a/pkg/consensus/recovery_request.go b/pkg/consensus/recovery_request.go index 630775b86..52e0fb269 100644 --- a/pkg/consensus/recovery_request.go +++ b/pkg/consensus/recovery_request.go @@ -23,7 +23,7 @@ func (m *recoveryRequest) EncodeBinary(w *io.BinWriter) { } // Timestamp implements payload.RecoveryRequest interface. -func (m *recoveryRequest) Timestamp() uint64 { return m.timestamp * 1000000 } +func (m *recoveryRequest) Timestamp() uint64 { return m.timestamp * nsInMs } // SetTimestamp implements payload.RecoveryRequest interface. -func (m *recoveryRequest) SetTimestamp(ts uint64) { m.timestamp = ts / 1000000 } +func (m *recoveryRequest) SetTimestamp(ts uint64) { m.timestamp = ts / nsInMs } diff --git a/pkg/consensus/recovery_request_test.go b/pkg/consensus/recovery_request_test.go index 8bae99aa6..adfc57c51 100644 --- a/pkg/consensus/recovery_request_test.go +++ b/pkg/consensus/recovery_request_test.go @@ -9,6 +9,6 @@ import ( func TestRecoveryRequest_Setters(t *testing.T) { var r recoveryRequest - r.SetTimestamp(123 * 1000000) - require.EqualValues(t, 123*1000000, r.Timestamp()) + r.SetTimestamp(123 * nsInMs) + require.EqualValues(t, 123*nsInMs, r.Timestamp()) }