Skip to content
This repository has been archived by the owner on May 11, 2024. It is now read-only.

Commit

Permalink
feat(prover): add --prover.blockSlippage flag (#449)
Browse files Browse the repository at this point in the history
  • Loading branch information
RogerLamTd authored Nov 11, 2023
1 parent 7f24d1e commit 0ee8259
Show file tree
Hide file tree
Showing 18 changed files with 282 additions and 77 deletions.
2 changes: 1 addition & 1 deletion bindings/.githead
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7090d5f5c7e4f290a87b42e83d73accdbfe176c7
205eb2c49f2364ffe382408577040767a69c5a03
16 changes: 15 additions & 1 deletion bindings/encoding/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ var (
Name: "expiry",
Type: "uint64",
},
{
Name: "maxBlockId",
Type: "uint64",
},
{
Name: "signature",
Type: "bytes",
Expand Down Expand Up @@ -188,6 +192,7 @@ var (
{Name: "blobHash", Type: bytes32Type},
{Name: "assignment.feeToken", Type: addressType},
{Name: "assignment.expiry", Type: uint64Type},
{Name: "assignment.maxBlockId", Type: uint64Type},
{Name: "assignment.tierFees", Type: tierFeesType},
}
blockMetadataComponentsType, _ = abi.NewType("tuple", "TaikoData.BlockMetadata", blockMetadataComponents)
Expand Down Expand Up @@ -233,9 +238,18 @@ func EncodeProverAssignmentPayload(
txListHash common.Hash,
feeToken common.Address,
expiry uint64,
maxBlockID uint64,
tierFees []TierFee,
) ([]byte, error) {
b, err := proverAssignmentPayloadArgs.Pack("PROVER_ASSIGNMENT", taikoAddress, txListHash, feeToken, expiry, tierFees)
b, err := proverAssignmentPayloadArgs.Pack(
"PROVER_ASSIGNMENT",
taikoAddress,
txListHash,
feeToken,
expiry,
maxBlockID,
tierFees,
)
if err != nil {
return nil, fmt.Errorf("failed to abi.encode prover assignment hash payload, %w", err)
}
Expand Down
1 change: 1 addition & 0 deletions bindings/encoding/input_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func TestEncodeProverAssignmentPayload(t *testing.T) {
common.BytesToHash(randomBytes(32)),
common.BytesToAddress(randomBytes(20)),
120,
1024,
[]TierFee{{Tier: 0, Fee: common.Big1}},
)

Expand Down
11 changes: 6 additions & 5 deletions bindings/encoding/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,12 @@ type TierFee struct {

// ProverAssignment should be same with TaikoData.ProverAssignment.
type ProverAssignment struct {
Prover common.Address
FeeToken common.Address
TierFees []TierFee
Expiry uint64
Signature []byte
Prover common.Address
FeeToken common.Address
TierFees []TierFee
Expiry uint64
MaxBlockId uint64
Signature []byte
}

// FromGethHeader converts a GETH *types.Header to *BlockHeader.
Expand Down
1 change: 0 additions & 1 deletion bindings/gen_taiko_l2.go

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

44 changes: 43 additions & 1 deletion bindings/gen_taiko_token.go

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions cmd/flags/prover.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@ var (
Value: false,
Category: proverCategory,
}
// Max slippage allowed
MaxAcceptableBlockSlippage = &cli.Uint64Flag{
Name: "prover.blockSlippage",
Usage: "Maximum accepted slippage difference for blockID for accepting proving a block",
Value: 1024,
Category: proverCategory,
}
)

// All prover flags.
Expand Down Expand Up @@ -179,4 +186,5 @@ var ProverFlags = MergeFlags(CommonFlags, []cli.Flag{
ProverCapacity,
MaxExpiry,
TaikoTokenAddress,
MaxAcceptableBlockSlippage,
})
59 changes: 42 additions & 17 deletions pkg/rpc/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
)

var (
ZeroAddress = common.HexToAddress("0x0000000000000000000000000000000000000000")
ZeroAddress common.Address
waitReceiptPollingInterval = 3 * time.Second
defaultWaitReceiptTimeout = 1 * time.Minute
)
Expand Down Expand Up @@ -127,32 +127,40 @@ func WaitReceipt(
}
}

// NeedNewProof checks whether the L2 block still needs a new proof.
func NeedNewProof(
// BlockProofStatus represents the proving status of the given L2 block.
type BlockProofStatus struct {
IsSubmitted bool
Invalid bool
CurrentTransitionState *bindings.TaikoDataTransitionState
ParentBlock *types.Header
}

// GetBlockProofStatus checks whether the L2 block still needs a new proof or a new contest.
func GetBlockProofStatus(
ctx context.Context,
cli *Client,
id *big.Int,
proverAddress common.Address,
) (bool, error) {
) (*BlockProofStatus, error) {
ctxWithTimeout, cancel := ctxWithTimeoutOrDefault(ctx, defaultTimeout)
defer cancel()

var parent *types.Header
if id.Cmp(common.Big1) == 0 {
header, err := cli.L2.HeaderByNumber(ctxWithTimeout, common.Big0)
if err != nil {
return false, err
return nil, err
}

parent = header
} else {
parentL1Origin, err := cli.WaitL1Origin(ctxWithTimeout, new(big.Int).Sub(id, common.Big1))
if err != nil {
return false, err
return nil, err
}

if parent, err = cli.L2.HeaderByHash(ctxWithTimeout, parentL1Origin.L2BlockHash); err != nil {
return false, err
return nil, err
}
}

Expand All @@ -163,29 +171,46 @@ func NeedNewProof(
)
if err != nil {
if !strings.Contains(encoding.TryParsingCustomError(err).Error(), "L1_TRANSITION_NOT_FOUND") {
return false, encoding.TryParsingCustomError(err)
return nil, encoding.TryParsingCustomError(err)
}

return true, nil
return &BlockProofStatus{IsSubmitted: false}, nil
}

l1Origin, err := cli.WaitL1Origin(ctxWithTimeout, id)
if err != nil {
return false, err
return nil, err
}

l2SignalService, err := cli.TaikoL2.SignalService(&bind.CallOpts{Context: ctx, BlockNumber: id})
if err != nil {
return nil, err
}

root, err := cli.GetStorageRoot(ctx, cli.L2GethClient, l2SignalService, id)
if err != nil {
return nil, err
}

if l1Origin.L2BlockHash != transition.BlockHash {
if l1Origin.L2BlockHash != transition.BlockHash || transition.SignalRoot != root {
log.Info(
"Different blockhash detected, try submitting a proof",
"local", common.BytesToHash(l1Origin.L2BlockHash[:]),
"protocol", common.BytesToHash(transition.BlockHash[:]),
"Different block hash or signal root detected, try submitting a contest",
"localBlockHash", common.BytesToHash(l1Origin.L2BlockHash[:]),
"protocolTransitionBlockHash", common.BytesToHash(transition.BlockHash[:]),
"localSignalRoot", root,
"protocolTransitionSignalRoot", common.BytesToHash(transition.SignalRoot[:]),
)
return true, nil
return &BlockProofStatus{
IsSubmitted: true,
Invalid: true,
CurrentTransitionState: &transition,
ParentBlock: parent,
}, nil
}

if proverAddress == transition.Prover {
log.Info("📬 Block's proof has already been submitted by current prover", "blockID", id)
return false, nil
return &BlockProofStatus{IsSubmitted: true}, nil
}

log.Info(
Expand All @@ -195,7 +220,7 @@ func NeedNewProof(
"timestamp", transition.Timestamp,
)

return false, nil
return &BlockProofStatus{IsSubmitted: true}, nil
}

type AccountPoolContent map[string]map[string]*types.Transaction
Expand Down
21 changes: 15 additions & 6 deletions proposer/prover_selector/eth_fee_eoa_selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,14 @@ func assignProver(

// Ensure prover in response is the same as the one recovered
// from the signature
payload, err := encoding.EncodeProverAssignmentPayload(taikoL1Address, txListHash, common.Address{}, expiry, tierFees)
payload, err := encoding.EncodeProverAssignmentPayload(
taikoL1Address,
txListHash,
common.Address{},
expiry,
result.MaxBlockID,
tierFees,
)
if err != nil {
return nil, common.Address{}, err
}
Expand All @@ -240,17 +247,19 @@ func assignProver(
"address", result.Prover,
"endpoint", endpoint,
"tierFees", tierFees,
"maxBlockID", result.MaxBlockID,
"expiry", expiry,
)

// Convert signature to one solidity can recover by adding 27 to 65th byte
result.SignedPayload[64] = uint8(uint(result.SignedPayload[64])) + 27

return &encoding.ProverAssignment{
Prover: result.Prover,
FeeToken: common.Address{},
TierFees: tierFees,
Expiry: reqBody.Expiry,
Signature: result.SignedPayload,
Prover: result.Prover,
FeeToken: common.Address{},
TierFees: tierFees,
Expiry: reqBody.Expiry,
MaxBlockId: result.MaxBlockID,
Signature: result.SignedPayload,
}, result.Prover, nil
}
2 changes: 2 additions & 0 deletions prover/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type Config struct {
MinPseZkevmTierFee *big.Int
MinSgxAndPseZkevmTierFee *big.Int
MaxExpiry time.Duration
MaxBlockSlippage uint64
}

// NewConfigFromCliContext creates a new config instance from command line flags.
Expand Down Expand Up @@ -136,5 +137,6 @@ func NewConfigFromCliContext(c *cli.Context) (*Config, error) {
MinPseZkevmTierFee: new(big.Int).SetUint64(c.Uint64(flags.MinPseZkevmTierFee.Name)),
MinSgxAndPseZkevmTierFee: new(big.Int).SetUint64(c.Uint64(flags.MinSgxAndPseZkevmTierFee.Name)),
MaxExpiry: c.Duration(flags.MaxExpiry.Name),
MaxBlockSlippage: c.Uint64(flags.MaxAcceptableBlockSlippage.Name),
}, nil
}
9 changes: 7 additions & 2 deletions prover/proof_submitter/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package submitter

import (
"context"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/taikoxyz/taiko-client/bindings"
proofProducer "github.com/taikoxyz/taiko-client/prover/proof_producer"
)
Expand All @@ -17,7 +19,10 @@ type Submitter interface {
type Contester interface {
SubmitContest(
ctx context.Context,
blockProposedEvent *bindings.TaikoL1ClientBlockProposed,
transitionProvedEvent *bindings.TaikoL1ClientTransitionProved,
blockID *big.Int,
proposedIn *big.Int,
parentHash common.Hash,
meta *bindings.TaikoDataBlockMetadata,
tier uint16,
) error
}
40 changes: 24 additions & 16 deletions prover/proof_submitter/proof_contester.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,24 @@ func NewProofContester(
// SubmitContest submits a taikoL1.proveBlock transaction to contest a L2 block transition.
func (c *ProofContester) SubmitContest(
ctx context.Context,
blockProposedEvent *bindings.TaikoL1ClientBlockProposed,
transitionProvedEvent *bindings.TaikoL1ClientTransitionProved,
blockID *big.Int,
proposedIn *big.Int,
parentHash common.Hash,
meta *bindings.TaikoDataBlockMetadata,
tier uint16,
) error {
// Ensure the transition has not been contested yet.
transition, err := c.rpc.TaikoL1.GetTransition(
&bind.CallOpts{Context: ctx},
transitionProvedEvent.BlockId.Uint64(),
transitionProvedEvent.Tran.ParentHash,
blockID.Uint64(),
parentHash,
)
if err != nil {
if !strings.Contains(encoding.TryParsingCustomError(err).Error(), "L1_") {
log.Warn(
"Failed to get transition",
"blockID", transitionProvedEvent.BlockId,
"parentHash", transitionProvedEvent.Tran.ParentHash,
"blockID", blockID,
"parentHash", parentHash,
"error", encoding.TryParsingCustomError(err),
)
return nil
Expand All @@ -94,40 +97,45 @@ func (c *ProofContester) SubmitContest(
if transition.Contester != (common.Address{}) {
log.Info(
"Transaction has already been contested",
"blockID", transitionProvedEvent.BlockId,
"parentHash", transitionProvedEvent.Tran.ParentHash,
"blockID", blockID,
"parentHash", parentHash,
"contester", transition.Contester,
)
return nil
}

header, err := c.rpc.L2.HeaderByNumber(ctx, transitionProvedEvent.BlockId)
header, err := c.rpc.L2.HeaderByNumber(ctx, blockID)
if err != nil {
return err
}

signalRoot, err := c.rpc.GetStorageRoot(ctx, c.rpc.L2GethClient, c.l2SignalService, transitionProvedEvent.BlockId)
signalRoot, err := c.rpc.GetStorageRoot(ctx, c.rpc.L2GethClient, c.l2SignalService, blockID)
if err != nil {
return fmt.Errorf("failed to get L2 signal service storage root: %w", err)
}

l1HeaderProposedIn, err := c.rpc.L1.HeaderByNumber(ctx, proposedIn)
if err != nil {
return err
}

if err := c.txSender.Send(
ctx,
&proofProducer.ProofWithHeader{
BlockID: transitionProvedEvent.BlockId,
Meta: &blockProposedEvent.Meta,
BlockID: blockID,
Meta: meta,
Header: header,
Proof: []byte{},
Opts: &proofProducer.ProofRequestOptions{
EventL1Hash: blockProposedEvent.Raw.BlockHash,
EventL1Hash: l1HeaderProposedIn.Hash(),
SignalRoot: signalRoot,
},
Tier: transitionProvedEvent.Tier,
Tier: tier,
},
c.txBuilder.Build(
ctx,
transitionProvedEvent.BlockId,
&blockProposedEvent.Meta,
blockID,
meta,
&bindings.TaikoDataTransition{
ParentHash: header.ParentHash,
BlockHash: header.Hash(),
Expand Down
Loading

0 comments on commit 0ee8259

Please sign in to comment.