mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 13:16:42 +00:00
eth/catalyst: add tests for getblobsv4, fcuv4
This commit is contained in:
parent
294ac215af
commit
10a2b9272e
1 changed files with 147 additions and 19 deletions
|
|
@ -38,6 +38,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/beacon"
|
"github.com/ethereum/go-ethereum/consensus/beacon"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||||
|
|
@ -1847,23 +1848,27 @@ func init() {
|
||||||
|
|
||||||
// makeMultiBlobTx is a utility method to construct a random blob tx with
|
// makeMultiBlobTx is a utility method to construct a random blob tx with
|
||||||
// certain number of blobs in its sidecar.
|
// certain number of blobs in its sidecar.
|
||||||
func makeMultiBlobTx(chainConfig *params.ChainConfig, nonce uint64, blobCount int, blobOffset int, key *ecdsa.PrivateKey, version byte) *types.Transaction {
|
func makeMultiBlobTx(chainConfig *params.ChainConfig, nonce uint64, blobCount int, blobOffset int, key *ecdsa.PrivateKey, version byte, custody types.CustodyBitmap) *blobpool.BlobTxForPool {
|
||||||
|
indices := custody.Indices()
|
||||||
var (
|
var (
|
||||||
blobs []kzg4844.Blob
|
|
||||||
blobHashes []common.Hash
|
blobHashes []common.Hash
|
||||||
commitments []kzg4844.Commitment
|
commitments []kzg4844.Commitment
|
||||||
proofs []kzg4844.Proof
|
proofs []kzg4844.Proof
|
||||||
|
cells []kzg4844.Cell
|
||||||
)
|
)
|
||||||
for i := 0; i < blobCount; i++ {
|
for i := 0; i < blobCount; i++ {
|
||||||
blobs = append(blobs, *testBlobs[blobOffset+i])
|
j := blobOffset + i
|
||||||
commitments = append(commitments, testBlobCommits[blobOffset+i])
|
blobHashes = append(blobHashes, testBlobVHashes[j])
|
||||||
|
commitments = append(commitments, testBlobCommits[j])
|
||||||
if version == types.BlobSidecarVersion0 {
|
if version == types.BlobSidecarVersion0 {
|
||||||
proofs = append(proofs, testBlobProofs[blobOffset+i])
|
proofs = append(proofs, testBlobProofs[j])
|
||||||
} else {
|
} else {
|
||||||
cellProofs, _ := kzg4844.ComputeCellProofs(testBlobs[blobOffset+i])
|
proofs = append(proofs, testBlobCellProofs[j]...)
|
||||||
proofs = append(proofs, cellProofs...)
|
}
|
||||||
|
full, _ := kzg4844.ComputeCells([]kzg4844.Blob{*testBlobs[j]})
|
||||||
|
for _, idx := range indices {
|
||||||
|
cells = append(cells, full[idx])
|
||||||
}
|
}
|
||||||
blobHashes = append(blobHashes, testBlobVHashes[blobOffset+i])
|
|
||||||
}
|
}
|
||||||
blobtx := &types.BlobTx{
|
blobtx := &types.BlobTx{
|
||||||
ChainID: uint256.MustFromBig(chainConfig.ChainID),
|
ChainID: uint256.MustFromBig(chainConfig.ChainID),
|
||||||
|
|
@ -1874,12 +1879,20 @@ func makeMultiBlobTx(chainConfig *params.ChainConfig, nonce uint64, blobCount in
|
||||||
BlobFeeCap: uint256.NewInt(1000),
|
BlobFeeCap: uint256.NewInt(1000),
|
||||||
BlobHashes: blobHashes,
|
BlobHashes: blobHashes,
|
||||||
Value: uint256.NewInt(100),
|
Value: uint256.NewInt(100),
|
||||||
Sidecar: types.NewBlobTxSidecar(version, blobs, commitments, proofs),
|
|
||||||
}
|
}
|
||||||
return types.MustSignNewTx(key, types.LatestSigner(chainConfig), blobtx)
|
return &blobpool.BlobTxForPool{
|
||||||
|
Tx: types.MustSignNewTx(key, types.LatestSigner(chainConfig), blobtx),
|
||||||
|
CellSidecar: &types.BlobTxCellSidecar{
|
||||||
|
Version: version,
|
||||||
|
Cells: cells,
|
||||||
|
Commitments: commitments,
|
||||||
|
Proofs: proofs,
|
||||||
|
Custody: custody,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGetBlobEnv(t testing.TB, version byte) (*node.Node, *ConsensusAPI) {
|
func newGetBlobEnv(t testing.TB, version byte, custody types.CustodyBitmap) (*node.Node, *ConsensusAPI) {
|
||||||
var (
|
var (
|
||||||
// Create a database pre-initialize with a genesis block
|
// Create a database pre-initialize with a genesis block
|
||||||
config = *params.MergedTestChainConfig
|
config = *params.MergedTestChainConfig
|
||||||
|
|
@ -1908,18 +1921,24 @@ func newGetBlobEnv(t testing.TB, version byte) (*node.Node, *ConsensusAPI) {
|
||||||
}
|
}
|
||||||
n, ethServ := startEthService(t, gspec, nil)
|
n, ethServ := startEthService(t, gspec, nil)
|
||||||
|
|
||||||
// fill blob txs into the pool
|
// fill blob txs into the pool, each holding only the given custody cells
|
||||||
tx1 := makeMultiBlobTx(&config, 0, 2, 0, key1, version) // blob[0, 2)
|
txs := []*blobpool.BlobTxForPool{
|
||||||
tx2 := makeMultiBlobTx(&config, 0, 2, 2, key2, version) // blob[2, 4)
|
makeMultiBlobTx(&config, 0, 2, 0, key1, version, custody), // blob[0, 2)
|
||||||
tx3 := makeMultiBlobTx(&config, 0, 2, 4, key3, version) // blob[4, 6)
|
makeMultiBlobTx(&config, 0, 2, 2, key2, version, custody), // blob[2, 4)
|
||||||
ethServ.TxPool().Add([]*types.Transaction{tx1, tx2, tx3}, true)
|
makeMultiBlobTx(&config, 0, 2, 4, key3, version, custody), // blob[4, 6)
|
||||||
|
}
|
||||||
|
for _, ptx := range txs {
|
||||||
|
if err := ethServ.BlobTxPool().AddPooledTx(ptx); err != nil {
|
||||||
|
t.Fatalf("failed to add blob tx: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
api := newConsensusAPIWithoutHeartbeat(ethServ)
|
api := newConsensusAPIWithoutHeartbeat(ethServ)
|
||||||
return n, api
|
return n, api
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetBlobsV1(t *testing.T) {
|
func TestGetBlobsV1(t *testing.T) {
|
||||||
n, api := newGetBlobEnv(t, 0)
|
n, api := newGetBlobEnv(t, 0, types.CustodyBitmapAll)
|
||||||
defer n.Close()
|
defer n.Close()
|
||||||
|
|
||||||
suites := []struct {
|
suites := []struct {
|
||||||
|
|
@ -2023,7 +2042,7 @@ func TestGetBlobsV1AfterOsakaFork(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetBlobsV2And3(t *testing.T) {
|
func TestGetBlobsV2And3(t *testing.T) {
|
||||||
n, api := newGetBlobEnv(t, 1)
|
n, api := newGetBlobEnv(t, 1, types.CustodyBitmapAll)
|
||||||
defer n.Close()
|
defer n.Close()
|
||||||
|
|
||||||
suites := []struct {
|
suites := []struct {
|
||||||
|
|
@ -2059,7 +2078,7 @@ func TestGetBlobsV2And3(t *testing.T) {
|
||||||
// Benchmark GetBlobsV2 internals
|
// Benchmark GetBlobsV2 internals
|
||||||
// Note that this is not an RPC-level benchmark, so JSON-RPC overhead is not included.
|
// Note that this is not an RPC-level benchmark, so JSON-RPC overhead is not included.
|
||||||
func BenchmarkGetBlobsV2(b *testing.B) {
|
func BenchmarkGetBlobsV2(b *testing.B) {
|
||||||
n, api := newGetBlobEnv(b, 1)
|
n, api := newGetBlobEnv(b, 1, types.CustodyBitmapAll)
|
||||||
defer n.Close()
|
defer n.Close()
|
||||||
|
|
||||||
// for blobs in [1, 2, 4, 6], print string and run benchmark
|
// for blobs in [1, 2, 4, 6], print string and run benchmark
|
||||||
|
|
@ -2119,3 +2138,112 @@ func runGetBlobs(t testing.TB, getBlobs getBlobsFn, start, limit int, fillRandom
|
||||||
t.Fatalf("Unexpected result for case %s", name)
|
t.Fatalf("Unexpected result for case %s", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetBlobsV4(t *testing.T) {
|
||||||
|
// The pool holds only this set of custody cells.
|
||||||
|
custody := types.NewCustodyBitmap([]uint64{0, 1, 2, 3, 4})
|
||||||
|
n, api := newGetBlobEnv(t, 1, custody)
|
||||||
|
defer n.Close()
|
||||||
|
|
||||||
|
masks := []struct {
|
||||||
|
name string
|
||||||
|
mask types.CustodyBitmap
|
||||||
|
}{
|
||||||
|
{"missing", types.NewCustodyBitmap([]uint64{5})},
|
||||||
|
{"overlap", types.NewCustodyBitmap([]uint64{0, 2, 5, 127})},
|
||||||
|
{"aligned", custody},
|
||||||
|
}
|
||||||
|
suites := []struct {
|
||||||
|
start int
|
||||||
|
limit int
|
||||||
|
missingBlob bool
|
||||||
|
}{
|
||||||
|
{start: 0, limit: 1},
|
||||||
|
{start: 0, limit: 2},
|
||||||
|
{start: 1, limit: 3},
|
||||||
|
{start: 0, limit: 6},
|
||||||
|
{start: 1, limit: 5},
|
||||||
|
{start: 0, limit: 6, missingBlob: true},
|
||||||
|
}
|
||||||
|
for _, m := range masks {
|
||||||
|
for i, suite := range suites {
|
||||||
|
runGetBlobsV4(t, api, custody, m.mask, suite.start, suite.limit, suite.missingBlob, fmt.Sprintf("GetBlobsV4 mask=%s suite=%d", m.name, i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runGetBlobsV4(t testing.TB, api *ConsensusAPI, custody, mask types.CustodyBitmap, start, limit int, missingBlob bool, name string) {
|
||||||
|
// Fill the request for retrieving cells and build the expected response.
|
||||||
|
var (
|
||||||
|
vhashes []common.Hash
|
||||||
|
expect []*engine.BlobCellsAndProofsV1
|
||||||
|
indices = mask.Indices()
|
||||||
|
)
|
||||||
|
for j := start; j < limit; j++ {
|
||||||
|
vhashes = append(vhashes, testBlobVHashes[j])
|
||||||
|
|
||||||
|
cells, err := kzg4844.ComputeCells([]kzg4844.Blob{*testBlobs[j]})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to compute cells for case %s: %v", name, err)
|
||||||
|
}
|
||||||
|
blobCells := make([]*hexutil.Bytes, len(indices))
|
||||||
|
blobProofs := make([]*hexutil.Bytes, len(indices))
|
||||||
|
for i, idx := range indices {
|
||||||
|
if !custody.IsSet(idx) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cell := hexutil.Bytes(cells[idx][:])
|
||||||
|
blobCells[i] = &cell
|
||||||
|
proof := hexutil.Bytes(testBlobCellProofs[j][idx][:])
|
||||||
|
blobProofs[i] = &proof
|
||||||
|
}
|
||||||
|
expect = append(expect, &engine.BlobCellsAndProofsV1{
|
||||||
|
BlobCells: blobCells,
|
||||||
|
Proofs: blobProofs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// put random missing blob
|
||||||
|
if missingBlob {
|
||||||
|
vhashes = append(vhashes, testrand.Hash())
|
||||||
|
expect = append(expect, nil)
|
||||||
|
}
|
||||||
|
result, err := api.GetBlobsV4(vhashes, mask)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error for case %s, %v", name, err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(result, expect) {
|
||||||
|
t.Fatalf("Unexpected result for case %s", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestForkchoiceUpdatedV4 tests the custody bitmap argument added in V4.
|
||||||
|
func TestForkchoiceUpdatedV4(t *testing.T) {
|
||||||
|
n, api := newGetBlobEnv(t, 1, types.CustodyBitmapAll)
|
||||||
|
defer n.Close()
|
||||||
|
|
||||||
|
head := api.eth.BlockChain().CurrentHeader().Hash()
|
||||||
|
fcState := engine.ForkchoiceStateV1{
|
||||||
|
HeadBlockHash: head,
|
||||||
|
SafeBlockHash: head,
|
||||||
|
FinalizedBlockHash: head,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non nil custody bitmap case.
|
||||||
|
custody := types.NewCustodyBitmap([]uint64{0, 1, 2, 127})
|
||||||
|
resp, err := api.ForkchoiceUpdatedV4(context.Background(), fcState, nil, &custody)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error with custody bitmap: %v", err)
|
||||||
|
}
|
||||||
|
if resp.PayloadStatus.Status != engine.VALID {
|
||||||
|
t.Fatalf("Unexpected status with custody bitmap: got %s, want %s", resp.PayloadStatus.Status, engine.VALID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nil custody bitmap case.
|
||||||
|
resp, err = api.ForkchoiceUpdatedV4(context.Background(), fcState, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error with nil custody bitmap: %v", err)
|
||||||
|
}
|
||||||
|
if resp.PayloadStatus.Status != engine.VALID {
|
||||||
|
t.Fatalf("Unexpected status with nil custody bitmap: got %s, want %s", resp.PayloadStatus.Status, engine.VALID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue