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

Commit

Permalink
feat(eip4844): Eip4844 blob tx (#527)
Browse files Browse the repository at this point in the history
  • Loading branch information
mask-pp authored Jan 23, 2024
2 parents 7aacb28 + 4614b95 commit b6ea3ad
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 4 deletions.
140 changes: 140 additions & 0 deletions pkg/rpc/txblob.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package rpc

import (
"errors"
"fmt"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/holiman/uint256"
"math/big"
)

func (c *EthClient) TransactBlobTx(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
// Sign the transaction and schedule it for execution
if opts.Signer == nil {
return nil, errors.New("no signer to authorize the transaction with")
}
// Create blob tx.
rawTx, err := c.createBlobTx(opts, data)
if err != nil {
return nil, err
}
signedTx, err := opts.Signer(opts.From, rawTx)
if err != nil {
return nil, err
}
if opts.NoSend {
return signedTx, nil
}
if err := c.SendTransaction(opts.Context, signedTx); err != nil {
return nil, err
}
return signedTx, nil
}

func (c *EthClient) createBlobTx(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) {
header, err := c.HeaderByNumber(opts.Context, nil)
if err != nil {
return nil, err
}
// Estimate TipCap
gasTipCap := opts.GasTipCap
if gasTipCap == nil {
tip, err := c.SuggestGasTipCap(opts.Context)
if err != nil {
return nil, err
}
gasTipCap = tip
}
// Estimate FeeCap
gasFeeCap := opts.GasFeeCap
if gasFeeCap == nil {
gasFeeCap = new(big.Int).Add(
gasTipCap,
new(big.Int).Mul(header.BaseFee, big.NewInt(2)),
)
}
if gasFeeCap.Cmp(gasTipCap) < 0 {
return nil, fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", gasFeeCap, gasTipCap)
}
// Estimate GasLimit
gasLimit := opts.GasLimit
if opts.GasLimit == 0 {
var err error
gasLimit, err = c.EstimateGas(nil, ethereum.CallMsg{

Check failure on line 67 in pkg/rpc/txblob.go

View workflow job for this annotation

GitHub Actions / Lint

SA1012: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (staticcheck)
From: opts.From,
To: nil,
GasPrice: nil,
GasTipCap: gasTipCap,
GasFeeCap: gasFeeCap,
Value: nil,
Data: nil,
})
if err != nil {
return nil, err
}
}
// create the transaction
nonce, err := c.getNonce(opts)
if err != nil {
return nil, err
}
chainID, err := c.ChainID(opts.Context)
if err != nil {
return nil, err
}

sidecar, err := makeSidecarWithSingleBlob(data)
if err != nil {
return nil, err
}

var blobFeeCap uint64 = 100066
if header.ExcessBlobGas != nil {
blobFeeCap = *header.ExcessBlobGas
}

baseTx := &types.BlobTx{
ChainID: uint256.NewInt(chainID.Uint64()),
Nonce: nonce,
GasTipCap: uint256.NewInt(gasTipCap.Uint64()),
GasFeeCap: uint256.NewInt(gasFeeCap.Uint64()),
Gas: gasLimit,
BlobFeeCap: uint256.MustFromBig(eip4844.CalcBlobFee(blobFeeCap)),
BlobHashes: sidecar.BlobHashes(),
Sidecar: sidecar,
}
return types.NewTx(baseTx), nil
}

func (c *EthClient) getNonce(opts *bind.TransactOpts) (uint64, error) {
if opts.Nonce == nil {
return c.PendingNonceAt(opts.Context, opts.From)
} else {

Check failure on line 116 in pkg/rpc/txblob.go

View workflow job for this annotation

GitHub Actions / Lint

indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (revive)
return opts.Nonce.Uint64(), nil
}
}

func makeSidecarWithSingleBlob(data []byte) (*types.BlobTxSidecar, error) {
if len(data) > BlobBytes {
return nil, fmt.Errorf("data is bigger than 128k")
}
blob := kzg4844.Blob{}
copy(blob[:], data)
commitment, err := kzg4844.BlobToCommitment(blob)
if err != nil {
return nil, err
}
proof, err := kzg4844.ComputeBlobProof(blob, commitment)
if err != nil {
return nil, err
}
return &types.BlobTxSidecar{
Blobs: []kzg4844.Blob{blob},
Commitments: []kzg4844.Commitment{commitment},
Proofs: []kzg4844.Proof{proof},
}, nil
}
45 changes: 45 additions & 0 deletions pkg/rpc/txblob_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package rpc

import (
"context"
"os"
"testing"
"time"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/assert"
)

func TestBlockTx(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

url := "https://rpc.ankr.com/eth_goerli" //os.Getenv("L1_NODE_WS_ENDPOINT")
l1Client, err := NewEthClient(ctx, url, time.Second*20)
assert.NoError(t, err)

priv := os.Getenv("L1_PROPOSER_PRIVATE_KEY")
sk, err := crypto.ToECDSA(common.FromHex(priv))
assert.NoError(t, err)

chainID, err := l1Client.ChainID(ctx)
assert.NoError(t, err)

opts, err := bind.NewKeyedTransactorWithChainID(sk, chainID)
assert.NoError(t, err)
opts.Context = ctx
//opts.NoSend = true

balance, err := l1Client.BalanceAt(ctx, opts.From, nil)
assert.NoError(t, err)
t.Logf("address: %s, balance: %s", opts.From.String(), balance.String())

tx, err := l1Client.TransactBlobTx(opts, []byte("s"))
assert.NoError(t, err)

receipt, err := bind.WaitMined(ctx, l1Client, tx)
assert.NoError(t, err)
t.Log(receipt)
}
3 changes: 3 additions & 0 deletions pkg/rpc/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"

"github.com/taikoxyz/taiko-client/bindings"
"github.com/taikoxyz/taiko-client/bindings/encoding"
"github.com/taikoxyz/taiko-client/internal/utils"
Expand All @@ -23,6 +25,7 @@ var (
ZeroAddress common.Address
waitReceiptPollingInterval = 3 * time.Second
defaultWaitReceiptTimeout = 1 * time.Minute
BlobBytes = params.BlobTxBytesPerFieldElement * params.BlobTxFieldElementsPerBlob
)

// GetProtocolStateVariables gets the protocol states from TaikoL1 contract.
Expand Down
36 changes: 32 additions & 4 deletions proposer/proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,27 @@ func (p *Proposer) ProposeOp(ctx context.Context) error {
return nil
}

func (p *Proposer) sendTxListByBlobTx(ctx context.Context, txListBytes []byte) (*types.Transaction, error) {
blobOpts, err := getTxOpts(ctx, p.rpc.L1, p.L1ProposerPrivKey, p.rpc.L1ChainID, nil)
if err != nil {
return nil, err
}
tx, err := p.rpc.L1.TransactBlobTx(blobOpts, txListBytes)
if err != nil {
return nil, err
}
// Wait until blob tx is mined.
if _, err := bind.WaitMined(ctx, p.rpc.L1, tx); err != nil {
return nil, err
}

return tx, nil
}

// sendProposeBlockTx tries to send a TaikoL1.proposeBlock transaction.
func (p *Proposer) sendProposeBlockTx(
ctx context.Context,
txListBytes []byte,
blobHash common.Hash,
nonce *uint64,
assignment *encoding.ProverAssignment,
assignedProver common.Address,
Expand Down Expand Up @@ -376,7 +393,7 @@ func (p *Proposer) sendProposeBlockTx(
ExtraData: rpc.StringToBytes32(p.ExtraData),
TxListByteOffset: common.Big0,
TxListByteSize: common.Big0,
BlobHash: [32]byte{},
BlobHash: blobHash,
CacheBlobForReuse: false,
ParentMetaHash: parentMetaHash,
HookCalls: hookCalls,
Expand All @@ -388,8 +405,9 @@ func (p *Proposer) sendProposeBlockTx(
proposeTx, err := p.rpc.TaikoL1.ProposeBlock(
opts,
encodedParams,
txListBytes,
nil,
)

if err != nil {
return nil, encoding.TryParsingCustomError(err)
}
Expand All @@ -415,16 +433,26 @@ func (p *Proposer) ProposeTxList(

var (
isReplacement bool
blobTx *types.Transaction
tx *types.Transaction
)
if err := backoff.Retry(
func() error {
if ctx.Err() != nil {
return nil
}

// Send tx list by blob tx.
if blobTx == nil {
blobTx, err = p.sendTxListByBlobTx(ctx, txListBytes)
if err != nil {
return nil
}
}

if tx, err = p.sendProposeBlockTx(
ctx,
txListBytes,
blobTx.BlobHashes()[0],
nonce,
assignment,
proverAddress,
Expand Down

0 comments on commit b6ea3ad

Please sign in to comment.