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

Commit

Permalink
feat(prover): introduce SGXAndZkevmRpcdProducer (#476)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidtaikocha committed Dec 15, 2023
1 parent a27d353 commit 1750a4b
Show file tree
Hide file tree
Showing 7 changed files with 244 additions and 24 deletions.
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

0 comments on commit 1750a4b

Please sign in to comment.