diff --git a/internal/trie/node/branch_encode.go b/internal/trie/node/branch_encode.go index 78d55502431..9ed2bed8d23 100644 --- a/internal/trie/node/branch_encode.go +++ b/internal/trie/node/branch_encode.go @@ -133,7 +133,7 @@ func encodeChild(child *Node, buffer io.Writer) (err error) { // and then SCALE encodes it. This is used to encode children // nodes of branches. func scaleEncodeHash(node *Node) (encoding []byte, err error) { - _, merkleValue, err := node.EncodeAndHash() + merkleValue, err := node.CalculateMerkleValue() if err != nil { return nil, fmt.Errorf("encoding and hashing %s: %w", node.Kind(), err) } diff --git a/lib/trie/buffer_mock_test.go b/lib/trie/buffer_mock_test.go deleted file mode 100644 index 6f76b676c41..00000000000 --- a/lib/trie/buffer_mock_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ChainSafe/gossamer/internal/trie/node (interfaces: Buffer) - -// Package trie is a generated GoMock package. -package trie - -import ( - reflect "reflect" - - gomock "github.com/golang/mock/gomock" -) - -// MockBuffer is a mock of Buffer interface. -type MockBuffer struct { - ctrl *gomock.Controller - recorder *MockBufferMockRecorder -} - -// MockBufferMockRecorder is the mock recorder for MockBuffer. -type MockBufferMockRecorder struct { - mock *MockBuffer -} - -// NewMockBuffer creates a new mock instance. -func NewMockBuffer(ctrl *gomock.Controller) *MockBuffer { - mock := &MockBuffer{ctrl: ctrl} - mock.recorder = &MockBufferMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockBuffer) EXPECT() *MockBufferMockRecorder { - return m.recorder -} - -// Bytes mocks base method. -func (m *MockBuffer) Bytes() []byte { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Bytes") - ret0, _ := ret[0].([]byte) - return ret0 -} - -// Bytes indicates an expected call of Bytes. -func (mr *MockBufferMockRecorder) Bytes() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Bytes", reflect.TypeOf((*MockBuffer)(nil).Bytes)) -} - -// Len mocks base method. -func (m *MockBuffer) Len() int { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Len") - ret0, _ := ret[0].(int) - return ret0 -} - -// Len indicates an expected call of Len. -func (mr *MockBufferMockRecorder) Len() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Len", reflect.TypeOf((*MockBuffer)(nil).Len)) -} - -// Write mocks base method. -func (m *MockBuffer) Write(arg0 []byte) (int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Write", arg0) - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Write indicates an expected call of Write. -func (mr *MockBufferMockRecorder) Write(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*MockBuffer)(nil).Write), arg0) -} diff --git a/lib/trie/helpers_test.go b/lib/trie/helpers_test.go index a03c24f857d..507317a964b 100644 --- a/lib/trie/helpers_test.go +++ b/lib/trie/helpers_test.go @@ -4,7 +4,6 @@ package trie import ( - "errors" "math/rand" "testing" "time" @@ -13,14 +12,6 @@ import ( "github.com/stretchr/testify/require" ) -type writeCall struct { - written []byte - n int - err error -} - -var errTest = errors.New("test error") - type keyValues struct { key []byte value []byte diff --git a/lib/trie/trie.go b/lib/trie/trie.go index c3fd7f320fc..c42afefd2af 100644 --- a/lib/trie/trie.go +++ b/lib/trie/trie.go @@ -13,7 +13,7 @@ import ( ) // EmptyHash is the empty trie hash. -var EmptyHash, _ = NewEmptyTrie().Hash() +var EmptyHash = common.MustBlake2bHash([]byte{0}) // Trie is a base 16 modified Merkle Patricia trie. type Trie struct { @@ -170,18 +170,6 @@ func (t *Trie) RootNode() *Node { return t.root.Copy(copySettings) } -// encodeRoot writes the encoding of the root node to the buffer. -func encodeRoot(root *Node, buffer node.Buffer) (err error) { - if root == nil { - _, err = buffer.Write([]byte{0}) - if err != nil { - return fmt.Errorf("cannot write nil root node to buffer: %w", err) - } - return nil - } - return root.Encode(buffer) -} - // MustHash returns the hashed root of the trie. // It panics if it fails to hash the root node. func (t *Trie) MustHash() common.Hash { @@ -195,13 +183,17 @@ func (t *Trie) MustHash() common.Hash { // Hash returns the hashed root of the trie. func (t *Trie) Hash() (rootHash common.Hash, err error) { - buffer := bytes.NewBuffer(nil) - err = encodeRoot(t.root, buffer) - if err != nil { - return [32]byte{}, err + if t.root == nil { + return EmptyHash, nil } - return common.Blake2bHash(buffer.Bytes()) // TODO optimisation: use hashers sync pools + merkleValue, err := t.root.CalculateRootMerkleValue() + if err != nil { + // no need to wrap the error really + return rootHash, err + } + copy(rootHash[:], merkleValue) + return rootHash, nil } // Entries returns all the key-value pairs in the trie as a map of keys to values diff --git a/lib/trie/trie_test.go b/lib/trie/trie_test.go index d799fa9f663..76d96ba1385 100644 --- a/lib/trie/trie_test.go +++ b/lib/trie/trie_test.go @@ -11,11 +11,22 @@ import ( "github.com/ChainSafe/gossamer/internal/trie/node" "github.com/ChainSafe/gossamer/lib/common" - gomock "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +func Test_EmptyHash(t *testing.T) { + t.Parallel() + + expected := common.Hash{ + 0x3, 0x17, 0xa, 0x2e, 0x75, 0x97, 0xb7, 0xb7, + 0xe3, 0xd8, 0x4c, 0x5, 0x39, 0x1d, 0x13, 0x9a, + 0x62, 0xb1, 0x57, 0xe7, 0x87, 0x86, 0xd8, 0xc0, + 0x82, 0xf2, 0x9d, 0xcf, 0x4c, 0x11, 0x13, 0x14, + } + assert.Equal(t, expected, EmptyHash) +} + func Test_NewEmptyTrie(t *testing.T) { expectedTrie := &Trie{ childTries: make(map[common.Hash]*Trie), @@ -290,99 +301,6 @@ func Test_Trie_RootNode(t *testing.T) { assert.Equal(t, expectedRoot, root) } -//go:generate mockgen -destination=buffer_mock_test.go -package $GOPACKAGE github.com/ChainSafe/gossamer/internal/trie/node Buffer - -func Test_encodeRoot(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - root *Node - writeCalls []writeCall - errWrapped error - errMessage string - expectedRoot *Node - }{ - "nil root and no error": { - writeCalls: []writeCall{ - {written: []byte{0}}, - }, - }, - "nil root and write error": { - writeCalls: []writeCall{ - { - written: []byte{0}, - err: errTest, - }, - }, - errWrapped: errTest, - errMessage: "cannot write nil root node to buffer: test error", - }, - "root encoding error": { - root: &Node{ - Key: []byte{1, 2}, - SubValue: []byte{1}, - }, - writeCalls: []writeCall{ - { - written: []byte{66}, - err: errTest, - }, - }, - errWrapped: errTest, - errMessage: "cannot encode header: test error", - expectedRoot: &Node{ - Key: []byte{1, 2}, - SubValue: []byte{1}, - }, - }, - "root encoding success": { - root: &Node{ - Key: []byte{1, 2}, - SubValue: []byte{1}, - }, - writeCalls: []writeCall{ - {written: []byte{66}}, - {written: []byte{18}}, - {written: []byte{4, 1}}, - }, - expectedRoot: &Node{ - Key: []byte{1, 2}, - SubValue: []byte{1}, - }, - }, - } - - for name, testCase := range testCases { - testCase := testCase - t.Run(name, func(t *testing.T) { - t.Parallel() - ctrl := gomock.NewController(t) - - buffer := NewMockBuffer(ctrl) - - var previousCall *gomock.Call - for _, write := range testCase.writeCalls { - call := buffer.EXPECT(). - Write(write.written). - Return(write.n, write.err) - - if previousCall != nil { - call.After(previousCall) - } - previousCall = call - } - - err := encodeRoot(testCase.root, buffer) - - assert.ErrorIs(t, err, testCase.errWrapped) - if testCase.errWrapped != nil { - assert.EqualError(t, err, testCase.errMessage) - } - assert.Equal(t, testCase.expectedRoot, testCase.root) - }) - } -} - func Test_Trie_MustHash(t *testing.T) { t.Parallel() @@ -435,6 +353,12 @@ func Test_Trie_Hash(t *testing.T) { root: &Node{ Key: []byte{1, 2, 3}, SubValue: []byte{1}, + MerkleValue: []byte{ + 0xa8, 0x13, 0x7c, 0xee, 0xb4, 0xad, 0xea, 0xac, + 0x9e, 0x5b, 0x37, 0xe2, 0x8e, 0x7d, 0x64, 0x78, + 0xac, 0xba, 0xb0, 0x6e, 0x90, 0x76, 0xe4, 0x67, + 0xa1, 0xd8, 0xa2, 0x29, 0x4e, 0x4a, 0xd9, 0xa3, + }, }, }, }, @@ -456,8 +380,14 @@ func Test_Trie_Hash(t *testing.T) { 0xf0, 0xe, 0xd3, 0x39, 0x48, 0x21, 0xe3, 0xdd}, expectedTrie: Trie{ root: &Node{ - Key: []byte{1, 2, 3}, - SubValue: []byte("branch"), + Key: []byte{1, 2, 3}, + SubValue: []byte("branch"), + MerkleValue: []byte{ + 0xaa, 0x7e, 0x57, 0x48, 0xb0, 0x27, 0x4d, 0x18, + 0xf5, 0x1c, 0xfd, 0x36, 0x4c, 0x4b, 0x56, 0x4a, + 0xf5, 0x37, 0x9d, 0xd7, 0xcb, 0xf5, 0x80, 0x15, + 0xf0, 0x0e, 0xd3, 0x39, 0x48, 0x21, 0xe3, 0xdd, + }, Descendants: 1, Children: padRightChildren([]*Node{ {