This repository has been archived by the owner on May 11, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 332
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(driver, bindings): optimize assembling anchor transactions b…
…y introducing `AnchorConstructor` and `FixedKSigner` structs && introduce `bindings.ProtocolConstants` (#59)
- Loading branch information
1 parent
b5f74cf
commit cc2fba6
Showing
28 changed files
with
453 additions
and
629 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
6ef307486711f17b3a3fb225055179525822b05d | ||
0652595af38f17ed4bfc6e72bca64d2a6fb5616c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,34 @@ | ||
package bindings | ||
|
||
import ( | ||
"math/big" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
) | ||
|
||
var ( | ||
// Account address and private key of golden touch account. | ||
// Account address and private key of golden touch account, defined in protocol's LibAnchorSignature. | ||
// ref: https://github.com/taikoxyz/taiko-mono/blob/main/packages/protocol/contracts/libs/LibAnchorSignature.sol | ||
GoldenTouchAddress = common.HexToAddress("0x0000777735367b36bC9B61C50022d9D0700dB4Ec") | ||
GoldenTouchPrivKey = "0x92954368afd3caa1f3ce3ead0069c1af414054aefe1ef9aeacc1bf426222ce38" | ||
) | ||
|
||
// ProtocolConstants contains some constants used by Taiko protocol, defined in protocol's LibConstants. | ||
// NOTE: this struct *MUST* match the return values of TaikoL1.getConstants method. | ||
// ref: https://github.com/taikoxyz/taiko-mono/blob/main/packages/protocol/contracts/libs/LibConstants.sol | ||
type ProtocolConstants struct { | ||
ZKProofsPerBlock *big.Int // uint256 K_ZKPROOFS_PER_BLOCK | ||
ChainID *big.Int // uint256 TAIKO_CHAIN_ID | ||
MaxProposedBlocks *big.Int // uint256 TAIKO_MAX_PROPOSED_BLOCKS | ||
MaxVerificationsPerTx *big.Int // uint256 TAIKO_MAX_VERIFICATIONS_PER_TX | ||
CommitDelayConfirmations *big.Int // uint256 K_COMMIT_DELAY_CONFIRMATIONS | ||
MaxProofsPerForkChoice *big.Int // uint256 TAIKO_MAX_PROOFS_PER_FORK_CHOICE | ||
BlockMaxGasLimit *big.Int // uint256 TAIKO_BLOCK_MAX_GAS_LIMIT | ||
BlockMaxTxs *big.Int // uint256 TAIKO_BLOCK_MAX_TXS | ||
BlockDeadendHash common.Hash // bytes32 TAIKO_BLOCK_DEADEND_HASH | ||
TxListMaxBytes *big.Int // uint256 TAIKO_TXLIST_MAX_BYTES | ||
TxMinGasLimit *big.Int // uint256 TAIKO_TX_MIN_GAS_LIMIT | ||
AnchorTxGasLimit *big.Int // uint256 V1_ANCHOR_TX_GAS_LIMIT | ||
AnchorTxSelector [4]byte // bytes4 V1_ANCHOR_TX_SELECTOR | ||
InvalidateBlockLogTopic [32]byte // bytes32 V1_INVALIDATE_BLOCK_LOG_TOPIC | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package driver | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"math/big" | ||
|
||
"github.com/decred/dcrd/dcrec/secp256k1/v4" | ||
"github.com/ethereum/go-ethereum/accounts/abi/bind" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/types" | ||
"github.com/ethereum/go-ethereum/log" | ||
"github.com/taikoxyz/taiko-client/driver/signer" | ||
"github.com/taikoxyz/taiko-client/pkg/rpc" | ||
) | ||
|
||
// AnchorConstructor is responsible for assembling the anchor transaction (V1TaikoL2.anchor) in | ||
// each L2 block, which is always the first transaction. | ||
type AnchorConstructor struct { | ||
rpc *rpc.Client | ||
gasLimit uint64 | ||
goldenTouchAddress common.Address | ||
signer *signer.FixedKSigner | ||
} | ||
|
||
// NewAnchorConstructor creates a new AnchorConstructor instance. | ||
func NewAnchorConstructor( | ||
rpc *rpc.Client, | ||
gasLimit uint64, | ||
goldenTouchAddress common.Address, | ||
goldenTouchPrivKey string, | ||
) (*AnchorConstructor, error) { | ||
signer, err := signer.NewFixedKSigner(goldenTouchPrivKey) | ||
if err != nil { | ||
return nil, fmt.Errorf("invalid golden touch private key %s", goldenTouchPrivKey) | ||
} | ||
|
||
return &AnchorConstructor{ | ||
rpc: rpc, | ||
gasLimit: gasLimit, | ||
goldenTouchAddress: goldenTouchAddress, | ||
signer: signer, | ||
}, nil | ||
} | ||
|
||
// AssembleAnchorTx assembles a signed TaikoL2.anchor transaction. | ||
func (c *AnchorConstructor) AssembleAnchorTx( | ||
ctx context.Context, | ||
// Parameters of the TaikoL2.anchor transaction. | ||
l1Height *big.Int, | ||
l1Hash common.Hash, | ||
// Height of the L2 block which including the TaikoL2.anchor transaction. | ||
l2Height *big.Int, | ||
) (*types.Transaction, error) { | ||
opts, err := c.transactOpts(ctx, l2Height) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return c.rpc.TaikoL2.Anchor(opts, l1Height, l1Hash) | ||
} | ||
|
||
// transactOpts is a utility method to create some transact options of the anchor transaction in given L2 block with | ||
// golden touch account's private key. | ||
func (c *AnchorConstructor) transactOpts(ctx context.Context, l2Height *big.Int) (*bind.TransactOpts, error) { | ||
signer := types.LatestSignerForChainID(c.rpc.L2ChainID) | ||
|
||
// Get the nonce of golden touch account at the specified height. | ||
nonce, err := c.rpc.L2AccountNonce(ctx, c.goldenTouchAddress, l2Height) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &bind.TransactOpts{ | ||
From: c.goldenTouchAddress, | ||
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) { | ||
if address != c.goldenTouchAddress { | ||
return nil, bind.ErrNotAuthorized | ||
} | ||
signature, err := c.signTxPayload(signer.Hash(tx).Bytes()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return tx.WithSignature(signer, signature) | ||
}, | ||
Nonce: new(big.Int).SetUint64(nonce), | ||
Context: ctx, | ||
GasPrice: common.Big0, | ||
GasLimit: c.gasLimit, | ||
NoSend: true, | ||
}, nil | ||
} | ||
|
||
// signTxPayload calculates an ECDSA signature for an anchor transaction. | ||
// ref: https://github.com/taikoxyz/taiko-mono/blob/main/packages/protocol/contracts/libs/LibAnchorSignature.sol | ||
func (c *AnchorConstructor) signTxPayload(hash []byte) ([]byte, error) { | ||
if len(hash) != 32 { | ||
return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash)) | ||
} | ||
|
||
// Try k = 1. | ||
sig, ok := c.signer.SignWithK(new(secp256k1.ModNScalar).SetInt(1))(hash) | ||
if !ok { | ||
// Try k = 2. | ||
sig, ok = c.signer.SignWithK(new(secp256k1.ModNScalar).SetInt(2))(hash) | ||
if !ok { | ||
log.Crit("Failed to sign V1TaikoL2.anchor transaction using K = 1 and K = 2") | ||
} | ||
} | ||
|
||
return sig[:], nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package driver | ||
|
||
import ( | ||
"context" | ||
"math/rand" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/common/hexutil" | ||
"github.com/ethereum/go-ethereum/crypto" | ||
"github.com/taikoxyz/taiko-client/bindings" | ||
"github.com/taikoxyz/taiko-client/testutils" | ||
) | ||
|
||
func (s *DriverTestSuite) TestNewAnchorTransactor() { | ||
gasLimit := rand.Uint64() | ||
c, err := NewAnchorConstructor( | ||
s.RpcClient, | ||
gasLimit, bindings.GoldenTouchAddress, | ||
bindings.GoldenTouchPrivKey, | ||
) | ||
s.Nil(err) | ||
|
||
opts, err := c.transactOpts(context.Background(), common.Big0) | ||
s.Nil(err) | ||
s.Equal(true, opts.NoSend) | ||
s.Equal(gasLimit, opts.GasLimit) | ||
s.Equal(common.Big0, opts.GasPrice) | ||
s.Equal(common.Big0, opts.Nonce) | ||
s.Equal(bindings.GoldenTouchAddress, opts.From) | ||
} | ||
|
||
func (s *DriverTestSuite) TestSign() { | ||
// Payload 1 | ||
hash := hexutil.MustDecode("0x44943399d1507f3ce7525e9be2f987c3db9136dc759cb7f92f742154196868b9") | ||
signatureBytes := testutils.SignatureFromRSV( | ||
"0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", | ||
"0x782a1e70872ecc1a9f740dd445664543f8b7598c94582720bca9a8c48d6a4766", | ||
1, | ||
) | ||
pubKey, err := crypto.Ecrecover(hash, signatureBytes) | ||
s.Nil(err) | ||
isVsalid := crypto.VerifySignature(pubKey, hash, signatureBytes[:64]) | ||
s.True(isVsalid) | ||
signed, err := s.d.l2ChainSyncer.anchorConstructor.signTxPayload(hash) | ||
s.Nil(err) | ||
s.Equal(signatureBytes, signed) | ||
|
||
// Payload 2 | ||
hash = hexutil.MustDecode("0x663d210fa6dba171546498489de1ba024b89db49e21662f91bf83cdffe788820") | ||
signatureBytes = testutils.SignatureFromRSV( | ||
"0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", | ||
"0x568130fab1a3a9e63261d4278a7e130588beb51f27de7c20d0258d38a85a27ff", | ||
1, | ||
) | ||
pubKey, err = crypto.Ecrecover(hash, signatureBytes) | ||
s.Nil(err) | ||
isVsalid = crypto.VerifySignature(pubKey, hash, signatureBytes[:64]) | ||
s.True(isVsalid) | ||
signed, err = s.d.l2ChainSyncer.anchorConstructor.signTxPayload(hash) | ||
s.Nil(err) | ||
s.Equal(signatureBytes, signed) | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.