Skip to content
Draft
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
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ env:
@echo export CARTESI_BLOCKCHAIN_WS_ENDPOINT="ws://localhost:8545"
@echo export CARTESI_BLOCKCHAIN_ID="31337"
@echo export CARTESI_CONTRACTS_INPUT_BOX_ADDRESS="0x1b51e2992A2755Ba4D6F7094032DF91991a0Cfac"
@echo export CARTESI_CONTRACTS_AUTHORITY_FACTORY_ADDRESS="0x5a3368b30174d389aFd205a46bAd35BBE6709b8a"
@echo export CARTESI_CONTRACTS_AUTHORITY_FACTORY_ADDRESS="0x5E96408CFE423b01dADeD3bc867E6013135990cc"
@echo export CARTESI_CONTRACTS_APPLICATION_FACTORY_ADDRESS="0x26E758238CB6eC5aB70ce0dd52aF2d7b82e1972E"
@echo export CARTESI_CONTRACTS_SELF_HOSTED_APPLICATION_FACTORY_ADDRESS="0x870240e83b1181b419f18303D4ccC56574De2931"
@echo export CARTESI_CONTRACTS_SELF_HOSTED_APPLICATION_FACTORY_ADDRESS="0x010D3CbB4223F5bCc7b7B03cEE59f3aAea8eDb8A"
@echo export CARTESI_CONTRACTS_DAVE_APP_FACTORY_ADDRESS="0x96cD319eBD67DF6b753766ec000fe639dFba9F6b"
@echo export CARTESI_AUTH_MNEMONIC=\"test test test test test test test test test test test junk\"
@echo export CARTESI_DATABASE_CONNECTION="postgres://postgres:password@localhost:5432/rollupsdb?sslmode=disable"
Expand Down
181 changes: 70 additions & 111 deletions internal/claimer/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package claimer
import (
"context"
"fmt"
"iter"
"log/slog"
"math/big"

Expand All @@ -15,8 +14,6 @@ import (
"github.com/cartesi/rollups-node/pkg/contracts/iconsensus"
"github.com/cartesi/rollups-node/pkg/ethutil"

"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -103,22 +100,6 @@ func (self *claimerBlockchain) submitClaimToBlockchain(
return txHash, err
}

func unwrapClaimSubmitted(
ic *iconsensus.IConsensus,
pull func() (log *types.Log, err error, ok bool),
) (
*iconsensus.IConsensusClaimSubmitted,
bool,
error,
) {
log, err, ok := pull()
if !ok || err != nil {
return nil, false, err
}
ev, err := ic.ParseClaimSubmitted(*log)
return ev, true, err
}

// scan the event stream for a claimSubmitted event that matches claim.
// return this event and its successor
func (self *claimerBlockchain) findClaimSubmittedEventAndSucc(
Expand All @@ -137,68 +118,48 @@ func (self *claimerBlockchain) findClaimSubmittedEventAndSucc(
return nil, nil, nil, err
}

// filter must match:
// - `ClaimSubmitted` events
// - submitter == nil (any)
// - appContract == claim.IApplicationAddress
c, err := iconsensus.IConsensusMetaData.GetAbi()
topics, err := abi.MakeTopics(
[]any{c.Events[model.MonitoredEvent_ClaimSubmitted.String()].ID},
nil,
[]any{application.IApplicationAddress},
)
if err != nil {
return nil, nil, nil, err
}
oracle := func(ctx context.Context, block uint64) (*big.Int, error) {
callOpts := &bind.CallOpts{
Context: ctx,
BlockNumber: new(big.Int).SetUint64(block),
}
numSubmittedClaims, err := ic.GetNumberOfSubmittedClaims(callOpts)

it, err := self.filter.ChunkedFilterLogs(ctx, self.client, ethereum.FilterQuery{
FromBlock: new(big.Int).SetUint64(epoch.LastBlock),
ToBlock: endBlock,
Addresses: []common.Address{application.IConsensusAddress},
Topics: topics,
})
if err != nil {
return nil, nil, nil, err
if err != nil {
return nil, fmt.Errorf("failed to get number of submitted claims at block %d: %w", block, err)
}
return numSubmittedClaims, nil
}

// pull events instead of iterating
next, stop := iter.Pull2(it)
defer stop()
for {
event, ok, err := unwrapClaimSubmitted(ic, next)
if !ok || err != nil {
return ic, event, nil, err
events := []*iconsensus.IConsensusClaimSubmitted{}
onHit := func(block uint64) error {
filterOpts := &bind.FilterOpts{
Context: ctx,
Start: block,
End: &block,
}
lastBlock := event.LastProcessedBlockNumber.Uint64()

if claimSubmittedEventMatches(application, epoch, event) {
// found the event, does it has a successor? try to fetch it
succ, ok, err := unwrapClaimSubmitted(ic, next)
if !ok || err != nil {
return ic, event, nil, err
}
return ic, event, succ, err
} else if lastBlock > epoch.LastBlock {
err = fmt.Errorf("No matching claim, searched up to %v", event)
return nil, nil, nil, err
claimSubmittedEvents, err := ic.FilterClaimSubmitted(filterOpts, nil, []common.Address{application.IApplicationAddress})
if err != nil {
return fmt.Errorf("failed to retrieve inputs at block %d: %w", block, err)
}
for claimSubmittedEvents.Next() {
events = append(events, claimSubmittedEvents.Event)
}
return nil
}
}

func unwrapClaimAccepted(
ic *iconsensus.IConsensus,
pull func() (log *types.Log, err error, ok bool),
) (
*iconsensus.IConsensusClaimAccepted,
bool,
error,
) {
log, err, ok := pull()
if !ok || err != nil {
return nil, false, err
_, err = ethutil.FindTransitions(ctx, epoch.LastBlock, endBlock.Uint64(), nil, oracle, onHit)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to walk input transitions: %w", err)
}

if len(events) == 0 {
return ic, nil, nil, nil
} else if len(events) == 1 {
return ic, events[0], nil, nil
} else {
return ic, events[0], events[1], nil
}
ev, err := ic.ParseClaimAccepted(*log)
return ev, true, err
}

// scan the event stream for a claimAccepted event that matches claim.
Expand All @@ -219,49 +180,47 @@ func (self *claimerBlockchain) findClaimAcceptedEventAndSucc(
return nil, nil, nil, err
}

// filter must match:
// - `ClaimAccepted` events
// - appContract == claim.IApplicationAddress
c, err := iconsensus.IConsensusMetaData.GetAbi()
topics, err := abi.MakeTopics(
[]any{c.Events[model.MonitoredEvent_ClaimAccepted.String()].ID},
[]any{application.IApplicationAddress},
)
if err != nil {
return nil, nil, nil, err
}
oracle := func(ctx context.Context, block uint64) (*big.Int, error) {
callOpts := &bind.CallOpts{
Context: ctx,
BlockNumber: new(big.Int).SetUint64(block),
}
numAcceptedClaims, err := ic.GetNumberOfAcceptedClaims(callOpts)

it, err := self.filter.ChunkedFilterLogs(ctx, self.client, ethereum.FilterQuery{
FromBlock: new(big.Int).SetUint64(epoch.LastBlock),
ToBlock: endBlock,
Addresses: []common.Address{application.IConsensusAddress},
Topics: topics,
})
if err != nil {
return nil, nil, nil, err
if err != nil {
return nil, fmt.Errorf("failed to get number of Accepted claims at block %d: %w", block, err)
}
return numAcceptedClaims, nil
}

// pull events instead of iterating
next, stop := iter.Pull2(it)
defer stop()
for {
event, ok, err := unwrapClaimAccepted(ic, next)
if !ok || err != nil {
return ic, event, nil, err
events := []*iconsensus.IConsensusClaimAccepted{}
onHit := func(block uint64) error {
filterOpts := &bind.FilterOpts{
Context: ctx,
Start: block,
End: &block,
}
lastBlock := event.LastProcessedBlockNumber.Uint64()

if claimAcceptedEventMatches(application, epoch, event) {
// found the event, does it has a successor? try to fetch it
succ, ok, err := unwrapClaimAccepted(ic, next)
if !ok || err != nil {
return ic, event, nil, err
}
return ic, event, succ, err
} else if lastBlock > epoch.LastBlock {
err = fmt.Errorf("No matching claim, searched up to %v", event)
return nil, nil, nil, err
claimAcceptedEvents, err := ic.FilterClaimAccepted(filterOpts, []common.Address{application.IApplicationAddress})
if err != nil {
return fmt.Errorf("failed to retrieve inputs at block %d: %w", block, err)
}
for claimAcceptedEvents.Next() {
events = append(events, claimAcceptedEvents.Event)
}
return nil
}

_, err = ethutil.FindTransitions(ctx, epoch.LastBlock, endBlock.Uint64(), nil, oracle, onHit)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to walk input transitions: %w", err)
}

if len(events) == 0 {
return ic, nil, nil, nil
} else if len(events) == 1 {
return ic, events[0], nil, nil
} else {
return ic, events[0], events[1], nil
}
}

Expand Down
33 changes: 32 additions & 1 deletion pkg/contracts/iconsensus/iconsensus.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading