Skip to content

Commit

Permalink
Add merkle recent blocks (#122)
Browse files Browse the repository at this point in the history
  • Loading branch information
bamzedev authored Nov 19, 2024
1 parent 7603ea5 commit 5680cfc
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 14 deletions.
2 changes: 1 addition & 1 deletion internal/state/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ import (
type BlockState struct {
HeaderHash crypto.Hash // Hash of the block header (h)
StateRoot crypto.Hash // State root (b)
AccumulationResultMMR crypto.Hash // Accumulation-result MMR (s)
AccumulationResultMMR []*crypto.Hash // Accumulation-result MMR (s)
WorkReportHashes map[crypto.Hash]crypto.Hash // Hashes of work-reports (p)
}
3 changes: 2 additions & 1 deletion internal/state/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ func RandomBlockState(t *testing.T) BlockState {
var state BlockState
state.HeaderHash = testutils.RandomHash(t)
state.StateRoot = testutils.RandomHash(t)
state.AccumulationResultMMR = testutils.RandomHash(t)
h := testutils.RandomHash(t)
state.AccumulationResultMMR = []*crypto.Hash{&h}
workReportHashes := make(map[crypto.Hash]crypto.Hash)
for i := uint16(0); i < common.TotalNumberOfCores; i++ {
workReportHashes[testutils.RandomHash(t)] = testutils.RandomHash(t)
Expand Down
63 changes: 51 additions & 12 deletions internal/statetransition/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/eigerco/strawberry/pkg/serialization/codec/jam"
"log"
"maps"
"slices"
"sort"
"sync"

"github.com/eigerco/strawberry/pkg/serialization/codec/jam"

"github.com/eigerco/strawberry/internal/block"
"github.com/eigerco/strawberry/internal/common"
"github.com/eigerco/strawberry/internal/crypto"
"github.com/eigerco/strawberry/internal/jamtime"
"github.com/eigerco/strawberry/internal/merkle/binary_tree"
"github.com/eigerco/strawberry/internal/merkle/mountain_ranges"
"github.com/eigerco/strawberry/internal/polkavm"
"github.com/eigerco/strawberry/internal/safrole"
"github.com/eigerco/strawberry/internal/service"
Expand Down Expand Up @@ -294,14 +297,22 @@ func calculateNewTimeState(header block.Header) jamtime.Timeslot {
// calculateNewRecentBlocks Equation 18: β′ ≺ (H, EG, β†, C) v0.4.5
func calculateNewRecentBlocks(header block.Header, guarantees block.GuaranteesExtrinsic, intermediateRecentBlocks []state.BlockState, serviceHashPairs ServiceHashPairs) ([]state.BlockState, error) {
// Equation 83: let r = M_B([s ^^ E_4(s) ⌢ E(h) | (s, h) ∈ C], H_K)
accumulationRoot := calculateAccumulationRoot(serviceHashPairs)
accumulationRoot, err := computeAccumulationRoot(serviceHashPairs)
if err != nil {
return nil, err
}

// Equation 83: let b = A(last([[]] ⌢ [x_b | x <− β]), r, H_K)
var lastBlockMMR crypto.Hash
var lastBlockMMR []*crypto.Hash
if len(intermediateRecentBlocks) > 0 {
lastBlockMMR = intermediateRecentBlocks[len(intermediateRecentBlocks)-1].AccumulationResultMMR
}
newMMR := AppendToMMR(lastBlockMMR, accumulationRoot)
// Create new MMR instance
mountainRange := mountain_ranges.New()

// Append the accumulation root to the MMR using Keccak hash
// A(last([[]] ⌢ [x_b | x <− β]), r, H_K)
newMMR := mountainRange.Append(lastBlockMMR, accumulationRoot, crypto.KeccakData)

// Equation 83: p = {((g_w)_s)_h ↦ ((g_w)_s)_e | g ∈ E_G}
workPackageMapping := buildWorkPackageMapping(guarantees.Guarantees)
Expand Down Expand Up @@ -330,15 +341,43 @@ func calculateNewRecentBlocks(header block.Header, guarantees block.GuaranteesEx
return newRecentBlocks, nil
}

// TODO: this is just a mock implementation
func AppendToMMR(lastBlockMMR crypto.Hash, accumulationRoot crypto.Hash) crypto.Hash {
return crypto.Hash{}
}
// This should create a Merkle tree from the accumulations and return the root ("r" from equation 83, v0.4.5)
func computeAccumulationRoot(pairs ServiceHashPairs) (crypto.Hash, error) {
if len(pairs) == 0 {
return crypto.Hash{}, nil
}

// Sort pairs to ensure deterministic ordering
sort.Slice(pairs, func(i, j int) bool {
return pairs[i].ServiceId < pairs[j].ServiceId
})

// Create sequence of [s ^^ E_4(s) ⌢ E(h)] for each (s,h) pair
items := make([][]byte, len(pairs))
for i, pair := range pairs {
// Create concatenated item
item := make([]byte, 0)

s, err := jam.Marshal(pair.ServiceId)
if err != nil {
return crypto.Hash{}, err
}

// Append service ID encoding
item = append(item, s...)

h, err := jam.Marshal(pair.Hash)
if err != nil {
return crypto.Hash{}, err
}
// Append hash encoding
item = append(item, h...)

items[i] = item
}

// TODO: this is just a mock implementation
// This should create a Merkle tree from the accumulations and return the root
func calculateAccumulationRoot(accumulations ServiceHashPairs) crypto.Hash {
return crypto.Hash{}
// Compute MB([s ^^ E_4(s) ⌢ E(h)], HK) using well-balanced Merkle tree
return binary_tree.ComputeWellBalancedRoot(items, crypto.KeccakData), nil
}

// buildWorkPackageMapping creates the work package mapping p from equation 83:
Expand Down

0 comments on commit 5680cfc

Please sign in to comment.