Skip to content

Commit

Permalink
feat(taiko-client): enable proof aggregation (batch proofs) (#18163)
Browse files Browse the repository at this point in the history
Co-authored-by: David <[email protected]>
Co-authored-by: maskpp <[email protected]>
  • Loading branch information
3 people authored Dec 5, 2024
1 parent 524ac55 commit 7642961
Show file tree
Hide file tree
Showing 22 changed files with 1,515 additions and 82 deletions.
44 changes: 44 additions & 0 deletions packages/taiko-client/bindings/encoding/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,13 @@ var (
{Name: "TaikoData.Transition", Type: transitionComponentsType},
{Name: "TaikoData.TierProof", Type: tierProofComponentsType},
}
proveBlocksInputArgs = abi.Arguments{
{Name: "TaikoData.BlockMetadata", Type: blockMetadataV2ComponentsType},
{Name: "TaikoData.Transition", Type: transitionComponentsType},
}
proveBlocksBatchProofArgs = abi.Arguments{
{Name: "TaikoData.TierProof", Type: tierProofComponentsType},
}
)

// Contract ABIs.
Expand Down Expand Up @@ -423,6 +430,43 @@ func EncodeProveBlockInput(
return b, nil
}

// EncodeProveBlocksInput performs the solidity `abi.encode` for the given TaikoL1.proveBlocks input.
func EncodeProveBlocksInput(
metas []metadata.TaikoBlockMetaData,
transitions []bindings.TaikoDataTransition,
) ([][]byte, error) {
if len(metas) != len(transitions) {
return nil, fmt.Errorf("both arrays of TaikoBlockMetaData and TaikoDataTransition must be equal in length")
}
b := make([][]byte, 0, len(metas))
for i := range metas {
input, err := proveBlocksInputArgs.Pack(
metas[i].(*metadata.TaikoDataBlockMetadataOntake).InnerMetadata(),
transitions[i],
)
if err != nil {
return nil, fmt.Errorf("failed to abi.encode TaikoL1.proveBlocks input item after ontake fork, %w", err)
}

b = append(b, input)
}

return b, nil
}

// EncodeProveBlocksBatchProof performs the solidity `abi.encode` for the given TaikoL1.proveBlocks batchProof.
func EncodeProveBlocksBatchProof(
tierProof *bindings.TaikoDataTierProof,
) ([]byte, error) {
input, err := proveBlocksBatchProofArgs.Pack(
tierProof,
)
if err != nil {
return nil, fmt.Errorf("failed to abi.encode TaikoL1.proveBlocks input item after ontake fork, %w", err)
}
return input, nil
}

// UnpackTxListBytes unpacks the input data of a TaikoL1.proposeBlock transaction, and returns the txList bytes.
func UnpackTxListBytes(txData []byte) ([]byte, error) {
method, err := TaikoL1ABI.MethodById(txData)
Expand Down
28 changes: 28 additions & 0 deletions packages/taiko-client/cmd/flags/prover.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,31 @@ var (
Category: proverCategory,
EnvVars: []string{"PROVER_BLOCK_CONFIRMATIONS"},
}
// Batch proof related flag
SGXBatchSize = &cli.Uint64Flag{
Name: "prover.sgx.batchSize",
Usage: "The default size of batch sgx proofs, when it arrives, submit a batch of proof immediately, " +
"this flag only works post Ontake fork",
Value: 1,
Category: proverCategory,
EnvVars: []string{"PROVER_SGX_BATCH_SIZE"},
}
ZKVMBatchSize = &cli.Uint64Flag{
Name: "prover.zkvm.batchSize",
Usage: "The size of batch ZKVM proof, when it arrives, submit a batch of proof immediately, " +
"this flag only works post Ontake fork",
Value: 1,
Category: proverCategory,
EnvVars: []string{"PROVER_ZKVM_BATCH_SIZE"},
}
ForceProveInterval = &cli.DurationFlag{
Name: "prover.forceBatchProvingInterval",
Usage: "Time interval to prove blocks even the number of pending proof do not exceed prover.batchSize, " +
"this flag only works post Ontake fork",
Category: proverCategory,
Value: 30 * time.Minute,
EnvVars: []string{"PROVER_FORCE_BATCH_PROVING_INTERVAL"},
}
)

