Skip to content

Commit

Permalink
op-service: add blockpayload_args to send to rpc opsigner_signBlockPa…
Browse files Browse the repository at this point in the history
…yload
  • Loading branch information
mininny committed Oct 18, 2024
1 parent ebeb2a4 commit 9860c29
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 32 deletions.
40 changes: 13 additions & 27 deletions op-node/p2p/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,40 +22,27 @@ type Signer interface {
io.Closer
}

func SigningHash(domain [32]byte, chainID *big.Int, payloadBytes []byte) (common.Hash, error) {
var msgInput [32 + 32 + 32]byte
// domain: first 32 bytes
copy(msgInput[:32], domain[:])
// chain_id: second 32 bytes
if chainID.BitLen() > 256 {
return common.Hash{}, errors.New("chain_id is too large")
}
chainID.FillBytes(msgInput[32:64])
// payload_hash: third 32 bytes, hash of encoded payload
copy(msgInput[64:], crypto.Keccak256(payloadBytes))

return crypto.Keccak256Hash(msgInput[:]), nil
}

func BlockSigningHash(cfg *rollup.Config, payloadBytes []byte) (common.Hash, error) {
return SigningHash(SigningDomainBlocksV1, cfg.L2ChainID, payloadBytes)
return opsigner.NewBlockPayloadArgs(SigningDomainBlocksV1, cfg.L2ChainID, payloadBytes, nil).ToSigningHash()
}

// LocalSigner is suitable for testing
type LocalSigner struct {
priv *ecdsa.PrivateKey
hasher func(domain [32]byte, chainID *big.Int, payloadBytes []byte) (common.Hash, error)
priv *ecdsa.PrivateKey
}

func NewLocalSigner(priv *ecdsa.PrivateKey) *LocalSigner {
return &LocalSigner{priv: priv, hasher: SigningHash}
return &LocalSigner{priv: priv}
}

func (s *LocalSigner) Sign(ctx context.Context, domain [32]byte, chainID *big.Int, encodedMsg []byte) (sig *[65]byte, err error) {
if s.priv == nil {
return nil, errors.New("signer is closed")
}
signingHash, err := s.hasher(domain, chainID, encodedMsg)

blockPayloadArgs := opsigner.NewBlockPayloadArgs(domain, chainID, encodedMsg, nil)
signingHash, err := blockPayloadArgs.ToSigningHash()

if err != nil {
return nil, err
}
Expand All @@ -73,27 +60,26 @@ func (s *LocalSigner) Close() error {

type RemoteSigner struct {
client *opsigner.SignerClient
hasher func(domain [32]byte, chainID *big.Int, payloadBytes []byte) (common.Hash, error)
sender *common.Address
}

func NewRemoteSigner(logger log.Logger, config opsigner.CLIConfig) (*RemoteSigner, error) {
signerClient, err := opsigner.NewSignerClientFromConfig(logger, config)
if err != nil {
return nil, err
}
return &RemoteSigner{signerClient, SigningHash}, nil
senderAddress := common.HexToAddress(config.Address)
return &RemoteSigner{signerClient, &senderAddress}, nil
}

func (s *RemoteSigner) Sign(ctx context.Context, domain [32]byte, chainID *big.Int, encodedMsg []byte) (sig *[65]byte, err error) {
if s.client == nil {
return nil, errors.New("signer is closed")
}
signingHash, err := s.hasher(domain, chainID, encodedMsg)
if err != nil {
return nil, err
}

signature, err := s.client.SignBlockPayload(ctx, signingHash)
blockPayloadArgs := opsigner.NewBlockPayloadArgs(domain, chainID, encodedMsg, s.sender)
signature, err := s.client.SignBlockPayload(ctx, blockPayloadArgs)

if err != nil {
return nil, err
}
Expand Down
61 changes: 61 additions & 0 deletions op-service/signer/blockpayload_args.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package signer

import (
"errors"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)

// BlockPayloadArgs represents the arguments to sign a new block payload from the sequencer.
type BlockPayloadArgs struct {
Domain [32]byte `json:"domain"`
ChainID *big.Int `json:"chainId"`
PayloadHash []byte `json:"payloadHash"`
PayloadBytes []byte
SenderAddress *common.Address `json:"senderAddress"`
}

// NewBlockPayloadArgs creates a BlockPayloadArgs struct
func NewBlockPayloadArgs(domain [32]byte, chainId *big.Int, payloadBytes []byte, senderAddress *common.Address) *BlockPayloadArgs {
payloadHash := crypto.Keccak256(payloadBytes)
args := &BlockPayloadArgs{
Domain: domain,
ChainID: chainId,
PayloadHash: payloadHash,
PayloadBytes: payloadBytes,
SenderAddress: senderAddress,
}
return args
}

func (args *BlockPayloadArgs) Check() error {
if args.ChainID == nil {
return errors.New("chainId not specified")
}
if len(args.PayloadHash) == 0 {
return errors.New("payloadHash not specified")
}
return nil
}

// ToSigningHash hashes
func (args *BlockPayloadArgs) ToSigningHash() (common.Hash, error) {
if err := args.Check(); err != nil {
return common.Hash{}, err
}
var msgInput [32 + 32 + 32]byte
// domain: first 32 bytes
copy(msgInput[:32], args.Domain[:])
// chain_id: second 32 bytes
if args.ChainID.BitLen() > 256 {
return common.Hash{}, errors.New("chain_id is too large")
}
args.ChainID.FillBytes(msgInput[32:64])

// payload_hash: third 32 bytes, hash of encoded payload
copy(msgInput[64:], args.PayloadHash[:])

return crypto.Keccak256Hash(msgInput[:]), nil
}
4 changes: 2 additions & 2 deletions op-service/signer/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ func (c CLIConfig) Check() error {
if err := c.TLSConfig.Check(); err != nil {
return err
}
if !((c.Endpoint == "" && c.Address == "") || (c.Endpoint != "")) {
if !((c.Endpoint == "" && c.Address == "") || (c.Endpoint != "" && c.Address != "")) {
return errors.New("signer endpoint and address must both be set or not set")
}
return nil
}

func (c CLIConfig) Enabled() bool {
return c.Endpoint != ""
return c.Endpoint != "" && c.Address != ""
}

func ReadCLIConfig(ctx *cli.Context) CLIConfig {
Expand Down
7 changes: 4 additions & 3 deletions op-service/signer/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,11 @@ func (s *SignerClient) SignTransaction(ctx context.Context, chainId *big.Int, fr
return &signed, nil
}

func (s *SignerClient) SignBlockPayload(ctx context.Context, signingHash common.Hash) ([65]byte, error) {
func (s *SignerClient) SignBlockPayload(ctx context.Context, args *BlockPayloadArgs) ([65]byte, error) {
var result hexutil.Bytes
if err := s.client.CallContext(ctx, &result, "eth_signBlockPayload", signingHash); err != nil {
return [65]byte{}, fmt.Errorf("eth_signTransaction failed: %w", err)

if err := s.client.CallContext(ctx, &result, "opsigner_signBlockPayload", args); err != nil {
return [65]byte{}, fmt.Errorf("opsigner_signBlockPayload failed: %w", err)
}

if len(result) < 65 {
Expand Down

0 comments on commit 9860c29

Please sign in to comment.