From 5f450799839855ca21c08814ee130e3c073e0436 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 25 Apr 2023 12:31:16 -0700 Subject: [PATCH 01/16] oracle prover --- bindings/encoding/input.go | 2 - bindings/encoding/input_test.go | 9 - cmd/flags/prover.go | 7 + oracle/evidence.go | 39 ++++ oracle/evidence_test.go | 60 +++++ prover/config.go | 2 + prover/config_test.go | 3 + .../proof_submitter/oracle_proof_submitter.go | 209 ++++++++++++++++++ .../oracle_proof_submitter_test.go | 48 ++++ .../proof_submitter/valid_proof_submitter.go | 12 +- prover/prover.go | 59 +++-- 11 files changed, 410 insertions(+), 40 deletions(-) create mode 100644 oracle/evidence.go create mode 100644 oracle/evidence_test.go create mode 100644 prover/proof_submitter/oracle_proof_submitter.go create mode 100644 prover/proof_submitter/oracle_proof_submitter_test.go diff --git a/bindings/encoding/input.go b/bindings/encoding/input.go index 24c29f137..c7f1d5f2f 100644 --- a/bindings/encoding/input.go +++ b/bindings/encoding/input.go @@ -210,8 +210,6 @@ func EncodeProposeBlockInput(metadataInput *TaikoL1BlockMetadataInput) ([]byte, // EncodeProveBlockInput encodes the input params for TaikoL1.proveBlock. func EncodeProveBlockInput( evidence *TaikoL1Evidence, - anchorTx *types.Transaction, - anchorReceipt *types.Receipt, ) ([]byte, error) { evidenceBytes, err := EncodeEvidence(evidence) if err != nil { diff --git a/bindings/encoding/input_test.go b/bindings/encoding/input_test.go index 61e2ad150..140ba32aa 100644 --- a/bindings/encoding/input_test.go +++ b/bindings/encoding/input_test.go @@ -56,15 +56,6 @@ func TestEncodeProveBlockInput(t *testing.T) { VerifierId: 1024, Proof: randomHash().Big().Bytes(), }, - types.NewTransaction( - 0, - common.BytesToAddress(randomHash().Bytes()), - common.Big0, - 0, - common.Big0, - randomHash().Bytes(), - ), - types.NewReceipt(randomHash().Bytes(), false, 1024), ) require.Nil(t, err) diff --git a/cmd/flags/prover.go b/cmd/flags/prover.go index 634e73780..b96ca328d 100644 --- a/cmd/flags/prover.go +++ b/cmd/flags/prover.go @@ -53,6 +53,12 @@ var ( "`lowerBound-upperBound` (e.g. `30m-1h`), testing purposes only", Category: proverCategory, } + OracleProver = &cli.BoolFlag{ + Name: "oracleProver", + Usage: "Set whether prover should use oracle prover or not", + Category: proverCategory, + Value: false, + } ) // All prover flags. @@ -67,4 +73,5 @@ var ProverFlags = MergeFlags(CommonFlags, []cli.Flag{ MaxConcurrentProvingJobs, Dummy, RandomDummyProofDelay, + OracleProver, }) diff --git a/oracle/evidence.go b/oracle/evidence.go new file mode 100644 index 000000000..96e011b8a --- /dev/null +++ b/oracle/evidence.go @@ -0,0 +1,39 @@ +package oracle + +import ( + "crypto/ecdsa" + "fmt" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/taikoxyz/taiko-client/bindings/encoding" +) + +// HashSignAndSetEvidenceForOracleProof hashes and signs the TaikoL1Evidence according to the +// protoco spec to generate an "oracle proof" via the signature and v value. +func HashSignAndSetEvidenceForOracleProof( + evidence *encoding.TaikoL1Evidence, + privateKey *ecdsa.PrivateKey, +) ([]byte, uint8, error) { + evidence.VerifierId = 0 + evidence.Proof = nil + + inputToSign, err := encoding.EncodeProveBlockInput(evidence) + if err != nil { + return nil, 0, fmt.Errorf("failed to encode TaikoL1.proveBlock inputs: %w", err) + } + + hashed := crypto.Keccak256Hash(inputToSign) + + sig, err := crypto.Sign(hashed.Bytes(), privateKey) + if err != nil { + return nil, 0, fmt.Errorf("failed to sign TaikoL1Evidence: %w", err) + } + + // add 27 to be able to be ecrecover in solidity + v := uint8(int(sig[64])) + 27 + + evidence.VerifierId = uint16(v) + evidence.Proof = sig + + return sig, v, nil +} diff --git a/oracle/evidence_test.go b/oracle/evidence_test.go new file mode 100644 index 000000000..c4f39b031 --- /dev/null +++ b/oracle/evidence_test.go @@ -0,0 +1,60 @@ +package oracle + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "math/big" + "math/rand" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" + "github.com/taikoxyz/taiko-client/bindings/encoding" +) + +// randomHash generates a random blob of data and returns it as a hash. +func randomHash() common.Hash { + var hash common.Hash + if n, err := rand.Read(hash[:]); n != common.HashLength || err != nil { + panic(err) + } + return hash +} + +func TestHashAndSignEvidenceForOracleProof(t *testing.T) { + evidence := &encoding.TaikoL1Evidence{ + MetaHash: randomHash(), + BlockHash: randomHash(), + ParentHash: randomHash(), + SignalRoot: randomHash(), + Graffiti: randomHash(), + Prover: common.BigToAddress(new(big.Int).SetUint64(rand.Uint64())), + ParentGasUsed: 1024, + GasUsed: 1024, + VerifierId: 0, + Proof: nil, + } + + privateKey, err := crypto.HexToECDSA("1acb95df9ff6e93035ca3b8afce58273ac880d7b8bcb8a26b0be5a84be3a879d") + require.Nil(t, err) + + publicKey := privateKey.Public() + + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + require.True(t, ok) + + input, err := encoding.EncodeProveBlockInput(evidence) + require.Nil(t, err) + + hash := crypto.Keccak256Hash(input) + + sig, _, err := HashSignAndSetEvidenceForOracleProof(evidence, privateKey) + + pubKey, err := crypto.Ecrecover(hash.Bytes(), sig) + require.Nil(t, err) + isValid := crypto.VerifySignature(pubKey, hash.Bytes(), sig[:64]) + require.True(t, isValid) + + require.Equal(t, elliptic.Marshal(publicKeyECDSA, publicKeyECDSA.X, publicKeyECDSA.Y), pubKey) +} diff --git a/prover/config.go b/prover/config.go index 6d013b518..b4238de3a 100644 --- a/prover/config.go +++ b/prover/config.go @@ -27,6 +27,7 @@ type Config struct { StartingBlockID *big.Int MaxConcurrentProvingJobs uint Dummy bool + OracleProver bool RandomDummyProofDelayLowerBound *time.Duration RandomDummyProofDelayUpperBound *time.Duration } @@ -87,6 +88,7 @@ func NewConfigFromCliContext(c *cli.Context) (*Config, error) { StartingBlockID: startingBlockID, MaxConcurrentProvingJobs: c.Uint(flags.MaxConcurrentProvingJobs.Name), Dummy: c.Bool(flags.Dummy.Name), + OracleProver: c.Bool(flags.OracleProver.Name), RandomDummyProofDelayLowerBound: randomDummyProofDelayLowerBound, RandomDummyProofDelayUpperBound: randomDummyProofDelayUpperBound, }, nil diff --git a/prover/config_test.go b/prover/config_test.go index adf21187c..c30017ab8 100644 --- a/prover/config_test.go +++ b/prover/config_test.go @@ -29,6 +29,7 @@ func (s *ProverTestSuite) TestNewConfigFromCliContext() { &cli.StringFlag{Name: flags.L1ProverPrivKey.Name}, &cli.BoolFlag{Name: flags.Dummy.Name}, &cli.StringFlag{Name: flags.RandomDummyProofDelay.Name}, + &cli.BoolFlag{Name: flags.OracleProver.Name}, } app.Action = func(ctx *cli.Context) error { c, err := NewConfigFromCliContext(ctx) @@ -46,6 +47,7 @@ func (s *ProverTestSuite) TestNewConfigFromCliContext() { s.Equal(30*time.Minute, *c.RandomDummyProofDelayLowerBound) s.Equal(time.Hour, *c.RandomDummyProofDelayUpperBound) s.True(c.Dummy) + s.True(c.OracleProver) s.Nil(new(Prover).InitFromCli(context.Background(), ctx)) return err @@ -62,5 +64,6 @@ func (s *ProverTestSuite) TestNewConfigFromCliContext() { "-" + flags.L1ProverPrivKey.Name, os.Getenv("L1_PROVER_PRIVATE_KEY"), "-" + flags.Dummy.Name, "-" + flags.RandomDummyProofDelay.Name, "30m-1h", + "-" + flags.OracleProver.Name, })) } diff --git a/prover/proof_submitter/oracle_proof_submitter.go b/prover/proof_submitter/oracle_proof_submitter.go new file mode 100644 index 000000000..69100e8a6 --- /dev/null +++ b/prover/proof_submitter/oracle_proof_submitter.go @@ -0,0 +1,209 @@ +package submitter + +import ( + "context" + "crypto/ecdsa" + "errors" + "fmt" + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + "github.com/taikoxyz/taiko-client/bindings" + "github.com/taikoxyz/taiko-client/bindings/encoding" + "github.com/taikoxyz/taiko-client/metrics" + "github.com/taikoxyz/taiko-client/oracle" + "github.com/taikoxyz/taiko-client/pkg/rpc" + anchorTxValidator "github.com/taikoxyz/taiko-client/prover/anchor_tx_validator" + proofProducer "github.com/taikoxyz/taiko-client/prover/proof_producer" +) + +var _ ProofSubmitter = (*OracleProofSubmitter)(nil) + +// OracleProofSubmitter is responsible requesting zk proofs for the given valid L2 +// blocks, and submitting the generated proofs to the TaikoL1 smart contract. +type OracleProofSubmitter struct { + rpc *rpc.Client + resultCh chan *proofProducer.ProofWithHeader + anchorTxValidator *anchorTxValidator.AnchorTxValidator + proverPrivKey *ecdsa.PrivateKey + proverAddress common.Address + mutex *sync.Mutex +} + +// NewOracleProofSubmitter creates a new OracleProofSubmitter instance. +func NewOracleProofSubmitter( + rpc *rpc.Client, + resultCh chan *proofProducer.ProofWithHeader, + taikoL2Address common.Address, + proverPrivKey *ecdsa.PrivateKey, + mutex *sync.Mutex, +) (*OracleProofSubmitter, error) { + anchorValidator, err := anchorTxValidator.New(taikoL2Address, rpc.L2ChainID, rpc) + if err != nil { + return nil, err + } + + return &OracleProofSubmitter{ + rpc: rpc, + resultCh: resultCh, + anchorTxValidator: anchorValidator, + proverPrivKey: proverPrivKey, + proverAddress: crypto.PubkeyToAddress(proverPrivKey.PublicKey), + mutex: mutex, + }, nil +} + +// RequestProof implements the ProofSubmitter interface. +func (s *OracleProofSubmitter) RequestProof(ctx context.Context, event *bindings.TaikoL1ClientBlockProposed) error { + l1Origin, err := s.rpc.WaitL1Origin(ctx, event.Id) + if err != nil { + return fmt.Errorf("failed to fetch l1Origin, blockID: %d, err: %w", event.Id, err) + } + + // Get the header of the block to prove from L2 execution engine. + header, err := s.rpc.L2.HeaderByHash(ctx, l1Origin.L2BlockHash) + if err != nil { + return err + } + + metrics.ProverQueuedProofCounter.Inc(1) + metrics.ProverQueuedValidProofCounter.Inc(1) + + // "proof" for Oracle Proof is actually signed in SubmitProof, since + // we already have the evidence and to not duplicate RPC calls. + // "Proof" and "Degree" fields are not used here. + s.resultCh <- &proofProducer.ProofWithHeader{ + Header: header, + BlockID: event.Id, + Meta: &event.Meta, + } + + return nil +} + +// SubmitProof implements the ProofSubmitter interface. +func (s *OracleProofSubmitter) SubmitProof( + ctx context.Context, + proofWithHeader *proofProducer.ProofWithHeader, +) (err error) { + log.Info( + "New oracle block proof", + "blockID", proofWithHeader.BlockID, + "beneficiary", proofWithHeader.Meta.Beneficiary, + "hash", proofWithHeader.Header.Hash(), + ) + var ( + blockID = proofWithHeader.BlockID + header = proofWithHeader.Header + ) + + metrics.ProverReceivedProofCounter.Inc(1) + metrics.ProverReceivedValidProofCounter.Inc(1) + + // Get the corresponding L2 block. + block, err := s.rpc.L2.BlockByHash(ctx, header.Hash()) + if err != nil { + return fmt.Errorf("failed to get L2 block with given hash %s: %w", header.Hash(), err) + } + + log.Debug( + "Get the L2 block to prove", + "blockID", blockID, + "hash", block.Hash(), + "root", header.Root.String(), + "transactions", len(block.Transactions()), + ) + + if block.Transactions().Len() == 0 { + return fmt.Errorf("invalid block without anchor transaction, blockID %s", blockID) + } + + // Validate TaikoL2.anchor transaction inside the L2 block. + anchorTx := block.Transactions()[0] + if err := s.anchorTxValidator.ValidateAnchorTx(ctx, anchorTx); err != nil { + return fmt.Errorf("invalid anchor transaction: %w", err) + } + + // Get and validate this anchor transaction's receipt. + _, err = s.anchorTxValidator.GetAndValidateAnchorTxReceipt(ctx, anchorTx) + if err != nil { + return fmt.Errorf("failed to fetch anchor transaction receipt: %w", err) + } + + signalRoot, err := s.anchorTxValidator.GetAnchoredSignalRoot(ctx, anchorTx) + if err != nil { + return err + } + + parent, err := s.rpc.L2.BlockByHash(ctx, block.ParentHash()) + if err != nil { + return err + } + + blockInfo, err := s.rpc.TaikoL1.GetBlock(nil, blockID) + if err != nil { + return err + } + + // signature should be done with proof set to nil, verifierID set to 0, + // and prover set to 0 address. + evidence := &encoding.TaikoL1Evidence{ + MetaHash: blockInfo.MetaHash, + ParentHash: block.ParentHash(), + BlockHash: block.Hash(), + SignalRoot: signalRoot, + Graffiti: [32]byte{}, + Prover: common.HexToAddress("0x0000000000000000000000000000000000000000"), + ParentGasUsed: uint32(parent.GasUsed()), + GasUsed: uint32(block.GasUsed()), + VerifierId: 0, + Proof: nil, + } + + _, _, err = oracle.HashSignAndSetEvidenceForOracleProof(evidence, s.proverPrivKey) + if err != nil { + return fmt.Errorf("failed to sign evidence: %w", err) + } + + input, err := encoding.EncodeProveBlockInput(evidence) + if err != nil { + return fmt.Errorf("failed to encode TaikoL1.proveBlock inputs: %w", err) + } + + // Send the TaikoL1.proveBlock transaction. + txOpts, err := getProveBlocksTxOpts(ctx, s.rpc.L1, s.rpc.L1ChainID, s.proverPrivKey) + if err != nil { + return err + } + + sendTx := func() (*types.Transaction, error) { + s.mutex.Lock() + defer s.mutex.Unlock() + + return s.rpc.TaikoL1.ProveBlock(txOpts, blockID, input) + } + + if err := sendTxWithBackoff(ctx, s.rpc, blockID, sendTx); err != nil { + if errors.Is(err, errUnretryable) { + return nil + } + + return err + } + + log.Info( + "✅ Oracle block proved", + "blockID", proofWithHeader.BlockID, + "hash", block.Hash(), "height", block.Number(), + "transactions", block.Transactions().Len(), + ) + + metrics.ProverSentProofCounter.Inc(1) + metrics.ProverSentValidProofCounter.Inc(1) + metrics.ProverLatestProvenBlockIDGauge.Update(proofWithHeader.BlockID.Int64()) + + return nil +} diff --git a/prover/proof_submitter/oracle_proof_submitter_test.go b/prover/proof_submitter/oracle_proof_submitter_test.go new file mode 100644 index 000000000..9751703c0 --- /dev/null +++ b/prover/proof_submitter/oracle_proof_submitter_test.go @@ -0,0 +1,48 @@ +package submitter + +import ( + "os" + "sync" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/suite" + "github.com/taikoxyz/taiko-client/driver/chain_syncer/calldata" + "github.com/taikoxyz/taiko-client/proposer" + proofProducer "github.com/taikoxyz/taiko-client/prover/proof_producer" + "github.com/taikoxyz/taiko-client/testutils" +) + +type OracleProofSubmitterTestSuite struct { + testutils.ClientTestSuite + oracleProofSubmitter *OracleProofSubmitter + calldataSyncer *calldata.Syncer + proposer *proposer.Proposer + validProofCh chan *proofProducer.ProofWithHeader + invalidProofCh chan *proofProducer.ProofWithHeader +} + +func (s *OracleProofSubmitterTestSuite) SetupTest() { + s.ClientTestSuite.SetupTest() + + l1ProverPrivKey, err := crypto.ToECDSA(common.Hex2Bytes("1acb95df9ff6e93035ca3b8afce58273ac880d7b8bcb8a26b0be5a84be3a879d")) + s.Nil(err) + + s.validProofCh = make(chan *proofProducer.ProofWithHeader, 1024) + s.invalidProofCh = make(chan *proofProducer.ProofWithHeader, 1024) + + s.oracleProofSubmitter, err = NewOracleProofSubmitter( + s.RpcClient, + s.validProofCh, + common.HexToAddress(os.Getenv("TAIKO_L2_ADDRESS")), + l1ProverPrivKey, + &sync.Mutex{}, + ) + s.Nil(err) + +} + +func TestOracleProofSubmitterTestSuite(t *testing.T) { + suite.Run(t, new(ProofSubmitterTestSuite)) +} diff --git a/prover/proof_submitter/valid_proof_submitter.go b/prover/proof_submitter/valid_proof_submitter.go index e1f7cb22c..9b77f7b8f 100644 --- a/prover/proof_submitter/valid_proof_submitter.go +++ b/prover/proof_submitter/valid_proof_submitter.go @@ -26,7 +26,7 @@ var _ ProofSubmitter = (*ValidProofSubmitter)(nil) type ValidProofSubmitter struct { rpc *rpc.Client proofProducer proofProducer.ProofProducer - reusltCh chan *proofProducer.ProofWithHeader + resultCh chan *proofProducer.ProofWithHeader anchorTxValidator *anchorTxValidator.AnchorTxValidator proverPrivKey *ecdsa.PrivateKey proverAddress common.Address @@ -37,7 +37,7 @@ type ValidProofSubmitter struct { func NewValidProofSubmitter( rpc *rpc.Client, proofProducer proofProducer.ProofProducer, - reusltCh chan *proofProducer.ProofWithHeader, + resultCh chan *proofProducer.ProofWithHeader, taikoL2Address common.Address, proverPrivKey *ecdsa.PrivateKey, mutex *sync.Mutex, @@ -50,7 +50,7 @@ func NewValidProofSubmitter( return &ValidProofSubmitter{ rpc: rpc, proofProducer: proofProducer, - reusltCh: reusltCh, + resultCh: resultCh, anchorTxValidator: anchorValidator, proverPrivKey: proverPrivKey, proverAddress: crypto.PubkeyToAddress(proverPrivKey.PublicKey), @@ -78,7 +78,7 @@ func (s *ValidProofSubmitter) RequestProof(ctx context.Context, event *bindings. ProposeBlockTxHash: event.Raw.TxHash, } - if err := s.proofProducer.RequestProof(ctx, opts, event.Id, &event.Meta, header, s.reusltCh); err != nil { + if err := s.proofProducer.RequestProof(ctx, opts, event.Id, &event.Meta, header, s.resultCh); err != nil { return err } @@ -134,7 +134,7 @@ func (s *ValidProofSubmitter) SubmitProof( } // Get and validate this anchor transaction's receipt. - anchorTxReceipt, err := s.anchorTxValidator.GetAndValidateAnchorTxReceipt(ctx, anchorTx) + _, err = s.anchorTxValidator.GetAndValidateAnchorTxReceipt(ctx, anchorTx) if err != nil { return fmt.Errorf("failed to fetch anchor transaction receipt: %w", err) } @@ -172,7 +172,7 @@ func (s *ValidProofSubmitter) SubmitProof( Proof: zkProof, } - input, err := encoding.EncodeProveBlockInput(evidence, anchorTx, anchorTxReceipt) + input, err := encoding.EncodeProveBlockInput(evidence) if err != nil { return fmt.Errorf("failed to encode TaikoL1.proveBlock inputs: %w", err) } diff --git a/prover/prover.go b/prover/prover.go index 53d2e81f7..b8c5bce85 100644 --- a/prover/prover.go +++ b/prover/prover.go @@ -123,36 +123,49 @@ func InitFromConfig(ctx context.Context, p *Prover, cfg *Config) (err error) { p.proposeConcurrencyGuard = make(chan struct{}, cfg.MaxConcurrentProvingJobs) p.submitProofConcurrencyGuard = make(chan struct{}, cfg.MaxConcurrentProvingJobs) - var producer proofProducer.ProofProducer - if cfg.Dummy { - producer = &proofProducer.DummyProofProducer{ - RandomDummyProofDelayLowerBound: p.cfg.RandomDummyProofDelayLowerBound, - RandomDummyProofDelayUpperBound: p.cfg.RandomDummyProofDelayUpperBound, + if cfg.OracleProver { + // Proof submitter + if p.validProofSubmitter, err = proofSubmitter.NewOracleProofSubmitter( + p.rpc, + p.proveValidProofCh, + p.cfg.TaikoL2Address, + p.cfg.L1ProverPrivKey, + p.submitProofTxMutex, + ); err != nil { + return err } } else { - if producer, err = proofProducer.NewZkevmRpcdProducer( - cfg.ZKEvmRpcdEndpoint, - cfg.ZkEvmRpcdParamsPath, - cfg.L1HttpEndpoint, - cfg.L2HttpEndpoint, - true, + var producer proofProducer.ProofProducer + + if cfg.Dummy { + producer = &proofProducer.DummyProofProducer{ + RandomDummyProofDelayLowerBound: p.cfg.RandomDummyProofDelayLowerBound, + RandomDummyProofDelayUpperBound: p.cfg.RandomDummyProofDelayUpperBound, + } + } else { + if producer, err = proofProducer.NewZkevmRpcdProducer( + cfg.ZKEvmRpcdEndpoint, + cfg.ZkEvmRpcdParamsPath, + cfg.L1HttpEndpoint, + cfg.L2HttpEndpoint, + true, + ); err != nil { + return err + } + } + // Proof submitter + if p.validProofSubmitter, err = proofSubmitter.NewValidProofSubmitter( + p.rpc, + producer, + p.proveValidProofCh, + p.cfg.TaikoL2Address, + p.cfg.L1ProverPrivKey, + p.submitProofTxMutex, ); err != nil { return err } } - // Proof submitter - if p.validProofSubmitter, err = proofSubmitter.NewValidProofSubmitter( - p.rpc, - producer, - p.proveValidProofCh, - p.cfg.TaikoL2Address, - p.cfg.L1ProverPrivKey, - p.submitProofTxMutex, - ); err != nil { - return err - } - return nil } From 1e9f587c34cf6390e4f3a4113c93c11c89cb26fd Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 25 Apr 2023 12:33:14 -0700 Subject: [PATCH 02/16] rm test file for now --- .../oracle_proof_submitter_test.go | 48 ------------------- 1 file changed, 48 deletions(-) delete mode 100644 prover/proof_submitter/oracle_proof_submitter_test.go diff --git a/prover/proof_submitter/oracle_proof_submitter_test.go b/prover/proof_submitter/oracle_proof_submitter_test.go deleted file mode 100644 index 9751703c0..000000000 --- a/prover/proof_submitter/oracle_proof_submitter_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package submitter - -import ( - "os" - "sync" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/stretchr/testify/suite" - "github.com/taikoxyz/taiko-client/driver/chain_syncer/calldata" - "github.com/taikoxyz/taiko-client/proposer" - proofProducer "github.com/taikoxyz/taiko-client/prover/proof_producer" - "github.com/taikoxyz/taiko-client/testutils" -) - -type OracleProofSubmitterTestSuite struct { - testutils.ClientTestSuite - oracleProofSubmitter *OracleProofSubmitter - calldataSyncer *calldata.Syncer - proposer *proposer.Proposer - validProofCh chan *proofProducer.ProofWithHeader - invalidProofCh chan *proofProducer.ProofWithHeader -} - -func (s *OracleProofSubmitterTestSuite) SetupTest() { - s.ClientTestSuite.SetupTest() - - l1ProverPrivKey, err := crypto.ToECDSA(common.Hex2Bytes("1acb95df9ff6e93035ca3b8afce58273ac880d7b8bcb8a26b0be5a84be3a879d")) - s.Nil(err) - - s.validProofCh = make(chan *proofProducer.ProofWithHeader, 1024) - s.invalidProofCh = make(chan *proofProducer.ProofWithHeader, 1024) - - s.oracleProofSubmitter, err = NewOracleProofSubmitter( - s.RpcClient, - s.validProofCh, - common.HexToAddress(os.Getenv("TAIKO_L2_ADDRESS")), - l1ProverPrivKey, - &sync.Mutex{}, - ) - s.Nil(err) - -} - -func TestOracleProofSubmitterTestSuite(t *testing.T) { - suite.Run(t, new(ProofSubmitterTestSuite)) -} From 62a773e09488989774f0c1221e0bfdb25e9c9a38 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 25 Apr 2023 12:34:09 -0700 Subject: [PATCH 03/16] fix typo godlen => golden --- driver/anchor_tx_constructor/anchor_tx_constructor_test.go | 4 ++-- prover/anchor_tx_validator/anchor_tx_validator_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/driver/anchor_tx_constructor/anchor_tx_constructor_test.go b/driver/anchor_tx_constructor/anchor_tx_constructor_test.go index be30cf33c..337eab113 100644 --- a/driver/anchor_tx_constructor/anchor_tx_constructor_test.go +++ b/driver/anchor_tx_constructor/anchor_tx_constructor_test.go @@ -45,7 +45,7 @@ func (s *AnchorTxConstructorTestSuite) TestAssembleAnchorTx() { } func (s *AnchorTxConstructorTestSuite) TestNewAnchorTransactor() { - godlenTouchAddress, err := s.RpcClient.TaikoL2.GOLDENTOUCHADDRESS(nil) + goldenTouchAddress, err := s.RpcClient.TaikoL2.GOLDENTOUCHADDRESS(nil) s.Nil(err) c, err := New( @@ -59,7 +59,7 @@ func (s *AnchorTxConstructorTestSuite) TestNewAnchorTransactor() { s.Equal(true, opts.NoSend) s.Equal(common.Big0, opts.GasPrice) s.Equal(common.Big0, opts.Nonce) - s.Equal(godlenTouchAddress, opts.From) + s.Equal(goldenTouchAddress, opts.From) } func (s *AnchorTxConstructorTestSuite) TestSign() { diff --git a/prover/anchor_tx_validator/anchor_tx_validator_test.go b/prover/anchor_tx_validator/anchor_tx_validator_test.go index 69fb36a5c..0414986d2 100644 --- a/prover/anchor_tx_validator/anchor_tx_validator_test.go +++ b/prover/anchor_tx_validator/anchor_tx_validator_test.go @@ -29,11 +29,11 @@ func (s *AnchorTxValidatorTestSuite) TestValidateAnchorTx() { wrongPrivKey, err := crypto.HexToECDSA("2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200") s.Nil(err) - godlenTouchPrivKey, err := s.RpcClient.TaikoL2.GOLDENTOUCHPRIVATEKEY(nil) + goldenTouchPrivKey, err := s.RpcClient.TaikoL2.GOLDENTOUCHPRIVATEKEY(nil) s.Nil(err) // 0x92954368afd3caa1f3ce3ead0069c1af414054aefe1ef9aeacc1bf426222ce38 - goldenTouchPriKey, err := crypto.HexToECDSA(common.Bytes2Hex(godlenTouchPrivKey.Bytes())) + goldenTouchPriKey, err := crypto.HexToECDSA(common.Bytes2Hex(goldenTouchPrivKey.Bytes())) s.Nil(err) // invalid To From 3fb39a0b8831809d8d637a17ec307912e8414044 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 25 Apr 2023 12:38:57 -0700 Subject: [PATCH 04/16] check err in test --- oracle/evidence_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/oracle/evidence_test.go b/oracle/evidence_test.go index c4f39b031..9c612c821 100644 --- a/oracle/evidence_test.go +++ b/oracle/evidence_test.go @@ -50,6 +50,7 @@ func TestHashAndSignEvidenceForOracleProof(t *testing.T) { hash := crypto.Keccak256Hash(input) sig, _, err := HashSignAndSetEvidenceForOracleProof(evidence, privateKey) + require.Nil(t, err) pubKey, err := crypto.Ecrecover(hash.Bytes(), sig) require.Nil(t, err) From 0aea6dcde5076744a58d9d44eedcedfbb4781a2a Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 25 Apr 2023 12:46:14 -0700 Subject: [PATCH 05/16] use env var --- oracle/evidence_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oracle/evidence_test.go b/oracle/evidence_test.go index 9c612c821..fa6732376 100644 --- a/oracle/evidence_test.go +++ b/oracle/evidence_test.go @@ -5,6 +5,7 @@ import ( "crypto/elliptic" "math/big" "math/rand" + "os" "testing" "github.com/ethereum/go-ethereum/common" @@ -36,7 +37,7 @@ func TestHashAndSignEvidenceForOracleProof(t *testing.T) { Proof: nil, } - privateKey, err := crypto.HexToECDSA("1acb95df9ff6e93035ca3b8afce58273ac880d7b8bcb8a26b0be5a84be3a879d") + privateKey, err := crypto.HexToECDSA(os.Getenv("L1_PROVER_PRIVATE_KEY")) require.Nil(t, err) publicKey := privateKey.Public() From 52d7d53b543cfe9a56c738c64228d55a141ee95f Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 25 Apr 2023 12:50:03 -0700 Subject: [PATCH 06/16] oracle => pkg/oracle --- {oracle => pkg/oracle}/evidence.go | 0 {oracle => pkg/oracle}/evidence_test.go | 0 prover/proof_submitter/oracle_proof_submitter.go | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename {oracle => pkg/oracle}/evidence.go (100%) rename {oracle => pkg/oracle}/evidence_test.go (100%) diff --git a/oracle/evidence.go b/pkg/oracle/evidence.go similarity index 100% rename from oracle/evidence.go rename to pkg/oracle/evidence.go diff --git a/oracle/evidence_test.go b/pkg/oracle/evidence_test.go similarity index 100% rename from oracle/evidence_test.go rename to pkg/oracle/evidence_test.go diff --git a/prover/proof_submitter/oracle_proof_submitter.go b/prover/proof_submitter/oracle_proof_submitter.go index 69100e8a6..b2c37f3da 100644 --- a/prover/proof_submitter/oracle_proof_submitter.go +++ b/prover/proof_submitter/oracle_proof_submitter.go @@ -14,7 +14,7 @@ import ( "github.com/taikoxyz/taiko-client/bindings" "github.com/taikoxyz/taiko-client/bindings/encoding" "github.com/taikoxyz/taiko-client/metrics" - "github.com/taikoxyz/taiko-client/oracle" + "github.com/taikoxyz/taiko-client/pkg/oracle" "github.com/taikoxyz/taiko-client/pkg/rpc" anchorTxValidator "github.com/taikoxyz/taiko-client/prover/anchor_tx_validator" proofProducer "github.com/taikoxyz/taiko-client/prover/proof_producer" From 85d1689c7e8a0bf4f99921c5e04cf8ac2651c8a9 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 25 Apr 2023 20:54:08 -0700 Subject: [PATCH 07/16] typo in error string for submitting proof --- prover/proof_submitter/util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prover/proof_submitter/util.go b/prover/proof_submitter/util.go index 1e2963684..231c686f3 100644 --- a/prover/proof_submitter/util.go +++ b/prover/proof_submitter/util.go @@ -24,7 +24,7 @@ var ( // isSubmitProofTxErrorRetryable checks whether the error returned by a proof submission transaction // is retryable. func isSubmitProofTxErrorRetryable(err error, blockID *big.Int) bool { - if strings.HasPrefix(err.Error(), "L1_NOT_ORACLE_PROVEN") || !strings.HasPrefix(err.Error(), "L1_") { + if strings.HasPrefix(err.Error(), "L1_NOT_ORACLE_PROVER") || !strings.HasPrefix(err.Error(), "L1_") { return true } From e62a83b9496c292472c9173beac6ea770a6af061 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 25 Apr 2023 20:56:35 -0700 Subject: [PATCH 08/16] move from oracle --- .../proof_submitter/oracle_proof_submitter.go | 3 +- prover/proof_submitter/util.go | 31 +++++++++++ prover/proof_submitter/util_test.go | 53 +++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/prover/proof_submitter/oracle_proof_submitter.go b/prover/proof_submitter/oracle_proof_submitter.go index b2c37f3da..c77625317 100644 --- a/prover/proof_submitter/oracle_proof_submitter.go +++ b/prover/proof_submitter/oracle_proof_submitter.go @@ -14,7 +14,6 @@ import ( "github.com/taikoxyz/taiko-client/bindings" "github.com/taikoxyz/taiko-client/bindings/encoding" "github.com/taikoxyz/taiko-client/metrics" - "github.com/taikoxyz/taiko-client/pkg/oracle" "github.com/taikoxyz/taiko-client/pkg/rpc" anchorTxValidator "github.com/taikoxyz/taiko-client/prover/anchor_tx_validator" proofProducer "github.com/taikoxyz/taiko-client/prover/proof_producer" @@ -163,7 +162,7 @@ func (s *OracleProofSubmitter) SubmitProof( Proof: nil, } - _, _, err = oracle.HashSignAndSetEvidenceForOracleProof(evidence, s.proverPrivKey) + _, _, err = hashSignAndSetEvidenceForOracleProof(evidence, s.proverPrivKey) if err != nil { return fmt.Errorf("failed to sign evidence: %w", err) } diff --git a/prover/proof_submitter/util.go b/prover/proof_submitter/util.go index 231c686f3..cab96d4c7 100644 --- a/prover/proof_submitter/util.go +++ b/prover/proof_submitter/util.go @@ -11,6 +11,7 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/taikoxyz/taiko-client/bindings/encoding" @@ -99,3 +100,33 @@ func sendTxWithBackoff( return nil } + +// HashSignAndSetEvidenceForOracleProof hashes and signs the TaikoL1Evidence according to the +// protoco spec to generate an "oracle proof" via the signature and v value. +func hashSignAndSetEvidenceForOracleProof( + evidence *encoding.TaikoL1Evidence, + privateKey *ecdsa.PrivateKey, +) ([]byte, uint8, error) { + evidence.VerifierId = 0 + evidence.Proof = nil + + inputToSign, err := encoding.EncodeProveBlockInput(evidence) + if err != nil { + return nil, 0, fmt.Errorf("failed to encode TaikoL1.proveBlock inputs: %w", err) + } + + hashed := crypto.Keccak256Hash(inputToSign) + + sig, err := crypto.Sign(hashed.Bytes(), privateKey) + if err != nil { + return nil, 0, fmt.Errorf("failed to sign TaikoL1Evidence: %w", err) + } + + // add 27 to be able to be ecrecover in solidity + v := uint8(int(sig[64])) + 27 + + evidence.VerifierId = uint16(v) + evidence.Proof = sig + + return sig, v, nil +} diff --git a/prover/proof_submitter/util_test.go b/prover/proof_submitter/util_test.go index cf39db471..4a2838e9e 100644 --- a/prover/proof_submitter/util_test.go +++ b/prover/proof_submitter/util_test.go @@ -2,11 +2,17 @@ package submitter import ( "context" + "crypto/ecdsa" + "crypto/elliptic" "errors" "math/big" + "math/rand" + "os" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/taikoxyz/taiko-client/bindings/encoding" ) func (s *ProofSubmitterTestSuite) TestIsSubmitProofTxErrorRetryable() { @@ -52,3 +58,50 @@ func (s *ProofSubmitterTestSuite) TestSendTxWithBackoff() { s.Nil(err) } + +// randomHash generates a random blob of data and returns it as a hash. +func randomHash() common.Hash { + var hash common.Hash + if n, err := rand.Read(hash[:]); n != common.HashLength || err != nil { + panic(err) + } + return hash +} + +func (s *ProofSubmitterTestSuite) TestHashAndSignEvidenceForOracleProof() { + evidence := &encoding.TaikoL1Evidence{ + MetaHash: randomHash(), + BlockHash: randomHash(), + ParentHash: randomHash(), + SignalRoot: randomHash(), + Graffiti: randomHash(), + Prover: common.BigToAddress(new(big.Int).SetUint64(rand.Uint64())), + ParentGasUsed: 1024, + GasUsed: 1024, + VerifierId: 0, + Proof: nil, + } + + privateKey, err := crypto.HexToECDSA(os.Getenv("L1_PROVER_PRIVATE_KEY")) + s.Nil(err) + + publicKey := privateKey.Public() + + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + s.True(ok) + + input, err := encoding.EncodeProveBlockInput(evidence) + s.Nil(err) + + hash := crypto.Keccak256Hash(input) + + sig, _, err := hashSignAndSetEvidenceForOracleProof(evidence, privateKey) + s.Nil(err) + + pubKey, err := crypto.Ecrecover(hash.Bytes(), sig) + s.Nil(err) + isValid := crypto.VerifySignature(pubKey, hash.Bytes(), sig[:64]) + s.True(isValid) + + s.Equal(elliptic.Marshal(publicKeyECDSA, publicKeyECDSA.X, publicKeyECDSA.Y), pubKey) +} From 20acdde4f0acafb2e8533d928abb9f92cf598fb5 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 25 Apr 2023 20:56:44 -0700 Subject: [PATCH 09/16] rm oracle folder --- pkg/oracle/evidence.go | 39 ----------------------- pkg/oracle/evidence_test.go | 62 ------------------------------------- 2 files changed, 101 deletions(-) delete mode 100644 pkg/oracle/evidence.go delete mode 100644 pkg/oracle/evidence_test.go diff --git a/pkg/oracle/evidence.go b/pkg/oracle/evidence.go deleted file mode 100644 index 96e011b8a..000000000 --- a/pkg/oracle/evidence.go +++ /dev/null @@ -1,39 +0,0 @@ -package oracle - -import ( - "crypto/ecdsa" - "fmt" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/taikoxyz/taiko-client/bindings/encoding" -) - -// HashSignAndSetEvidenceForOracleProof hashes and signs the TaikoL1Evidence according to the -// protoco spec to generate an "oracle proof" via the signature and v value. -func HashSignAndSetEvidenceForOracleProof( - evidence *encoding.TaikoL1Evidence, - privateKey *ecdsa.PrivateKey, -) ([]byte, uint8, error) { - evidence.VerifierId = 0 - evidence.Proof = nil - - inputToSign, err := encoding.EncodeProveBlockInput(evidence) - if err != nil { - return nil, 0, fmt.Errorf("failed to encode TaikoL1.proveBlock inputs: %w", err) - } - - hashed := crypto.Keccak256Hash(inputToSign) - - sig, err := crypto.Sign(hashed.Bytes(), privateKey) - if err != nil { - return nil, 0, fmt.Errorf("failed to sign TaikoL1Evidence: %w", err) - } - - // add 27 to be able to be ecrecover in solidity - v := uint8(int(sig[64])) + 27 - - evidence.VerifierId = uint16(v) - evidence.Proof = sig - - return sig, v, nil -} diff --git a/pkg/oracle/evidence_test.go b/pkg/oracle/evidence_test.go deleted file mode 100644 index fa6732376..000000000 --- a/pkg/oracle/evidence_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package oracle - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "math/big" - "math/rand" - "os" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/stretchr/testify/require" - "github.com/taikoxyz/taiko-client/bindings/encoding" -) - -// randomHash generates a random blob of data and returns it as a hash. -func randomHash() common.Hash { - var hash common.Hash - if n, err := rand.Read(hash[:]); n != common.HashLength || err != nil { - panic(err) - } - return hash -} - -func TestHashAndSignEvidenceForOracleProof(t *testing.T) { - evidence := &encoding.TaikoL1Evidence{ - MetaHash: randomHash(), - BlockHash: randomHash(), - ParentHash: randomHash(), - SignalRoot: randomHash(), - Graffiti: randomHash(), - Prover: common.BigToAddress(new(big.Int).SetUint64(rand.Uint64())), - ParentGasUsed: 1024, - GasUsed: 1024, - VerifierId: 0, - Proof: nil, - } - - privateKey, err := crypto.HexToECDSA(os.Getenv("L1_PROVER_PRIVATE_KEY")) - require.Nil(t, err) - - publicKey := privateKey.Public() - - publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) - require.True(t, ok) - - input, err := encoding.EncodeProveBlockInput(evidence) - require.Nil(t, err) - - hash := crypto.Keccak256Hash(input) - - sig, _, err := HashSignAndSetEvidenceForOracleProof(evidence, privateKey) - require.Nil(t, err) - - pubKey, err := crypto.Ecrecover(hash.Bytes(), sig) - require.Nil(t, err) - isValid := crypto.VerifySignature(pubKey, hash.Bytes(), sig[:64]) - require.True(t, isValid) - - require.Equal(t, elliptic.Marshal(publicKeyECDSA, publicKeyECDSA.X, publicKeyECDSA.Y), pubKey) -} From 1edf7351ad05e459496861035f8a9ebdc315b2da Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 25 Apr 2023 21:46:47 -0700 Subject: [PATCH 10/16] test --- prover/proof_submitter/util_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prover/proof_submitter/util_test.go b/prover/proof_submitter/util_test.go index 4a2838e9e..b7eadaa5a 100644 --- a/prover/proof_submitter/util_test.go +++ b/prover/proof_submitter/util_test.go @@ -17,7 +17,7 @@ import ( func (s *ProofSubmitterTestSuite) TestIsSubmitProofTxErrorRetryable() { s.True(isSubmitProofTxErrorRetryable(errors.New(testAddr.String()), common.Big0)) - s.True(isSubmitProofTxErrorRetryable(errors.New("L1_NOT_ORACLE_PROVEN"), common.Big0)) + s.True(isSubmitProofTxErrorRetryable(errors.New("L1_NOT_ORACLE_PROVER"), common.Big0)) s.False(isSubmitProofTxErrorRetryable(errors.New("L1_DUP_PROVERS"), common.Big0)) s.False(isSubmitProofTxErrorRetryable(errors.New("L1_"+testAddr.String()), common.Big0)) } From 64ac55eb6b2d130cb66f9d770237164355a8add9 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Wed, 26 Apr 2023 00:27:12 -0700 Subject: [PATCH 11/16] oracle proof producer instead of submitter --- .../proof_producer/oracle_proof_producer.go | 138 ++++++++++++ .../oracle_proof_producer_test.go | 62 ++++++ .../proof_submitter/oracle_proof_submitter.go | 208 ------------------ prover/proof_submitter/util.go | 31 --- prover/proof_submitter/util_test.go | 53 ----- .../proof_submitter/valid_proof_submitter.go | 8 + .../valid_proof_submitter_test.go | 1 + prover/prover.go | 59 +++-- 8 files changed, 237 insertions(+), 323 deletions(-) create mode 100644 prover/proof_producer/oracle_proof_producer.go create mode 100644 prover/proof_producer/oracle_proof_producer_test.go delete mode 100644 prover/proof_submitter/oracle_proof_submitter.go diff --git a/prover/proof_producer/oracle_proof_producer.go b/prover/proof_producer/oracle_proof_producer.go new file mode 100644 index 000000000..1e15bc95e --- /dev/null +++ b/prover/proof_producer/oracle_proof_producer.go @@ -0,0 +1,138 @@ +package producer + +import ( + "context" + "crypto/ecdsa" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + "github.com/taikoxyz/taiko-client/bindings" + "github.com/taikoxyz/taiko-client/bindings/encoding" + "github.com/taikoxyz/taiko-client/pkg/rpc" + anchorTxValidator "github.com/taikoxyz/taiko-client/prover/anchor_tx_validator" +) + +// OracleProducer is responsible for generating zk proofs from the given command line binary file. +type OracleProducer struct { + rpc *rpc.Client + proverPrivKey *ecdsa.PrivateKey + anchorTxValidator *anchorTxValidator.AnchorTxValidator +} + +// NewOracleProducer creates a new NewOracleProducer instance. +func NewOracleProducer( + rpc *rpc.Client, + proverPrivKey *ecdsa.PrivateKey, + taikoL2Address common.Address, +) (*OracleProducer, error) { + anchorValidator, err := anchorTxValidator.New(taikoL2Address, rpc.L2ChainID, rpc) + if err != nil { + return nil, err + } + + return &OracleProducer{rpc, proverPrivKey, anchorValidator}, nil +} + +// RequestProof implements the ProofProducer interface. +func (d *OracleProducer) RequestProof( + ctx context.Context, + opts *ProofRequestOptions, + blockID *big.Int, + meta *bindings.TaikoDataBlockMetadata, + header *types.Header, + resultCh chan *ProofWithHeader, +) error { + log.Info( + "Request oracle proof", + "blockID", blockID, + "beneficiary", meta.Beneficiary, + "height", header.Number, + "hash", header.Hash(), + ) + + block, err := d.rpc.L2.BlockByHash(ctx, header.Hash()) + if err != nil { + return fmt.Errorf("failed to get L2 block with given hash %s: %w", header.Hash(), err) + } + + anchorTx := block.Transactions()[0] + if err := d.anchorTxValidator.ValidateAnchorTx(ctx, anchorTx); err != nil { + return fmt.Errorf("invalid anchor transaction: %w", err) + } + + signalRoot, err := d.anchorTxValidator.GetAnchoredSignalRoot(ctx, anchorTx) + if err != nil { + return err + } + + parent, err := d.rpc.L2.BlockByHash(ctx, block.ParentHash()) + if err != nil { + return err + } + + blockInfo, err := d.rpc.TaikoL1.GetBlock(nil, blockID) + if err != nil { + return err + } + + // signature should be done with proof set to nil, verifierID set to 0, + // and prover set to 0 address. + evidence := &encoding.TaikoL1Evidence{ + MetaHash: blockInfo.MetaHash, + ParentHash: block.ParentHash(), + BlockHash: block.Hash(), + SignalRoot: signalRoot, + Graffiti: [32]byte{}, + Prover: common.HexToAddress("0x0000000000000000000000000000000000000000"), + ParentGasUsed: uint32(parent.GasUsed()), + GasUsed: uint32(block.GasUsed()), + VerifierId: 0, + Proof: nil, + } + + proof, v, err := hashAndSignForOracleProof(evidence, d.proverPrivKey) + if err != nil { + return fmt.Errorf("failed to sign evidence: %w", err) + } + + resultCh <- &ProofWithHeader{ + BlockID: blockID, + Header: header, + Meta: meta, + ZkProof: proof, + Degree: uint64(v), + } + + return nil +} + +// HashSignAndSetEvidenceForOracleProof hashes and signs the TaikoL1Evidence according to the +// protoco spec to generate an "oracle proof" via the signature and v value. +func hashAndSignForOracleProof( + evidence *encoding.TaikoL1Evidence, + privateKey *ecdsa.PrivateKey, +) ([]byte, uint8, error) { + evidence.VerifierId = 0 + evidence.Proof = nil + + inputToSign, err := encoding.EncodeProveBlockInput(evidence) + if err != nil { + return nil, 0, fmt.Errorf("failed to encode TaikoL1.proveBlock inputs: %w", err) + } + + hashed := crypto.Keccak256Hash(inputToSign) + + sig, err := crypto.Sign(hashed.Bytes(), privateKey) + if err != nil { + return nil, 0, fmt.Errorf("failed to sign TaikoL1Evidence: %w", err) + } + + // add 27 to be able to be ecrecover in solidity + v := uint8(int(sig[64])) + 27 + + return sig, v, nil +} diff --git a/prover/proof_producer/oracle_proof_producer_test.go b/prover/proof_producer/oracle_proof_producer_test.go new file mode 100644 index 000000000..c946fefa9 --- /dev/null +++ b/prover/proof_producer/oracle_proof_producer_test.go @@ -0,0 +1,62 @@ +package producer + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "math/big" + "math/rand" + "os" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" + "github.com/taikoxyz/taiko-client/bindings/encoding" +) + +// randomHash generates a random blob of data and returns it as a hash. +func randomHash() common.Hash { + var hash common.Hash + if n, err := rand.Read(hash[:]); n != common.HashLength || err != nil { + panic(err) + } + return hash +} + +func TestHashAndSignOracleProof(t *testing.T) { + evidence := &encoding.TaikoL1Evidence{ + MetaHash: randomHash(), + BlockHash: randomHash(), + ParentHash: randomHash(), + SignalRoot: randomHash(), + Graffiti: randomHash(), + Prover: common.BigToAddress(new(big.Int).SetUint64(rand.Uint64())), + ParentGasUsed: 1024, + GasUsed: 1024, + VerifierId: 0, + Proof: nil, + } + + privateKey, err := crypto.HexToECDSA(os.Getenv("L1_PROVER_PRIVATE_KEY")) + require.Nil(t, err) + + publicKey := privateKey.Public() + + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + require.True(t, ok) + + input, err := encoding.EncodeProveBlockInput(evidence) + require.Nil(t, err) + + hash := crypto.Keccak256Hash(input) + + sig, _, err := hashAndSignForOracleProof(evidence, privateKey) + require.Nil(t, err) + + pubKey, err := crypto.Ecrecover(hash.Bytes(), sig) + require.Nil(t, err) + isValid := crypto.VerifySignature(pubKey, hash.Bytes(), sig[:64]) + require.True(t, isValid) + + require.Equal(t, elliptic.Marshal(publicKeyECDSA, publicKeyECDSA.X, publicKeyECDSA.Y), pubKey) +} diff --git a/prover/proof_submitter/oracle_proof_submitter.go b/prover/proof_submitter/oracle_proof_submitter.go deleted file mode 100644 index c77625317..000000000 --- a/prover/proof_submitter/oracle_proof_submitter.go +++ /dev/null @@ -1,208 +0,0 @@ -package submitter - -import ( - "context" - "crypto/ecdsa" - "errors" - "fmt" - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" - "github.com/taikoxyz/taiko-client/bindings" - "github.com/taikoxyz/taiko-client/bindings/encoding" - "github.com/taikoxyz/taiko-client/metrics" - "github.com/taikoxyz/taiko-client/pkg/rpc" - anchorTxValidator "github.com/taikoxyz/taiko-client/prover/anchor_tx_validator" - proofProducer "github.com/taikoxyz/taiko-client/prover/proof_producer" -) - -var _ ProofSubmitter = (*OracleProofSubmitter)(nil) - -// OracleProofSubmitter is responsible requesting zk proofs for the given valid L2 -// blocks, and submitting the generated proofs to the TaikoL1 smart contract. -type OracleProofSubmitter struct { - rpc *rpc.Client - resultCh chan *proofProducer.ProofWithHeader - anchorTxValidator *anchorTxValidator.AnchorTxValidator - proverPrivKey *ecdsa.PrivateKey - proverAddress common.Address - mutex *sync.Mutex -} - -// NewOracleProofSubmitter creates a new OracleProofSubmitter instance. -func NewOracleProofSubmitter( - rpc *rpc.Client, - resultCh chan *proofProducer.ProofWithHeader, - taikoL2Address common.Address, - proverPrivKey *ecdsa.PrivateKey, - mutex *sync.Mutex, -) (*OracleProofSubmitter, error) { - anchorValidator, err := anchorTxValidator.New(taikoL2Address, rpc.L2ChainID, rpc) - if err != nil { - return nil, err - } - - return &OracleProofSubmitter{ - rpc: rpc, - resultCh: resultCh, - anchorTxValidator: anchorValidator, - proverPrivKey: proverPrivKey, - proverAddress: crypto.PubkeyToAddress(proverPrivKey.PublicKey), - mutex: mutex, - }, nil -} - -// RequestProof implements the ProofSubmitter interface. -func (s *OracleProofSubmitter) RequestProof(ctx context.Context, event *bindings.TaikoL1ClientBlockProposed) error { - l1Origin, err := s.rpc.WaitL1Origin(ctx, event.Id) - if err != nil { - return fmt.Errorf("failed to fetch l1Origin, blockID: %d, err: %w", event.Id, err) - } - - // Get the header of the block to prove from L2 execution engine. - header, err := s.rpc.L2.HeaderByHash(ctx, l1Origin.L2BlockHash) - if err != nil { - return err - } - - metrics.ProverQueuedProofCounter.Inc(1) - metrics.ProverQueuedValidProofCounter.Inc(1) - - // "proof" for Oracle Proof is actually signed in SubmitProof, since - // we already have the evidence and to not duplicate RPC calls. - // "Proof" and "Degree" fields are not used here. - s.resultCh <- &proofProducer.ProofWithHeader{ - Header: header, - BlockID: event.Id, - Meta: &event.Meta, - } - - return nil -} - -// SubmitProof implements the ProofSubmitter interface. -func (s *OracleProofSubmitter) SubmitProof( - ctx context.Context, - proofWithHeader *proofProducer.ProofWithHeader, -) (err error) { - log.Info( - "New oracle block proof", - "blockID", proofWithHeader.BlockID, - "beneficiary", proofWithHeader.Meta.Beneficiary, - "hash", proofWithHeader.Header.Hash(), - ) - var ( - blockID = proofWithHeader.BlockID - header = proofWithHeader.Header - ) - - metrics.ProverReceivedProofCounter.Inc(1) - metrics.ProverReceivedValidProofCounter.Inc(1) - - // Get the corresponding L2 block. - block, err := s.rpc.L2.BlockByHash(ctx, header.Hash()) - if err != nil { - return fmt.Errorf("failed to get L2 block with given hash %s: %w", header.Hash(), err) - } - - log.Debug( - "Get the L2 block to prove", - "blockID", blockID, - "hash", block.Hash(), - "root", header.Root.String(), - "transactions", len(block.Transactions()), - ) - - if block.Transactions().Len() == 0 { - return fmt.Errorf("invalid block without anchor transaction, blockID %s", blockID) - } - - // Validate TaikoL2.anchor transaction inside the L2 block. - anchorTx := block.Transactions()[0] - if err := s.anchorTxValidator.ValidateAnchorTx(ctx, anchorTx); err != nil { - return fmt.Errorf("invalid anchor transaction: %w", err) - } - - // Get and validate this anchor transaction's receipt. - _, err = s.anchorTxValidator.GetAndValidateAnchorTxReceipt(ctx, anchorTx) - if err != nil { - return fmt.Errorf("failed to fetch anchor transaction receipt: %w", err) - } - - signalRoot, err := s.anchorTxValidator.GetAnchoredSignalRoot(ctx, anchorTx) - if err != nil { - return err - } - - parent, err := s.rpc.L2.BlockByHash(ctx, block.ParentHash()) - if err != nil { - return err - } - - blockInfo, err := s.rpc.TaikoL1.GetBlock(nil, blockID) - if err != nil { - return err - } - - // signature should be done with proof set to nil, verifierID set to 0, - // and prover set to 0 address. - evidence := &encoding.TaikoL1Evidence{ - MetaHash: blockInfo.MetaHash, - ParentHash: block.ParentHash(), - BlockHash: block.Hash(), - SignalRoot: signalRoot, - Graffiti: [32]byte{}, - Prover: common.HexToAddress("0x0000000000000000000000000000000000000000"), - ParentGasUsed: uint32(parent.GasUsed()), - GasUsed: uint32(block.GasUsed()), - VerifierId: 0, - Proof: nil, - } - - _, _, err = hashSignAndSetEvidenceForOracleProof(evidence, s.proverPrivKey) - if err != nil { - return fmt.Errorf("failed to sign evidence: %w", err) - } - - input, err := encoding.EncodeProveBlockInput(evidence) - if err != nil { - return fmt.Errorf("failed to encode TaikoL1.proveBlock inputs: %w", err) - } - - // Send the TaikoL1.proveBlock transaction. - txOpts, err := getProveBlocksTxOpts(ctx, s.rpc.L1, s.rpc.L1ChainID, s.proverPrivKey) - if err != nil { - return err - } - - sendTx := func() (*types.Transaction, error) { - s.mutex.Lock() - defer s.mutex.Unlock() - - return s.rpc.TaikoL1.ProveBlock(txOpts, blockID, input) - } - - if err := sendTxWithBackoff(ctx, s.rpc, blockID, sendTx); err != nil { - if errors.Is(err, errUnretryable) { - return nil - } - - return err - } - - log.Info( - "✅ Oracle block proved", - "blockID", proofWithHeader.BlockID, - "hash", block.Hash(), "height", block.Number(), - "transactions", block.Transactions().Len(), - ) - - metrics.ProverSentProofCounter.Inc(1) - metrics.ProverSentValidProofCounter.Inc(1) - metrics.ProverLatestProvenBlockIDGauge.Update(proofWithHeader.BlockID.Int64()) - - return nil -} diff --git a/prover/proof_submitter/util.go b/prover/proof_submitter/util.go index cab96d4c7..231c686f3 100644 --- a/prover/proof_submitter/util.go +++ b/prover/proof_submitter/util.go @@ -11,7 +11,6 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/taikoxyz/taiko-client/bindings/encoding" @@ -100,33 +99,3 @@ func sendTxWithBackoff( return nil } - -// HashSignAndSetEvidenceForOracleProof hashes and signs the TaikoL1Evidence according to the -// protoco spec to generate an "oracle proof" via the signature and v value. -func hashSignAndSetEvidenceForOracleProof( - evidence *encoding.TaikoL1Evidence, - privateKey *ecdsa.PrivateKey, -) ([]byte, uint8, error) { - evidence.VerifierId = 0 - evidence.Proof = nil - - inputToSign, err := encoding.EncodeProveBlockInput(evidence) - if err != nil { - return nil, 0, fmt.Errorf("failed to encode TaikoL1.proveBlock inputs: %w", err) - } - - hashed := crypto.Keccak256Hash(inputToSign) - - sig, err := crypto.Sign(hashed.Bytes(), privateKey) - if err != nil { - return nil, 0, fmt.Errorf("failed to sign TaikoL1Evidence: %w", err) - } - - // add 27 to be able to be ecrecover in solidity - v := uint8(int(sig[64])) + 27 - - evidence.VerifierId = uint16(v) - evidence.Proof = sig - - return sig, v, nil -} diff --git a/prover/proof_submitter/util_test.go b/prover/proof_submitter/util_test.go index b7eadaa5a..602af89c3 100644 --- a/prover/proof_submitter/util_test.go +++ b/prover/proof_submitter/util_test.go @@ -2,17 +2,11 @@ package submitter import ( "context" - "crypto/ecdsa" - "crypto/elliptic" "errors" "math/big" - "math/rand" - "os" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/taikoxyz/taiko-client/bindings/encoding" ) func (s *ProofSubmitterTestSuite) TestIsSubmitProofTxErrorRetryable() { @@ -58,50 +52,3 @@ func (s *ProofSubmitterTestSuite) TestSendTxWithBackoff() { s.Nil(err) } - -// randomHash generates a random blob of data and returns it as a hash. -func randomHash() common.Hash { - var hash common.Hash - if n, err := rand.Read(hash[:]); n != common.HashLength || err != nil { - panic(err) - } - return hash -} - -func (s *ProofSubmitterTestSuite) TestHashAndSignEvidenceForOracleProof() { - evidence := &encoding.TaikoL1Evidence{ - MetaHash: randomHash(), - BlockHash: randomHash(), - ParentHash: randomHash(), - SignalRoot: randomHash(), - Graffiti: randomHash(), - Prover: common.BigToAddress(new(big.Int).SetUint64(rand.Uint64())), - ParentGasUsed: 1024, - GasUsed: 1024, - VerifierId: 0, - Proof: nil, - } - - privateKey, err := crypto.HexToECDSA(os.Getenv("L1_PROVER_PRIVATE_KEY")) - s.Nil(err) - - publicKey := privateKey.Public() - - publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) - s.True(ok) - - input, err := encoding.EncodeProveBlockInput(evidence) - s.Nil(err) - - hash := crypto.Keccak256Hash(input) - - sig, _, err := hashSignAndSetEvidenceForOracleProof(evidence, privateKey) - s.Nil(err) - - pubKey, err := crypto.Ecrecover(hash.Bytes(), sig) - s.Nil(err) - isValid := crypto.VerifySignature(pubKey, hash.Bytes(), sig[:64]) - s.True(isValid) - - s.Equal(elliptic.Marshal(publicKeyECDSA, publicKeyECDSA.X, publicKeyECDSA.Y), pubKey) -} diff --git a/prover/proof_submitter/valid_proof_submitter.go b/prover/proof_submitter/valid_proof_submitter.go index 9b77f7b8f..376fca988 100644 --- a/prover/proof_submitter/valid_proof_submitter.go +++ b/prover/proof_submitter/valid_proof_submitter.go @@ -31,6 +31,7 @@ type ValidProofSubmitter struct { proverPrivKey *ecdsa.PrivateKey proverAddress common.Address mutex *sync.Mutex + isOracle bool } // NewValidProofSubmitter creates a new ValidProofSubmitter instance. @@ -41,6 +42,7 @@ func NewValidProofSubmitter( taikoL2Address common.Address, proverPrivKey *ecdsa.PrivateKey, mutex *sync.Mutex, + isOracle bool, ) (*ValidProofSubmitter, error) { anchorValidator, err := anchorTxValidator.New(taikoL2Address, rpc.L2ChainID, rpc) if err != nil { @@ -55,6 +57,7 @@ func NewValidProofSubmitter( proverPrivKey: proverPrivKey, proverAddress: crypto.PubkeyToAddress(proverPrivKey.PublicKey), mutex: mutex, + isOracle: isOracle, }, nil } @@ -172,6 +175,11 @@ func (s *ValidProofSubmitter) SubmitProof( Proof: zkProof, } + if s.isOracle { + evidence.Prover = common.HexToAddress("0x0000000000000000000000000000000000000000") + evidence.VerifierId = uint16(proofWithHeader.Degree) + } + input, err := encoding.EncodeProveBlockInput(evidence) if err != nil { return fmt.Errorf("failed to encode TaikoL1.proveBlock inputs: %w", err) diff --git a/prover/proof_submitter/valid_proof_submitter_test.go b/prover/proof_submitter/valid_proof_submitter_test.go index 975ecbc9d..f750a2af5 100644 --- a/prover/proof_submitter/valid_proof_submitter_test.go +++ b/prover/proof_submitter/valid_proof_submitter_test.go @@ -45,6 +45,7 @@ func (s *ProofSubmitterTestSuite) SetupTest() { common.HexToAddress(os.Getenv("TAIKO_L2_ADDRESS")), l1ProverPrivKey, &sync.Mutex{}, + false, ) s.Nil(err) diff --git a/prover/prover.go b/prover/prover.go index b8c5bce85..243ba0919 100644 --- a/prover/prover.go +++ b/prover/prover.go @@ -123,49 +123,46 @@ func InitFromConfig(ctx context.Context, p *Prover, cfg *Config) (err error) { p.proposeConcurrencyGuard = make(chan struct{}, cfg.MaxConcurrentProvingJobs) p.submitProofConcurrencyGuard = make(chan struct{}, cfg.MaxConcurrentProvingJobs) + var producer proofProducer.ProofProducer + if cfg.OracleProver { - // Proof submitter - if p.validProofSubmitter, err = proofSubmitter.NewOracleProofSubmitter( + if producer, err = proofProducer.NewOracleProducer( p.rpc, - p.proveValidProofCh, - p.cfg.TaikoL2Address, p.cfg.L1ProverPrivKey, - p.submitProofTxMutex, + p.cfg.TaikoL2Address, ); err != nil { return err } - } else { - var producer proofProducer.ProofProducer - - if cfg.Dummy { - producer = &proofProducer.DummyProofProducer{ - RandomDummyProofDelayLowerBound: p.cfg.RandomDummyProofDelayLowerBound, - RandomDummyProofDelayUpperBound: p.cfg.RandomDummyProofDelayUpperBound, - } - } else { - if producer, err = proofProducer.NewZkevmRpcdProducer( - cfg.ZKEvmRpcdEndpoint, - cfg.ZkEvmRpcdParamsPath, - cfg.L1HttpEndpoint, - cfg.L2HttpEndpoint, - true, - ); err != nil { - return err - } + } else if cfg.Dummy { + producer = &proofProducer.DummyProofProducer{ + RandomDummyProofDelayLowerBound: p.cfg.RandomDummyProofDelayLowerBound, + RandomDummyProofDelayUpperBound: p.cfg.RandomDummyProofDelayUpperBound, } - // Proof submitter - if p.validProofSubmitter, err = proofSubmitter.NewValidProofSubmitter( - p.rpc, - producer, - p.proveValidProofCh, - p.cfg.TaikoL2Address, - p.cfg.L1ProverPrivKey, - p.submitProofTxMutex, + } else { + if producer, err = proofProducer.NewZkevmRpcdProducer( + cfg.ZKEvmRpcdEndpoint, + cfg.ZkEvmRpcdParamsPath, + cfg.L1HttpEndpoint, + cfg.L2HttpEndpoint, + true, ); err != nil { return err } } + // Proof submitter + if p.validProofSubmitter, err = proofSubmitter.NewValidProofSubmitter( + p.rpc, + producer, + p.proveValidProofCh, + p.cfg.TaikoL2Address, + p.cfg.L1ProverPrivKey, + p.submitProofTxMutex, + p.cfg.OracleProver, + ); err != nil { + return err + } + return nil } From d901227a5864c00c0966f58af8bea04eb8308b25 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Wed, 26 Apr 2023 00:29:01 -0700 Subject: [PATCH 12/16] rf --- prover/proof_submitter/valid_proof_submitter.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/prover/proof_submitter/valid_proof_submitter.go b/prover/proof_submitter/valid_proof_submitter.go index 376fca988..caacdcbc6 100644 --- a/prover/proof_submitter/valid_proof_submitter.go +++ b/prover/proof_submitter/valid_proof_submitter.go @@ -142,11 +142,6 @@ func (s *ValidProofSubmitter) SubmitProof( return fmt.Errorf("failed to fetch anchor transaction receipt: %w", err) } - circuitsIdx, err := proofProducer.DegreeToCircuitsIdx(proofWithHeader.Degree) - if err != nil { - return err - } - signalRoot, err := s.anchorTxValidator.GetAnchoredSignalRoot(ctx, anchorTx) if err != nil { return err @@ -171,15 +166,23 @@ func (s *ValidProofSubmitter) SubmitProof( Prover: s.proverAddress, ParentGasUsed: uint32(parent.GasUsed()), GasUsed: uint32(block.GasUsed()), - VerifierId: circuitsIdx, Proof: zkProof, } + var circuitsIdx uint16 + if s.isOracle { evidence.Prover = common.HexToAddress("0x0000000000000000000000000000000000000000") - evidence.VerifierId = uint16(proofWithHeader.Degree) + circuitsIdx = uint16(proofWithHeader.Degree) + } else { + circuitsIdx, err = proofProducer.DegreeToCircuitsIdx(proofWithHeader.Degree) + if err != nil { + return err + } } + evidence.VerifierId = circuitsIdx + input, err := encoding.EncodeProveBlockInput(evidence) if err != nil { return fmt.Errorf("failed to encode TaikoL1.proveBlock inputs: %w", err) From 5f6fd98058fa932434a6614f08299f4069af7ac5 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Wed, 26 Apr 2023 00:31:19 -0700 Subject: [PATCH 13/16] clean up --- prover/proof_submitter/valid_proof_submitter.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/prover/proof_submitter/valid_proof_submitter.go b/prover/proof_submitter/valid_proof_submitter.go index caacdcbc6..889975c06 100644 --- a/prover/proof_submitter/valid_proof_submitter.go +++ b/prover/proof_submitter/valid_proof_submitter.go @@ -163,24 +163,26 @@ func (s *ValidProofSubmitter) SubmitProof( BlockHash: block.Hash(), SignalRoot: signalRoot, Graffiti: [32]byte{}, - Prover: s.proverAddress, ParentGasUsed: uint32(parent.GasUsed()), GasUsed: uint32(block.GasUsed()), Proof: zkProof, } var circuitsIdx uint16 + var prover common.Address if s.isOracle { - evidence.Prover = common.HexToAddress("0x0000000000000000000000000000000000000000") + prover = common.HexToAddress("0x0000000000000000000000000000000000000000") circuitsIdx = uint16(proofWithHeader.Degree) } else { + prover = s.proverAddress + circuitsIdx, err = proofProducer.DegreeToCircuitsIdx(proofWithHeader.Degree) if err != nil { return err } } - + evidence.Prover = prover evidence.VerifierId = circuitsIdx input, err := encoding.EncodeProveBlockInput(evidence) From 417d9682e9ed7eb1b2c9c9ac656033c810af0255 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Wed, 26 Apr 2023 00:46:26 -0700 Subject: [PATCH 14/16] isOracle --- prover/proof_producer/oracle_proof_producer.go | 3 +-- prover/proof_submitter/valid_proof_submitter.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/prover/proof_producer/oracle_proof_producer.go b/prover/proof_producer/oracle_proof_producer.go index 1e15bc95e..e080692eb 100644 --- a/prover/proof_producer/oracle_proof_producer.go +++ b/prover/proof_producer/oracle_proof_producer.go @@ -94,7 +94,7 @@ func (d *OracleProducer) RequestProof( Proof: nil, } - proof, v, err := hashAndSignForOracleProof(evidence, d.proverPrivKey) + proof, _, err := hashAndSignForOracleProof(evidence, d.proverPrivKey) if err != nil { return fmt.Errorf("failed to sign evidence: %w", err) } @@ -104,7 +104,6 @@ func (d *OracleProducer) RequestProof( Header: header, Meta: meta, ZkProof: proof, - Degree: uint64(v), } return nil diff --git a/prover/proof_submitter/valid_proof_submitter.go b/prover/proof_submitter/valid_proof_submitter.go index 889975c06..c111e61a8 100644 --- a/prover/proof_submitter/valid_proof_submitter.go +++ b/prover/proof_submitter/valid_proof_submitter.go @@ -173,7 +173,7 @@ func (s *ValidProofSubmitter) SubmitProof( if s.isOracle { prover = common.HexToAddress("0x0000000000000000000000000000000000000000") - circuitsIdx = uint16(proofWithHeader.Degree) + circuitsIdx = uint16(int(zkProof[64])) + 27 } else { prover = s.proverAddress From 4efafd1700edf16562384a3010640420ad7d73f8 Mon Sep 17 00:00:00 2001 From: jeff <113397187+cyberhorsey@users.noreply.github.com> Date: Thu, 27 Apr 2023 00:46:49 -0700 Subject: [PATCH 15/16] Update prover/proof_producer/oracle_proof_producer.go Co-authored-by: David --- prover/proof_producer/oracle_proof_producer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prover/proof_producer/oracle_proof_producer.go b/prover/proof_producer/oracle_proof_producer.go index e080692eb..f102d499b 100644 --- a/prover/proof_producer/oracle_proof_producer.go +++ b/prover/proof_producer/oracle_proof_producer.go @@ -110,7 +110,7 @@ func (d *OracleProducer) RequestProof( } // HashSignAndSetEvidenceForOracleProof hashes and signs the TaikoL1Evidence according to the -// protoco spec to generate an "oracle proof" via the signature and v value. +// protocol spec to generate an "oracle proof" via the signature and v value. func hashAndSignForOracleProof( evidence *encoding.TaikoL1Evidence, privateKey *ecdsa.PrivateKey, From bda47aef24be2453262f45508a5919b60595651a Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Thu, 27 Apr 2023 00:49:22 -0700 Subject: [PATCH 16/16] fixes --- prover/proof_producer/oracle_proof_producer.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/prover/proof_producer/oracle_proof_producer.go b/prover/proof_producer/oracle_proof_producer.go index f102d499b..db9abd60c 100644 --- a/prover/proof_producer/oracle_proof_producer.go +++ b/prover/proof_producer/oracle_proof_producer.go @@ -16,7 +16,8 @@ import ( anchorTxValidator "github.com/taikoxyz/taiko-client/prover/anchor_tx_validator" ) -// OracleProducer is responsible for generating zk proofs from the given command line binary file. +// OracleProducer is responsible for generating a fake "zkproof" consisting +// of a signature of the evidence. type OracleProducer struct { rpc *rpc.Client proverPrivKey *ecdsa.PrivateKey @@ -115,9 +116,6 @@ func hashAndSignForOracleProof( evidence *encoding.TaikoL1Evidence, privateKey *ecdsa.PrivateKey, ) ([]byte, uint8, error) { - evidence.VerifierId = 0 - evidence.Proof = nil - inputToSign, err := encoding.EncodeProveBlockInput(evidence) if err != nil { return nil, 0, fmt.Errorf("failed to encode TaikoL1.proveBlock inputs: %w", err)