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

feat(prover): introduce SGXAndZkevmRpcdProducer #476

Merged
merged 5 commits into from
Dec 15, 2023
Merged
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
30 changes: 29 additions & 1 deletion bindings/encoding/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,27 @@ var (
Type: "uint256",
},
}
zkEvmProofComponents = []abi.ArgumentMarshaling{
{
Name: "verifierId",
Type: "uint16",
},
{
Name: "zkp",
Type: "bytes",
},
{
Name: "pointProof",
Type: "bytes",
},
}
)

var (
// BlockParams
assignmentHookInputType, _ = abi.NewType("tuple", "AssignmentHook.Input", assignmentHookInputComponents)
assignmentHookInputArgs = abi.Arguments{{Name: "AssignmentHook.Input", Type: assignmentHookInputType}}
zkEvmProofType, _ = abi.NewType("tuple", "ZkEvmProof", zkEvmProofComponents)
zkEvmProofArgs = abi.Arguments{{Name: "ZkEvmProof", Type: zkEvmProofType}}
blockParamsComponentsType, _ = abi.NewType("tuple", "TaikoData.BlockParams", blockParamsComponents)
blockParamsComponentsArgs = abi.Arguments{{Name: "TaikoData.BlockParams", Type: blockParamsComponentsType}}
// ProverAssignmentPayload
Expand Down Expand Up @@ -276,6 +291,19 @@ func EncodeBlockParams(params *BlockParams) ([]byte, error) {
return b, nil
}

// EncodeBlockParams performs the solidity `abi.encode` for the given blockParams.
func EncodeZKEvmProof(proof []byte) ([]byte, error) {
b, err := zkEvmProofArgs.Pack(&ZKEvmProof{
VerifierId: 0,
Zkp: proof,
PointProof: []byte{},
})
if err != nil {
return nil, fmt.Errorf("failed to abi.encode ZkEvmProof, %w", err)
}
return b, nil
}

// EncodeAssignmentHookInput performs the solidity `abi.encode` for the given input
func EncodeAssignmentHookInput(input *AssignmentHookInput) ([]byte, error) {
b, err := assignmentHookInputArgs.Pack(input)
Expand Down
8 changes: 8 additions & 0 deletions bindings/encoding/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var (
TierSgxAndPseZkevmID uint16 = 400
TierGuardianID uint16 = 1000
ProtocolTiers []uint16 = []uint16{TierOptimisticID, TierSgxID, TierSgxAndPseZkevmID, TierGuardianID}
AnchorTxGasLimit uint64 = 250_000
)

// BlockHeader represents an Ethereum block header.
Expand Down Expand Up @@ -79,6 +80,13 @@ type AssignmentHookInput struct {
Tip *big.Int
}

// ZKEvmProof should be same as PseZkVerifier.ZkEvmProof
type ZKEvmProof struct {
VerifierId uint16
Zkp []byte
PointProof []byte
}

// FromGethHeader converts a GETH *types.Header to *BlockHeader.
func FromGethHeader(header *types.Header) *BlockHeader {
baseFeePerGas := header.BaseFee
Expand Down
76 changes: 76 additions & 0 deletions prover/proof_producer/sgx_and_zkevm_rpcd_producer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package producer

import (
"context"
"math/big"

"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/taikoxyz/taiko-client/bindings"
"github.com/taikoxyz/taiko-client/bindings/encoding"
"golang.org/x/sync/errgroup"
)

// SGXAndZkevmRpcdProducer generates a SGX + PSE ZKEVM proof for the given block.
type SGXAndZkevmRpcdProducer struct {
*SGXProofProducer
*ZkevmRpcdProducer
}

// RequestProof implements the ProofProducer interface.
func (o *SGXAndZkevmRpcdProducer) RequestProof(
ctx context.Context,
opts *ProofRequestOptions,
blockID *big.Int,
meta *bindings.TaikoDataBlockMetadata,
header *types.Header,
resultCh chan *ProofWithHeader,
) error {
log.Info(
"Request SGX+PSE proof",
"blockID", blockID,
"coinbase", meta.Coinbase,
"height", header.Number,
"hash", header.Hash(),
)

sgxProofCh := make(chan *ProofWithHeader, 1)
pseZkEvmProofCh := make(chan *ProofWithHeader, 1)

g, ctx := errgroup.WithContext(ctx)
g.Go(func() error {
return o.SGXProofProducer.RequestProof(ctx, opts, blockID, meta, header, sgxProofCh)
})
g.Go(func() error {
return o.ZkevmRpcdProducer.RequestProof(ctx, opts, blockID, meta, header, pseZkEvmProofCh)
})
if err := g.Wait(); err != nil {
return err
}

resultCh <- &ProofWithHeader{
BlockID: blockID,
Meta: meta,
Header: header,
Proof: append((<-sgxProofCh).Proof, (<-pseZkEvmProofCh).Proof...),
Opts: opts,
Tier: o.Tier(),
}

return nil
}

// Tier implements the ProofProducer interface.
func (o *SGXAndZkevmRpcdProducer) Tier() uint16 {
return encoding.TierSgxAndPseZkevmID
}

// Cancellable implements the ProofProducer interface.
func (o *SGXAndZkevmRpcdProducer) Cancellable() bool {
return false
}

// Cancel cancels an existing proof generation.
func (o *SGXAndZkevmRpcdProducer) Cancel(ctx context.Context, blockID *big.Int) error {
return nil
}
14 changes: 12 additions & 2 deletions prover/proof_producer/sgx_producer.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,24 @@ func (p *SGXProofProducer) callProverDaemon(ctx context.Context, opts *ProofRequ
}

if output == nil {
log.Info("Proof generating", "height", opts.BlockID, "time", time.Since(start))
log.Info(
"Proof generating",
"height", opts.BlockID,
"time", time.Since(start),
"producer", "SGXProofProducer",
)
return errProofGenerating
}

log.Debug("Proof generation output", "output", output)

proof = common.Hex2Bytes(output.Proof)
log.Info("Proof generated", "height", opts.BlockID, "time", time.Since(start))
log.Info(
"Proof generated",
"height", opts.BlockID,
"time", time.Since(start),
"producer", "SGXProofProducer",
)
return nil
}, backoff.NewConstantBackOff(proofPollingInterval)); err != nil {
return nil, err
Expand Down
102 changes: 82 additions & 20 deletions prover/proof_producer/zkevm_rpcd_producer.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,43 @@ type RequestProofBodyParam struct {
ProtocolInstance *ProtocolInstance `json:"protocol_instance"`
}

type RequestMetaData struct {
L1Hash string `json:"l1_hash"`
Difficulty string `json:"difficulty"`
BlobHash string `json:"blob_hash"`
ExtraData string `json:"extra_data"`
DepositsHash string `json:"deposits_hash"`
Coinbase string `json:"coinbase"`
ID uint64 `json:"id"`
GasLimit uint32 `json:"gas_limit"`
Timestamp uint64 `json:"timestamp"`
L1Height uint64 `json:"l1_height"`
TxListByteOffset *big.Int `json:"tx_list_byte_offset"`
TxListByteSize *big.Int `json:"tx_list_byte_size"`
MinTier uint16 `json:"min_tier"`
BlobUsed bool `json:"blob_used"`
ParentMetaHash string `json:"parent_metahash"`
}

// RequestProofBody represents the JSON body of RequestProofBody.Param's `protocol_instance` field.
type ProtocolInstance struct {
L1SignalService string `json:"l1_signal_service"`
L2SignalService string `json:"l2_signal_service"`
TaikoL2 string `json:"l2_contract"`
MetaHash string `json:"meta_hash"`
BlockHash string `json:"block_hash"`
ParentHash string `json:"parent_hash"`
SignalRoot string `json:"signal_root"`
Graffiti string `json:"graffiti"`
Prover string `json:"prover"`
GasUsed uint64 `json:"gas_used"`
ParentGasUsed uint64 `json:"parent_gas_used"`
BlockMaxGasLimit uint64 `json:"block_max_gas_limit"`
MaxTransactionsPerBlock uint64 `json:"max_transactions_per_block"`
MaxBytesPerTxList uint64 `json:"max_bytes_per_tx_list"`
L1SignalService string `json:"l1_signal_service"`
L2SignalService string `json:"l2_signal_service"`
TaikoL2 string `json:"l2_contract"`
MetaHash string `json:"meta_hash"`
BlockHash string `json:"block_hash"`
ParentHash string `json:"parent_hash"`
SignalRoot string `json:"signal_root"`
Graffiti string `json:"graffiti"`
Prover string `json:"prover"`
Treasury string `json:"treasury"`
GasUsed uint64 `json:"gas_used"`
ParentGasUsed uint64 `json:"parent_gas_used"`
BlockMaxGasLimit uint64 `json:"block_max_gas_limit"`
MaxTransactionsPerBlock uint64 `json:"max_transactions_per_block"`
MaxBytesPerTxList uint64 `json:"max_bytes_per_tx_list"`
AnchorGasLimit uint64 `json:"anchor_gas_limit"`
RequestMetaData *RequestMetaData `json:"request_meta_data"`
}

// RequestProofBodyResponse represents the JSON body of the response of the proof requests.
Expand Down Expand Up @@ -151,12 +172,16 @@ func (p *ZkevmRpcdProducer) RequestProof(
if p.CustomProofHook != nil {
proof, degree, err = p.CustomProofHook()
} else {
proof, degree, err = p.callProverDaemon(ctx, opts)
proof, degree, err = p.callProverDaemon(ctx, opts, meta)
}
if err != nil {
return err
}

if proof, err = encoding.EncodeZKEvmProof(proof); err != nil {
return err
}

resultCh <- &ProofWithHeader{
BlockID: blockID,
Header: header,
Expand All @@ -171,7 +196,11 @@ func (p *ZkevmRpcdProducer) RequestProof(
}

// callProverDaemon keeps polling the proverd service to get the requested proof.
func (p *ZkevmRpcdProducer) callProverDaemon(ctx context.Context, opts *ProofRequestOptions) ([]byte, uint64, error) {
func (p *ZkevmRpcdProducer) callProverDaemon(
ctx context.Context,
opts *ProofRequestOptions,
meta *bindings.TaikoDataBlockMetadata,
) ([]byte, uint64, error) {
var (
proof []byte
degree uint64
Expand All @@ -181,14 +210,19 @@ func (p *ZkevmRpcdProducer) callProverDaemon(ctx context.Context, opts *ProofReq
if ctx.Err() != nil {
return nil
}
output, err := p.requestProof(opts)
output, err := p.requestProof(opts, meta)
if err != nil {
log.Error("Failed to request proof", "height", opts.BlockID, "err", err, "endpoint", p.RpcdEndpoint)
return err
}

if output == nil {
log.Info("Proof generating", "height", opts.BlockID, "time", time.Since(start))
log.Info(
"Proof generating",
"height", opts.BlockID,
"time", time.Since(start),
"producer", "ZkevmRpcdProducer",
)
return errProofGenerating
}

Expand All @@ -202,7 +236,13 @@ func (p *ZkevmRpcdProducer) callProverDaemon(ctx context.Context, opts *ProofReq

proof = common.Hex2Bytes(proofOutput)
degree = output.Aggregation.Degree
log.Info("Proof generated", "height", opts.BlockID, "degree", degree, "time", time.Since(start))
log.Info(
"Proof generated",
"height", opts.BlockID,
"degree", degree,
"time", time.Since(start),
"producer", "ZkevmRpcdProducer",
)
return nil
}, backoff.NewConstantBackOff(proofPollingInterval)); err != nil {
return nil, 0, err
Expand All @@ -214,7 +254,10 @@ func (p *ZkevmRpcdProducer) callProverDaemon(ctx context.Context, opts *ProofReq
}

// requestProof sends a RPC request to proverd to try to get the requested proof.
func (p *ZkevmRpcdProducer) requestProof(opts *ProofRequestOptions) (*RpcdOutput, error) {
func (p *ZkevmRpcdProducer) requestProof(
opts *ProofRequestOptions,
meta *bindings.TaikoDataBlockMetadata,
) (*RpcdOutput, error) {
reqBody := RequestProofBody{
JsonRPC: "2.0",
ID: common.Big1,
Expand All @@ -231,6 +274,7 @@ func (p *ZkevmRpcdProducer) requestProof(opts *ProofRequestOptions) (*RpcdOutput
Aggregate: true,
ProtocolInstance: &ProtocolInstance{
Prover: opts.ProverAddress.Hex()[2:],
Treasury: opts.TaikoL2.Hex()[2:],
L1SignalService: opts.L1SignalService.Hex()[2:],
L2SignalService: opts.L2SignalService.Hex()[2:],
TaikoL2: opts.TaikoL2.Hex()[2:],
Expand All @@ -243,6 +287,24 @@ func (p *ZkevmRpcdProducer) requestProof(opts *ProofRequestOptions) (*RpcdOutput
ParentGasUsed: opts.ParentGasUsed,
BlockMaxGasLimit: uint64(p.ProtocolConfig.BlockMaxGasLimit),
MaxBytesPerTxList: p.ProtocolConfig.BlockMaxTxListBytes.Uint64(),
AnchorGasLimit: encoding.AnchorTxGasLimit,
RequestMetaData: &RequestMetaData{
L1Hash: common.BytesToHash(meta.L1Hash[:]).Hex()[2:],
Difficulty: common.BytesToHash(meta.Difficulty[:]).Hex()[2:],
BlobHash: common.BytesToHash(meta.BlobHash[:]).Hex()[2:],
ExtraData: common.BytesToHash(meta.ExtraData[:]).Hex()[2:],
DepositsHash: common.BytesToHash(meta.DepositsHash[:]).Hex()[2:],
Coinbase: meta.Coinbase.Hex()[2:],
ID: meta.Id,
GasLimit: meta.GasLimit,
Timestamp: meta.Timestamp,
L1Height: meta.L1Height,
TxListByteOffset: meta.TxListByteOffset,
TxListByteSize: meta.TxListByteSize,
MinTier: meta.MinTier,
BlobUsed: meta.BlobUsed,
ParentMetaHash: common.BytesToHash(meta.ParentMetaHash[:]).Hex()[2:],
},
},
}},
}
Expand Down
6 changes: 5 additions & 1 deletion prover/proof_producer/zkevm_rpcd_producer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ func TestZkevmRpcdProducerCalls(t *testing.T) {

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
_, _, err = dummyZkevmRpcdProducer.callProverDaemon(ctx, &ProofRequestOptions{BlockID: common.Big32})
_, _, err = dummyZkevmRpcdProducer.callProverDaemon(
ctx,
&ProofRequestOptions{BlockID: common.Big32},
&bindings.TaikoDataBlockMetadata{},
)

require.Nil(t, err)
}
Loading