// ProverFlags All prover flags.
Expand Down Expand Up @@ -227,4 +252,7 @@ var ProverFlags = MergeFlags(CommonFlags, []cli.Flag{
BlockConfirmations,
RaikoRequestTimeout,
RaikoZKVMHostEndpoint,
SGXBatchSize,
ZKVMBatchSize,
ForceProveInterval,
}, TxmgrFlags)
12 changes: 12 additions & 0 deletions packages/taiko-client/internal/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,27 @@ var (
ProverSubmissionErrorCounter = factory.NewCounter(prometheus.CounterOpts{
Name: "prover_proof_submission_error",
})
ProverAggregationSubmissionErrorCounter = factory.NewCounter(prometheus.CounterOpts{
Name: "prover_proof_aggregation_submission_error",
})
ProverSgxProofGeneratedCounter = factory.NewCounter(prometheus.CounterOpts{
Name: "prover_proof_sgx_generated",
})
ProverSgxProofAggregationGeneratedCounter = factory.NewCounter(prometheus.CounterOpts{
Name: "prover_proof_sgx_aggregation_generated",
})
ProverR0ProofGeneratedCounter = factory.NewCounter(prometheus.CounterOpts{
Name: "prover_proof_r0_generated",
})
ProverR0ProofAggregationGeneratedCounter = factory.NewCounter(prometheus.CounterOpts{
Name: "prover_proof_r0_aggregation_generated",
})
ProverSp1ProofGeneratedCounter = factory.NewCounter(prometheus.CounterOpts{
Name: "prover_proof_sp1_generated",
})
ProverSp1ProofAggregationGeneratedCounter = factory.NewCounter(prometheus.CounterOpts{
Name: "prover_proof_sp1_aggregation_generated",
})
ProverSubmissionRevertedCounter = factory.NewCounter(prometheus.CounterOpts{
Name: "prover_proof_submission_reverted",
})
Expand Down
61 changes: 61 additions & 0 deletions packages/taiko-client/pkg/rpc/ethclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package rpc

import (
"context"
"errors"
"math/big"
"time"

Expand All @@ -14,6 +15,10 @@ import (
"github.com/ethereum/go-ethereum/rpc"
)

var (
ErrInvalidLenOfParams = errors.New("invalid length of parameters")
)

// gethClient is a wrapper for go-ethereum geth client.
type gethClient struct {
*gethclient.Client
Expand Down Expand Up @@ -74,6 +79,34 @@ func (c *EthClient) BlockByHash(ctx context.Context, hash common.Hash) (*types.B
return c.ethClient.BlockByHash(ctxWithTimeout, hash)
}

func (c *EthClient) BatchBlocksByHashes(ctx context.Context, hashes []common.Hash) ([]*types.Block, error) {
if len(hashes) < 1 {
return nil, ErrInvalidLenOfParams
}
ctxWithTimeout, cancel := CtxWithTimeoutOrDefault(ctx, c.timeout)
defer cancel()

reqs := make([]rpc.BatchElem, len(hashes))
results := make([]*types.Block, len(hashes))
for i, hash := range hashes {
reqs[i] = rpc.BatchElem{
Method: "eth_getBlockByHash",
Args: []interface{}{hash, true},
Result: &results[i],
}
}
if err := c.BatchCallContext(ctxWithTimeout, reqs); err != nil {
return nil, err
}
for i := range reqs {
if reqs[i].Error != nil {
return nil, reqs[i].Error
}
}

return results, nil
}

// BlockByNumber returns a block from the current canonical chain. If number is nil, the
// latest known block is returned.
//
Expand Down Expand Up @@ -119,6 +152,34 @@ func (c *EthClient) HeaderByNumber(ctx context.Context, number *big.Int) (*types
return c.ethClient.HeaderByNumber(ctxWithTimeout, number)
}

func (c *EthClient) BatchHeadersByNumbers(ctx context.Context, numbers []*big.Int) ([]*types.Header, error) {
if len(numbers) < 1 {
return nil, ErrInvalidLenOfParams
}
ctxWithTimeout, cancel := CtxWithTimeoutOrDefault(ctx, c.timeout)
defer cancel()

reqs := make([]rpc.BatchElem, len(numbers))
results := make([]*types.Header, len(numbers))
for i, blockNum := range numbers {
reqs[i] = rpc.BatchElem{
Method: "eth_getBlockByNumber",
Args: []interface{}{blockNum, false},
Result: &results[i],
}
}
if err := c.BatchCallContext(ctxWithTimeout, reqs); err != nil {
return nil, err
}
for i := range reqs {
if reqs[i].Error != nil {
return nil, reqs[i].Error
}
}

return results, nil
}

// TransactionByHash returns the transaction with the given hash.
func (c *EthClient) TransactionByHash(
ctx context.Context,
Expand Down
26 changes: 26 additions & 0 deletions packages/taiko-client/pkg/rpc/ethclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package rpc

import (
"context"
"math/big"
"testing"

"github.com/ethereum/go-ethereum"
Expand Down Expand Up @@ -168,3 +169,28 @@ func TestEstimateGas(t *testing.T) {
_, err := client.L1.EstimateGas(context.Background(), ethereum.CallMsg{})
require.Nil(t, err)
}

func TestBatchBlocksByNumbers(t *testing.T) {
client := newTestClientWithTimeout(t)

headers, err := client.L1.BatchHeadersByNumbers(context.Background(), []*big.Int{big.NewInt(0), big.NewInt(1)})
require.Nil(t, err)
require.Len(t, headers, 2)
}

func TestBatchBlocksByHashes(t *testing.T) {
client := newTestClientWithTimeout(t)

headers, err := client.L1.BatchHeadersByNumbers(context.Background(), []*big.Int{big.NewInt(0), big.NewInt(1)})
require.Nil(t, err)
require.Len(t, headers, 2)

hashes := make([]common.Hash, len(headers))
for i, header := range headers {
hashes[i] = header.Hash()
}

blocks, err := client.L1.BatchBlocksByHashes(context.Background(), hashes)
require.Nil(t, err)
require.Len(t, blocks, 2)
}
Loading

0 comments on commit 7642961

Please sign in to comment.