Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ledger/common/hash/sha3.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func (d *state) hash256Plus(p1 Hash, p2 []byte) Hash {
}

// hash256plus256 absorbs two 256 bits slices of data into the hash's state
// applies the permutation, and outpute the result in out
// applies the permutation, and outputs the result in out
func (d *state) hash256plus256(p1, p2 Hash) Hash {
copyIn512(d, p1, p2)
// permute
Expand Down
27 changes: 27 additions & 0 deletions ledger/common/hash/sha3_internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package hash

import (
"crypto/rand"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// Test_hash256Plus_matches_hash256plus256 checks that for a 32-byte p2 the two
// absorption routines produce the same digest. hash256Plus is the variable-length
// path (p1 is 256 bits, p2 is an arbitrary-length slice) while hash256plus256 is the
// fixed 256+256-bit fast path. When p2 is exactly 32 bytes both absorb the identical
// 512-bit input under the same SHA3-256 padding, so their outputs must be equal.
func Test_hash256Plus_matches_hash256plus256(t *testing.T) {
var p1, p2 Hash
_, err := rand.Read(p1[:])
require.NoError(t, err)
_, err = rand.Read(p2[:])
require.NoError(t, err)

h1 := (&state{}).hash256Plus(p1, p2[:])
h2 := (&state{}).hash256plus256(p1, p2)

assert.Equal(t, h1, h2)
}
96 changes: 49 additions & 47 deletions ledger/complete/mtrie/README.md

Large diffs are not rendered by default.

31 changes: 24 additions & 7 deletions ledger/complete/mtrie/trie/trie_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import (
)

// TestEmptyTrie tests whether the root hash of an empty trie matches the formal specification.
// The expected value originates from the standalone Merkle reference implementation (the source of
// truth): github.com/onflow/flow-internal → reference_implementations/merkle_tree.py. Run it to
// regenerate; MTrie is the implementation under test, checked against it.
func Test_EmptyTrie(t *testing.T) {
// Make new Trie (independently of MForest):
emptyTrie := trie.NewEmptyMTrie()
Expand All @@ -36,7 +39,9 @@ func Test_EmptyTrie(t *testing.T) {

// Test_TrieWithLeftRegister tests whether the root hash of trie with only the left-most
// register populated matches the formal specification.
// The expected value is coming from a reference implementation in python and is hard-coded here.
// The expected value originates from the standalone Merkle reference implementation (the source of
// truth): github.com/onflow/flow-internal → reference_implementations/merkle_tree.py. Run it to
// regenerate; MTrie is the implementation under test, checked against it.
func Test_TrieWithLeftRegister(t *testing.T) {
// Make new Trie (independently of MForest):
emptyTrie := trie.NewEmptyMTrie()
Expand All @@ -53,7 +58,9 @@ func Test_TrieWithLeftRegister(t *testing.T) {

// Test_TrieWithRightRegister tests whether the root hash of trie with only the right-most
// register populated matches the formal specification.
// The expected value is coming from a reference implementation in python and is hard-coded here.
// The expected value originates from the standalone Merkle reference implementation (the source of
// truth): github.com/onflow/flow-internal → reference_implementations/merkle_tree.py. Run it to
// regenerate; MTrie is the implementation under test, checked against it.
func Test_TrieWithRightRegister(t *testing.T) {
// Make new Trie (independently of MForest):
emptyTrie := trie.NewEmptyMTrie()
Expand All @@ -74,7 +81,9 @@ func Test_TrieWithRightRegister(t *testing.T) {

// Test_TrieWithMiddleRegister tests the root hash of trie holding only a single
// allocated register somewhere in the middle.
// The expected value is coming from a reference implementation in python and is hard-coded here.
// The expected value originates from the standalone Merkle reference implementation (the source of
// truth): github.com/onflow/flow-internal → reference_implementations/merkle_tree.py. Run it to
// regenerate; MTrie is the implementation under test, checked against it.
func Test_TrieWithMiddleRegister(t *testing.T) {
// Make new Trie (independently of MForest):
emptyTrie := trie.NewEmptyMTrie()
Expand All @@ -92,7 +101,9 @@ func Test_TrieWithMiddleRegister(t *testing.T) {

// Test_TrieWithManyRegisters tests whether the root hash of a trie storing 12001 randomly selected registers
// matches the formal specification.
// The expected value is coming from a reference implementation in python and is hard-coded here.
// The expected value originates from the standalone Merkle reference implementation (the source of
// truth): github.com/onflow/flow-internal → reference_implementations/merkle_tree.py. Run it to
// regenerate; MTrie is the implementation under test, checked against it.
func Test_TrieWithManyRegisters(t *testing.T) {
// Make new Trie (independently of MForest):
emptyTrie := trie.NewEmptyMTrie()
Expand All @@ -114,7 +125,9 @@ func Test_TrieWithManyRegisters(t *testing.T) {

// Test_FullTrie tests whether the root hash of a trie,
// whose left-most 65536 registers are populated, matches the formal specification.
// The expected value is coming from a reference implementation in python and is hard-coded here.
// The expected value originates from the standalone Merkle reference implementation (the source of
// truth): github.com/onflow/flow-internal → reference_implementations/merkle_tree.py. Run it to
// regenerate; MTrie is the implementation under test, checked against it.
func Test_FullTrie(t *testing.T) {
// Make new Trie (independently of MForest):
emptyTrie := trie.NewEmptyMTrie()
Expand Down Expand Up @@ -142,7 +155,9 @@ func Test_FullTrie(t *testing.T) {
}

// TestUpdateTrie tests whether iteratively updating a Trie matches the formal specification.
// The expected root hashes are coming from a reference implementation in python and is hard-coded here.
// The expected root hashes originate from the standalone Merkle reference implementation (the source
// of truth): github.com/onflow/flow-internal → reference_implementations/merkle_tree.py. Run it to
// regenerate; MTrie is the implementation under test, checked against it.
func Test_UpdateTrie(t *testing.T) {
expectedRootHashes := []string{
"08db9aeed2b9fcc66b63204a26a4c28652e44e3035bd87ba0ed632a227b3f6dd",
Expand Down Expand Up @@ -223,7 +238,9 @@ func Test_UpdateTrie(t *testing.T) {

// Test_UnallocateRegisters tests whether unallocating registers matches the formal specification.
// Unallocating here means, to set the stored register value to an empty byte slice.
// The expected value is coming from a reference implementation in python and is hard-coded here.
// The expected value originates from the standalone Merkle reference implementation (the source of
// truth): github.com/onflow/flow-internal → reference_implementations/merkle_tree.py. Run it to
// regenerate; MTrie is the implementation under test, checked against it.
func Test_UnallocateRegisters(t *testing.T) {
rng := &LinearCongruentialGenerator{seed: 0}
emptyTrie := trie.NewEmptyMTrie()
Expand Down
Loading