From 857ced82305d57bbf2de286bd1bf3e55836e7b94 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 26 Jun 2020 18:27:18 +0300 Subject: [PATCH] consensus: add network magic to hash data Consensus payload's hash now depends on the network node is operating in. --- pkg/consensus/consensus.go | 13 ++++++++++++- pkg/consensus/payload.go | 12 ++++++++++-- pkg/consensus/payload_test.go | 23 ++++++++++++++--------- pkg/network/message.go | 2 +- 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index 783501d7f..0cff84edc 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -136,7 +136,7 @@ func NewService(cfg Config) (Service, error) { dbft.WithGetValidators(srv.getValidators), dbft.WithGetConsensusAddress(srv.getConsensusAddress), - dbft.WithNewConsensusPayload(func() payload.ConsensusPayload { p := new(Payload); p.message = &message{}; return p }), + dbft.WithNewConsensusPayload(srv.newPayload), dbft.WithNewPrepareRequest(func() payload.PrepareRequest { return new(prepareRequest) }), dbft.WithNewPrepareResponse(func() payload.PrepareResponse { return new(prepareResponse) }), dbft.WithNewChangeView(func() payload.ChangeView { return new(changeView) }), @@ -157,6 +157,17 @@ var ( _ block.Block = (*neoBlock)(nil) ) +// NewPayload creates new consensus payloa dfor the provided network. +func NewPayload(m netmode.Magic) *Payload { + return &Payload{ + network: m, + } +} + +func (s *service) newPayload() payload.ConsensusPayload { + return NewPayload(s.network) +} + func (s *service) Start() { s.dbft.Start() s.Chain.SubscribeForBlocks(s.blockEvents) diff --git a/pkg/consensus/payload.go b/pkg/consensus/payload.go index f202e4065..31cbaec88 100644 --- a/pkg/consensus/payload.go +++ b/pkg/consensus/payload.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/nspcc-dev/dbft/payload" + "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core" "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/interop/crypto" @@ -30,6 +31,7 @@ type ( Payload struct { *message + network netmode.Magic data []byte version uint32 validatorIndex uint16 @@ -108,7 +110,7 @@ func (p Payload) GetRecoveryMessage() payload.RecoveryMessage { // MarshalUnsigned implements payload.ConsensusPayload interface. func (p Payload) MarshalUnsigned() []byte { w := io.NewBufBinWriter() - p.EncodeBinaryUnsigned(w.BinWriter) + p.encodeHashData(w.BinWriter) return w.Bytes() } @@ -116,6 +118,7 @@ func (p Payload) MarshalUnsigned() []byte { // UnmarshalUnsigned implements payload.ConsensusPayload interface. func (p *Payload) UnmarshalUnsigned(data []byte) error { r := io.NewBinReaderFromBuf(data) + p.network = netmode.Magic(r.ReadU32LE()) p.DecodeBinaryUnsigned(r) return r.Err @@ -184,6 +187,11 @@ func (p *Payload) EncodeBinary(w *io.BinWriter) { p.Witness.EncodeBinary(w) } +func (p *Payload) encodeHashData(w *io.BinWriter) { + w.WriteU32LE(uint32(p.network)) + p.EncodeBinaryUnsigned(w) +} + // Sign signs payload using the private key. // It also sets corresponding verification and invocation scripts. func (p *Payload) Sign(key *privateKey) error { @@ -241,7 +249,7 @@ func (p *Payload) DecodeBinaryUnsigned(r *io.BinReader) { // Hash implements payload.ConsensusPayload interface. func (p *Payload) Hash() util.Uint256 { w := io.NewBufBinWriter() - p.EncodeBinaryUnsigned(w.BinWriter) + p.encodeHashData(w.BinWriter) if w.Err != nil { panic("failed to hash payload") } diff --git a/pkg/consensus/payload_test.go b/pkg/consensus/payload_test.go index c5563beea..45d44c6cc 100644 --- a/pkg/consensus/payload_test.go +++ b/pkg/consensus/payload_test.go @@ -1,10 +1,12 @@ package consensus import ( + "encoding/hex" "math/rand" "testing" "github.com/nspcc-dev/dbft/payload" + "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/internal/random" @@ -73,18 +75,21 @@ func TestConsensusPayload_Setters(t *testing.T) { require.Equal(t, pl, p.GetRecoveryMessage()) } -//TODO NEO3.0: Update binary -/* -func TestConsensusPayload_Hash(t *testing.T) { - dataHex := "00000000d8fb8d3b143b5f98468ef701909c976505a110a01e26c5e99be9a90cff979199b6fc33000400000000008d2000184dc95de24018f9ad71f4448a2b438eaca8b4b2ab6b4524b5a69a45d920c35103f3901444320656c390ff39c0062f5e8e138ce446a40c7e4ba1af1f8247ebbdf49295933715d3a67949714ff924f8a28cec5b954c71eca3bfaf0e9d4b1f87b4e21e9ba4ae18f97de71501b5c5d07edc200bd66a46b9b28b1a371f2195c10b0af90000e24018f900000000014140c9faaee59942f58da0e5268bc199632f2a3ad0fcbee68681a4437f140b49512e8d9efc6880eb44d3490782895a5794f35eeccee2923ce0c76fa7a1890f934eac232103c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c1ac" +func TestConsensusPayload_Verify(t *testing.T) { + // signed payload from testnet + dataHex := "00000000a70b769e4af60878f6daa72be41770c62592c694bf9ead6b16b30ad90f28c4098cc704000400423000d5b4baae11191ac370a4d7860df01824fcea7f934d6461db6d4b7966ca3c135c8c262b7f23bbac13e73885223604141e062234d999068d9a74b77caeeb5271cf01420c4055ae8c7694c296e92da393f944b0dc1cd70d12de3ee944e9afc872d1db427fe87fcbe913709a8ec73e2f5acdfc0b7f0a96e9d63bad0a20e3226c882237f5c771290c2102a7834be9b32e2981d157cb5bbd3acb42cfd11ea5c3b10224d7a44e98c5910f1b0b410a906ad4" data, err := hex.DecodeString(dataHex) require.NoError(t, err) - var p Payload - require.NoError(t, testserdes.DecodeBinary(data, &p)) - require.Equal(t, p.Hash().String(), "45859759c8491597804f1922773947e0d37bf54484af82f80cd642f7b063aa56") + h, err := util.Uint160DecodeStringBE("31b7e7aea5131f74721e002c6a56b6885813f79e") + require.NoError(t, err) + + p := NewPayload(netmode.TestNet) + require.NoError(t, testserdes.DecodeBinary(data, p)) + require.NoError(t, p.decodeData()) + require.True(t, p.Verify(h)) } -*/ + func TestConsensusPayload_Serializable(t *testing.T) { for _, mt := range messageTypes { p := randomPayload(t, mt) @@ -99,7 +104,7 @@ func TestConsensusPayload_Serializable(t *testing.T) { require.Equal(t, p, actual) data = p.MarshalUnsigned() - pu := new(Payload) + pu := NewPayload(netmode.Magic(rand.Uint32())) require.NoError(t, pu.UnmarshalUnsigned(data)) assert.NoError(t, pu.decodeData()) diff --git a/pkg/network/message.go b/pkg/network/message.go index bb0678d79..c61600ac4 100644 --- a/pkg/network/message.go +++ b/pkg/network/message.go @@ -144,7 +144,7 @@ func (m *Message) decodePayload() error { case CMDBlock: p = block.New(m.Network) case CMDConsensus: - p = &consensus.Payload{} + p = consensus.NewPayload(m.Network) case CMDGetBlocks: fallthrough case CMDGetHeaders: