forked from TrueCloudLab/neoneo-go
Merge pull request #1620 from nspcc-dev/fix/consensus
consensus: validate timestamp in `verifyBlock()`
This commit is contained in:
commit
f2365e2392
4 changed files with 27 additions and 3 deletions
2
go.mod
2
go.mod
|
@ -11,7 +11,7 @@ require (
|
|||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/mr-tron/base58 v1.1.2
|
||||
github.com/nspcc-dev/dbft v0.0.0-20201109143252-cd27d76617ed
|
||||
github.com/nspcc-dev/dbft v0.0.0-20201216144126-a4bc58feae87
|
||||
github.com/nspcc-dev/rfc6979 v0.2.0
|
||||
github.com/pierrec/lz4 v2.5.2+incompatible
|
||||
github.com/prometheus/client_golang v1.2.1
|
||||
|
|
4
go.sum
4
go.sum
|
@ -166,8 +166,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-20201109143252-cd27d76617ed h1:T4qjutPMqjnYDQFyrbCew3lGeJt6MIbNyNn7gRx0o/g=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20201109143252-cd27d76617ed/go.mod h1:I5D0W3tu3epdt2RMCTxS//HDr4S+OHRqajouQTOAHI8=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20201216144126-a4bc58feae87 h1:sKV7BKdp2iDW39AkGp0GPGHRDuR9vgQT7gDdMKMkuOI=
|
||||
github.com/nspcc-dev/dbft v0.0.0-20201216144126-a4bc58feae87/go.mod h1:I5D0W3tu3epdt2RMCTxS//HDr4S+OHRqajouQTOAHI8=
|
||||
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=
|
||||
|
|
|
@ -81,6 +81,11 @@ type service struct {
|
|||
started *atomic.Bool
|
||||
quit chan struct{}
|
||||
finished chan struct{}
|
||||
// lastTimestamp contains timestamp for the last processed block.
|
||||
// We can't rely on timestamp from dbft context because it is changed
|
||||
// before block is accepted, so in case of change view it will contain
|
||||
// updated value.
|
||||
lastTimestamp uint64
|
||||
}
|
||||
|
||||
// Config is a configuration for consensus services.
|
||||
|
@ -298,6 +303,9 @@ func (s *service) handleChainBlock(b *coreb.Block) {
|
|||
s.log.Debug("new block in the chain",
|
||||
zap.Uint32("dbft index", s.dbft.BlockIndex),
|
||||
zap.Uint32("chain index", s.Chain.BlockHeight()))
|
||||
if s.lastTimestamp < b.Timestamp {
|
||||
s.lastTimestamp = b.Timestamp
|
||||
}
|
||||
s.dbft.InitializeConsensus(0)
|
||||
}
|
||||
}
|
||||
|
@ -418,6 +426,12 @@ func (s *service) verifyBlock(b block.Block) bool {
|
|||
s.log.Warn("proposed block has already outdated")
|
||||
return false
|
||||
}
|
||||
if s.lastTimestamp >= coreb.Timestamp {
|
||||
s.log.Warn("proposed block has small timestamp",
|
||||
zap.Uint64("ts", coreb.Timestamp),
|
||||
zap.Uint64("last", s.lastTimestamp))
|
||||
return false
|
||||
}
|
||||
maxBlockSize := int(s.Chain.GetPolicer().GetMaxBlockSize())
|
||||
size := io.GetVarSize(coreb)
|
||||
if size > maxBlockSize {
|
||||
|
@ -492,6 +506,9 @@ func (s *service) processBlock(b block.Block) {
|
|||
s.log.Warn("error on add block", zap.Error(err))
|
||||
}
|
||||
}
|
||||
if s.lastTimestamp < bb.Timestamp {
|
||||
s.lastTimestamp = bb.Timestamp
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) getBlockWitness(b *coreb.Block) *transaction.Witness {
|
||||
|
|
|
@ -344,6 +344,8 @@ func TestService_OnPayload(t *testing.T) {
|
|||
func TestVerifyBlock(t *testing.T) {
|
||||
srv := newTestService(t)
|
||||
defer srv.Chain.Close()
|
||||
|
||||
srv.lastTimestamp = 1
|
||||
t.Run("good empty", func(t *testing.T) {
|
||||
b := testchain.NewBlock(t, srv.Chain, 1, 0)
|
||||
require.True(t, srv.verifyBlock(&neoBlock{Block: *b}))
|
||||
|
@ -386,6 +388,11 @@ func TestVerifyBlock(t *testing.T) {
|
|||
b.Index = srv.Chain.BlockHeight()
|
||||
require.False(t, srv.verifyBlock(&neoBlock{Block: *b}))
|
||||
})
|
||||
t.Run("bad timestamp", func(t *testing.T) {
|
||||
b := testchain.NewBlock(t, srv.Chain, 1, 0)
|
||||
b.Timestamp = srv.lastTimestamp - 1
|
||||
require.False(t, srv.verifyBlock(&neoBlock{Block: *b}))
|
||||
})
|
||||
t.Run("bad big size", func(t *testing.T) {
|
||||
script := make([]byte, int(srv.Chain.GetPolicer().GetMaxBlockSize()))
|
||||
script[0] = byte(opcode.RET)
|
||||
|
|
Loading…
Reference in a new issue