Skip to content

Commit

Permalink
[3/3] - Replace Legacy History Commitment Implementation (#686)
Browse files Browse the repository at this point in the history
Co-authored-by: Pepper Lebeck-Jobe <[email protected]>
  • Loading branch information
rauljordan and eljobe authored Oct 16, 2024
1 parent 72d28cf commit a85df38
Show file tree
Hide file tree
Showing 22 changed files with 1,234 additions and 1,051 deletions.
6 changes: 3 additions & 3 deletions chain-abstraction/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

"github.com/OffchainLabs/bold/containers/option"
"github.com/OffchainLabs/bold/solgen/go/rollupgen"
commitments "github.com/OffchainLabs/bold/state-commitments/history"
"github.com/OffchainLabs/bold/state-commitments/history"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -289,15 +289,15 @@ type SpecChallengeManager interface {
ctx context.Context,
assertion Assertion,
startCommit,
endCommit commitments.History,
endCommit history.History,
startEndPrefixProof []byte,
) (VerifiedRoyalEdge, error)
// Adds a level-zero edge to subchallenge given a source edge and history commitments.
AddSubChallengeLevelZeroEdge(
ctx context.Context,
challengedEdge SpecEdge,
startCommit,
endCommit commitments.History,
endCommit history.History,
startParentInclusionProof []common.Hash,
endParentInclusionProof []common.Hash,
startEndPrefixProof []byte,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
"github.com/OffchainLabs/bold/solgen/go/challengeV2gen"
"github.com/OffchainLabs/bold/solgen/go/ospgen"
"github.com/OffchainLabs/bold/solgen/go/rollupgen"
commitments "github.com/OffchainLabs/bold/state-commitments/history"
"github.com/OffchainLabs/bold/state-commitments/history"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -916,7 +916,7 @@ func (cm *specChallengeManager) AddBlockChallengeLevelZeroEdge(
ctx context.Context,
assertion protocol.Assertion,
startCommit,
endCommit commitments.History,
endCommit history.History,
startEndPrefixProof []byte,
) (protocol.VerifiedRoyalEdge, error) {
assertionCreation, err := cm.assertionChain.ReadAssertionCreationInfo(ctx, assertion.Id())
Expand Down Expand Up @@ -1051,7 +1051,7 @@ func (cm *specChallengeManager) AddSubChallengeLevelZeroEdge(
ctx context.Context,
challengedEdge protocol.SpecEdge,
startCommit,
endCommit commitments.History,
endCommit history.History,
startParentInclusionProof,
endParentInclusionProof []common.Hash,
startEndPrefixProof []byte,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
l2stateprovider "github.com/OffchainLabs/bold/layer2-state-provider"
"github.com/OffchainLabs/bold/solgen/go/mocksgen"
"github.com/OffchainLabs/bold/solgen/go/rollupgen"
commitments "github.com/OffchainLabs/bold/state-commitments/history"
"github.com/OffchainLabs/bold/state-commitments/history"
challenge_testing "github.com/OffchainLabs/bold/testing"
stateprovider "github.com/OffchainLabs/bold/testing/mocks/state-provider"
"github.com/OffchainLabs/bold/testing/setup"
Expand Down Expand Up @@ -681,8 +681,8 @@ type bisectionScenario struct {
evilStateManager l2stateprovider.Provider
honestLevelZeroEdge protocol.SpecEdge
evilLevelZeroEdge protocol.SpecEdge
honestStartCommit commitments.History
evilStartCommit commitments.History
honestStartCommit history.History
evilStartCommit history.History
}

func setupBisectionScenario(
Expand All @@ -699,7 +699,7 @@ func setupBisectionScenario(
require.NoError(t, err)

// Honest assertion being added.
leafAdder := func(stateManager l2stateprovider.Provider, leaf protocol.Assertion) (commitments.History, protocol.SpecEdge) {
leafAdder := func(stateManager l2stateprovider.Provider, leaf protocol.Assertion) (history.History, protocol.SpecEdge) {
req := &l2stateprovider.HistoryCommitmentRequest{
WasmModuleRoot: common.Hash{},
FromBatch: 0,
Expand Down
26 changes: 13 additions & 13 deletions challenge-manager/edge-tracker/tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
l2stateprovider "github.com/OffchainLabs/bold/layer2-state-provider"
"github.com/OffchainLabs/bold/math"
retry "github.com/OffchainLabs/bold/runtime"
commitments "github.com/OffchainLabs/bold/state-commitments/history"
"github.com/OffchainLabs/bold/state-commitments/history"
utilTime "github.com/OffchainLabs/bold/time"
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -471,12 +471,12 @@ func (et *Tracker) tryToConfirmEdge(ctx context.Context) (bool, error) {
// commitment with a prefix proof for the action based on the challenge type.
func (et *Tracker) DetermineBisectionHistoryWithProof(
ctx context.Context,
) (commitments.History, []byte, error) {
) (history.History, []byte, error) {
startHeight, _ := et.edge.StartCommitment()
endHeight, _ := et.edge.EndCommitment()
bisectTo, err := math.Bisect(uint64(startHeight), uint64(endHeight))
if err != nil {
return commitments.History{}, nil, errors.Wrapf(err, "determining bisection point errored for %d and %d", startHeight, endHeight)
return history.History{}, nil, errors.Wrapf(err, "determining bisection point errored for %d and %d", startHeight, endHeight)
}
challengeLevel := et.edge.GetChallengeLevel()
if challengeLevel == protocol.NewBlockChallengeLevel() {
Expand All @@ -492,7 +492,7 @@ func (et *Tracker) DetermineBisectionHistoryWithProof(
},
)
if commitErr != nil {
return commitments.History{}, nil, commitErr
return history.History{}, nil, commitErr
}
proof, proofErr := et.stateProvider.PrefixProof(
ctx,
Expand All @@ -507,18 +507,18 @@ func (et *Tracker) DetermineBisectionHistoryWithProof(
l2stateprovider.Height(bisectTo),
)
if proofErr != nil {
return commitments.History{}, nil, proofErr
return history.History{}, nil, proofErr
}
return historyCommit, proof, nil
}
var historyCommit commitments.History
var historyCommit history.History
var commitErr error
var proof []byte
var proofErr error

originHeights, err := et.edge.TopLevelClaimHeight(ctx)
if err != nil {
return commitments.History{}, nil, err
return history.History{}, nil, err
}
challengeOriginHeights := make([]l2stateprovider.Height, len(originHeights.ChallengeOriginHeights))
for index, height := range originHeights.ChallengeOriginHeights {
Expand All @@ -537,7 +537,7 @@ func (et *Tracker) DetermineBisectionHistoryWithProof(
},
)
if commitErr != nil {
return commitments.History{}, nil, errors.Wrap(commitErr, "could not produce history commitment")
return history.History{}, nil, errors.Wrap(commitErr, "could not produce history commitment")
}
proof, proofErr = et.stateProvider.PrefixProof(
ctx,
Expand All @@ -552,7 +552,7 @@ func (et *Tracker) DetermineBisectionHistoryWithProof(
l2stateprovider.Height(bisectTo),
)
if proofErr != nil {
return commitments.History{}, nil, errors.Wrap(proofErr, "could not produce prefix proof")
return history.History{}, nil, errors.Wrap(proofErr, "could not produce prefix proof")
}
return historyCommit, proof, nil
}
Expand Down Expand Up @@ -601,10 +601,10 @@ func (et *Tracker) openSubchallengeLeaf(ctx context.Context) error {

fields := et.uniqueTrackerLogFields()

var startHistory commitments.History
var endHistory commitments.History
var startParentCommitment commitments.History
var endParentCommitment commitments.History
var startHistory history.History
var endHistory history.History
var startParentCommitment history.History
var endParentCommitment history.History
var startEndPrefixProof []byte
challengeLevel := et.edge.GetChallengeLevel()
switch challengeLevel {
Expand Down
105 changes: 55 additions & 50 deletions layer2-state-provider/history_commitment_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ import (
"context"
"fmt"
"math/big"
"slices"
"strconv"
"time"

protocol "github.com/OffchainLabs/bold/chain-abstraction"
"github.com/OffchainLabs/bold/state-commitments/history"
prefixproofs "github.com/OffchainLabs/bold/state-commitments/prefix-proofs"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/metrics"

"github.com/OffchainLabs/bold/api"
"github.com/OffchainLabs/bold/api/db"
"github.com/OffchainLabs/bold/containers/option"
commitments "github.com/OffchainLabs/bold/state-commitments/history"
"github.com/ethereum/go-ethereum/common"
)

Expand Down Expand Up @@ -109,7 +110,7 @@ type HistoryCommitmentProvider struct {
}

// NewHistoryCommitmentProvider creates an instance of a struct which can compute history
// commitments over any number of challenge levels for BOLD.
// commitments over any number of challenge levels for BoLD.
func NewHistoryCommitmentProvider(
l2MessageStateCollector L2MessageStateCollector,
machineHashCollector MachineHashCollector,
Expand All @@ -136,18 +137,46 @@ func (p *HistoryCommitmentProvider) UpdateAPIDatabase(apiDB db.Database) {
p.apiDB = apiDB
}

// virtualFrom computes the virtual value for a history commitment
//
// I the optional h value is None, then based on the challenge level, and given
// slice of challenge origin heights (coh) determine the maximum number of
// leaves for that level and return it as virtual.
func (p *HistoryCommitmentProvider) virtualFrom(h option.Option[Height], coh []Height) (uint64, error) {
var virtual uint64
if h.IsNone() {
validatedHeights, err := p.validateOriginHeights(coh)
if err != nil {
return 0, err
}
if len(validatedHeights) == 0 {
virtual = uint64(p.challengeLeafHeights[0]) + 1
} else {
lvl := deepestRequestedChallengeLevel(validatedHeights)
virtual = uint64(p.challengeLeafHeights[lvl]) + 1
}
} else {
virtual = uint64(h.Unwrap()) + 1
}
return virtual, nil
}

// HistoryCommitment computes a Merklelized commitment over a set of hashes
// at specified challenge levels. For block challenges, for example, this is a set
// of machine hashes corresponding each message in a range N to M.
func (p *HistoryCommitmentProvider) HistoryCommitment(
ctx context.Context,
req *HistoryCommitmentRequest,
) (commitments.History, error) {
) (history.History, error) {
hashes, err := p.historyCommitmentImpl(ctx, req)
if err != nil {
return commitments.History{}, err
return history.History{}, err
}
virtual, err := p.virtualFrom(req.UpToHeight, req.UpperChallengeOriginHeights)
if err != nil {
return history.History{}, err
}
return commitments.New(hashes)
return history.NewCommitment(hashes, virtual)
}

func (p *HistoryCommitmentProvider) historyCommitmentImpl(
Expand Down Expand Up @@ -266,7 +295,7 @@ func (p *HistoryCommitmentProvider) AgreesWithHistoryCommitment(
historyCommitMetadata *HistoryCommitmentRequest,
commit History,
) (bool, error) {
var localCommit commitments.History
var localCommit history.History
var err error
switch challengeLevel {
case protocol.NewBlockChallengeLevel():
Expand Down Expand Up @@ -343,68 +372,44 @@ func (p *HistoryCommitmentProvider) PrefixProof(
if err != nil {
return nil, err
}
// If no upToHeight is provided, we want to use the max number of leaves in our computation.
lowCommitmentNumLeaves := uint64(prefixHeight + 1)
var highCommitmentNumLeaves uint64
if req.UpToHeight.IsNone() {
highCommitmentNumLeaves = uint64(len(leaves))
} else {
// Else if it is provided, we expect the number of leaves to be the difference
// between the to and from height + 1.
upTo := req.UpToHeight.Unwrap()
if upTo < req.FromHeight {
return nil, fmt.Errorf("invalid range: end %d was < start %d", upTo, req.FromHeight)
}
highCommitmentNumLeaves = uint64(upTo) - uint64(req.FromHeight) + 1
}

// Validate we are within bounds of the leaves slice.
if highCommitmentNumLeaves > uint64(len(leaves)) {
return nil, fmt.Errorf("high prefix size out of bounds, got %d, leaves length %d", highCommitmentNumLeaves, len(leaves))
}

// Validate low vs high commitment.
if lowCommitmentNumLeaves > highCommitmentNumLeaves {
return nil, fmt.Errorf("low prefix size %d was greater than high prefix size %d", lowCommitmentNumLeaves, highCommitmentNumLeaves)
}

prefixExpansion, err := prefixproofs.ExpansionFromLeaves(leaves[:lowCommitmentNumLeaves])
virtual, err := p.virtualFrom(req.UpToHeight, req.UpperChallengeOriginHeights)
if err != nil {
return nil, err
}
prefixProof, err := prefixproofs.GeneratePrefixProof(
lowCommitmentNumLeaves,
prefixExpansion,
leaves[lowCommitmentNumLeaves:highCommitmentNumLeaves],
prefixproofs.RootFetcherFromExpansion,
)
// If no upToHeight is provided, we want to use the max number of leaves in our computation.
lowCommitmentNumLeaves := uint64(prefixHeight + 1)
// The prefix proof may be over a range of leaves that include virtual ones.
prefixLen := min(lowCommitmentNumLeaves, uint64(len(leaves)))
prefixHashes := slices.Clone(leaves[:prefixLen])
prefixRoot, err := history.ComputeRoot(prefixHashes, lowCommitmentNumLeaves)
if err != nil {
return nil, err
}
bigCommit, err := commitments.New(leaves[:highCommitmentNumLeaves])
fullTreeHashes := slices.Clone(leaves)
fullTreeRoot, err := history.ComputeRoot(fullTreeHashes, virtual)
if err != nil {
return nil, err
}

prefixCommit, err := commitments.New(leaves[:lowCommitmentNumLeaves])
hashesForProof := make([]common.Hash, len(leaves))
for i := uint64(0); i < uint64(len(leaves)); i++ {
hashesForProof[i] = leaves[i]
}
prefixExp, proof, err := history.GeneratePrefixProof(uint64(prefixHeight), hashesForProof, virtual)
if err != nil {
return nil, err
}
_, numRead := prefixproofs.MerkleExpansionFromCompact(prefixProof, lowCommitmentNumLeaves)
onlyProof := prefixProof[numRead:]

// We verify our prefix proof before an onchain submission as an extra safety-check.
if err = prefixproofs.VerifyPrefixProof(&prefixproofs.VerifyPrefixProofConfig{
PreRoot: prefixCommit.Merkle,
PreRoot: prefixRoot,
PreSize: lowCommitmentNumLeaves,
PostRoot: bigCommit.Merkle,
PostSize: highCommitmentNumLeaves,
PreExpansion: prefixExpansion,
PrefixProof: onlyProof,
PostRoot: fullTreeRoot,
PostSize: virtual,
PreExpansion: prefixExp,
PrefixProof: proof,
}); err != nil {
return nil, fmt.Errorf("could not verify prefix proof locally: %w", err)
}
return ProofArgs.Pack(&prefixExpansion, &onlyProof)
return ProofArgs.Pack(&prefixExp, &proof)
}

func (p *HistoryCommitmentProvider) OneStepProofData(
Expand Down
Loading

0 comments on commit a85df38

Please sign in to comment.