mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 05:36:46 +00:00
simplify the encode and decode logic about sidecar
This commit is contained in:
parent
a9a19c4202
commit
22e0abd3a5
3 changed files with 47 additions and 148 deletions
|
|
@ -947,7 +947,7 @@ func (pool *LegacyPool) Add(txs []*types.Transaction, sync bool) []error {
|
||||||
// Filter out known ones without obtaining the pool lock or recovering signatures
|
// Filter out known ones without obtaining the pool lock or recovering signatures
|
||||||
var (
|
var (
|
||||||
errs = make([]error, len(txs))
|
errs = make([]error, len(txs))
|
||||||
news = make([]*types.Transaction, 0, len(txs))
|
verifiedTxs int
|
||||||
)
|
)
|
||||||
for i, tx := range txs {
|
for i, tx := range txs {
|
||||||
// If the transaction is known, pre-set the error slot
|
// If the transaction is known, pre-set the error slot
|
||||||
|
|
@ -965,26 +965,18 @@ func (pool *LegacyPool) Add(txs []*types.Transaction, sync bool) []error {
|
||||||
invalidTxMeter.Mark(1)
|
invalidTxMeter.Mark(1)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Accumulate all unknown transactions for deeper processing
|
verifiedTxs++
|
||||||
news = append(news, tx)
|
|
||||||
}
|
}
|
||||||
if len(news) == 0 {
|
if verifiedTxs == 0 {
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process all the new transaction and merge any errors into the original slice
|
// Process all the new transaction and merge any errors into the original slice
|
||||||
|
var dirtyAddrs *accountSet
|
||||||
pool.mu.Lock()
|
pool.mu.Lock()
|
||||||
newErrs, dirtyAddrs := pool.addTxsLocked(news)
|
errs, dirtyAddrs = pool.addTxsLocked(txs, errs)
|
||||||
pool.mu.Unlock()
|
pool.mu.Unlock()
|
||||||
|
|
||||||
var nilSlot = 0
|
|
||||||
for _, err := range newErrs {
|
|
||||||
for errs[nilSlot] != nil {
|
|
||||||
nilSlot++
|
|
||||||
}
|
|
||||||
errs[nilSlot] = err
|
|
||||||
nilSlot++
|
|
||||||
}
|
|
||||||
// Reorg the pool internals if needed and return
|
// Reorg the pool internals if needed and return
|
||||||
done := pool.requestPromoteExecutables(dirtyAddrs)
|
done := pool.requestPromoteExecutables(dirtyAddrs)
|
||||||
if sync {
|
if sync {
|
||||||
|
|
@ -995,10 +987,15 @@ func (pool *LegacyPool) Add(txs []*types.Transaction, sync bool) []error {
|
||||||
|
|
||||||
// addTxsLocked attempts to queue a batch of transactions if they are valid.
|
// addTxsLocked attempts to queue a batch of transactions if they are valid.
|
||||||
// The transaction pool lock must be held.
|
// The transaction pool lock must be held.
|
||||||
func (pool *LegacyPool) addTxsLocked(txs []*types.Transaction) ([]error, *accountSet) {
|
func (pool *LegacyPool) addTxsLocked(txs []*types.Transaction, errs []error) ([]error, *accountSet) {
|
||||||
dirty := newAccountSet(pool.signer)
|
dirty := newAccountSet(pool.signer)
|
||||||
errs := make([]error, len(txs))
|
if errs == nil {
|
||||||
|
errs = make([]error, len(txs))
|
||||||
|
}
|
||||||
for i, tx := range txs {
|
for i, tx := range txs {
|
||||||
|
if errs[i] != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
replaced, err := pool.add(tx)
|
replaced, err := pool.add(tx)
|
||||||
errs[i] = err
|
errs[i] = err
|
||||||
if err == nil && !replaced {
|
if err == nil && !replaced {
|
||||||
|
|
@ -1439,7 +1436,7 @@ func (pool *LegacyPool) reset(oldHead, newHead *types.Header) {
|
||||||
// Inject any transactions discarded due to reorgs
|
// Inject any transactions discarded due to reorgs
|
||||||
log.Debug("Reinjecting stale transactions", "count", len(reinject))
|
log.Debug("Reinjecting stale transactions", "count", len(reinject))
|
||||||
core.SenderCacher().Recover(pool.signer, reinject)
|
core.SenderCacher().Recover(pool.signer, reinject)
|
||||||
pool.addTxsLocked(reinject)
|
pool.addTxsLocked(reinject, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// promoteExecutables moves transactions that have become processable from the
|
// promoteExecutables moves transactions that have become processable from the
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ package types
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"slices"
|
"slices"
|
||||||
|
|
@ -113,10 +112,7 @@ func (sc *BlobTxSidecar) CellProofsAt(idx int) ([]kzg4844.Proof, error) {
|
||||||
|
|
||||||
// ToV1 converts the BlobSidecar to version 1, attaching the cell proofs.
|
// ToV1 converts the BlobSidecar to version 1, attaching the cell proofs.
|
||||||
func (sc *BlobTxSidecar) ToV1() error {
|
func (sc *BlobTxSidecar) ToV1() error {
|
||||||
if sc.Version == BlobSidecarVersion1 {
|
if sc.Version != BlobSidecarVersion1 {
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if sc.Version == BlobSidecarVersion0 {
|
|
||||||
proofs := make([]kzg4844.Proof, 0, len(sc.Blobs)*kzg4844.CellProofsPerBlob)
|
proofs := make([]kzg4844.Proof, 0, len(sc.Blobs)*kzg4844.CellProofsPerBlob)
|
||||||
for _, blob := range sc.Blobs {
|
for _, blob := range sc.Blobs {
|
||||||
cellProofs, err := kzg4844.ComputeCellProofs(&blob)
|
cellProofs, err := kzg4844.ComputeCellProofs(&blob)
|
||||||
|
|
@ -183,48 +179,6 @@ type blobTxWithBlobs interface {
|
||||||
assign(*BlobTxSidecar) error
|
assign(*BlobTxSidecar) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type blobTxWithBlobsV0 struct {
|
|
||||||
BlobTx *BlobTx
|
|
||||||
Blobs []kzg4844.Blob
|
|
||||||
Commitments []kzg4844.Commitment
|
|
||||||
Proofs []kzg4844.Proof
|
|
||||||
}
|
|
||||||
|
|
||||||
type blobTxWithBlobsV1 struct {
|
|
||||||
BlobTx *BlobTx
|
|
||||||
Version byte
|
|
||||||
Blobs []kzg4844.Blob
|
|
||||||
Commitments []kzg4844.Commitment
|
|
||||||
Proofs []kzg4844.Proof
|
|
||||||
}
|
|
||||||
|
|
||||||
func (btx *blobTxWithBlobsV0) tx() *BlobTx {
|
|
||||||
return btx.BlobTx
|
|
||||||
}
|
|
||||||
|
|
||||||
func (btx *blobTxWithBlobsV0) assign(sc *BlobTxSidecar) error {
|
|
||||||
sc.Version = BlobSidecarVersion0
|
|
||||||
sc.Blobs = btx.Blobs
|
|
||||||
sc.Commitments = btx.Commitments
|
|
||||||
sc.Proofs = btx.Proofs
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (btx *blobTxWithBlobsV1) tx() *BlobTx {
|
|
||||||
return btx.BlobTx
|
|
||||||
}
|
|
||||||
|
|
||||||
func (btx *blobTxWithBlobsV1) assign(sc *BlobTxSidecar) error {
|
|
||||||
if btx.Version != BlobSidecarVersion1 {
|
|
||||||
return fmt.Errorf("unsupported blob tx version %d", btx.Version)
|
|
||||||
}
|
|
||||||
sc.Version = BlobSidecarVersion1
|
|
||||||
sc.Blobs = btx.Blobs
|
|
||||||
sc.Commitments = btx.Commitments
|
|
||||||
sc.Proofs = btx.Proofs
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy creates a deep copy of the transaction data and initializes all fields.
|
// copy creates a deep copy of the transaction data and initializes all fields.
|
||||||
func (tx *BlobTx) copy() TxData {
|
func (tx *BlobTx) copy() TxData {
|
||||||
cpy := &BlobTx{
|
cpy := &BlobTx{
|
||||||
|
|
@ -326,98 +280,29 @@ func (tx *BlobTx) withSidecar(sideCar *BlobTxSidecar) *BlobTx {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *BlobTx) encode(b *bytes.Buffer) error {
|
func (tx *BlobTx) encode(b *bytes.Buffer) error {
|
||||||
switch {
|
if err := rlp.Encode(b, tx); err != nil {
|
||||||
case tx.Sidecar == nil:
|
return err
|
||||||
return rlp.Encode(b, tx)
|
|
||||||
|
|
||||||
case tx.Sidecar.Version == BlobSidecarVersion0:
|
|
||||||
return rlp.Encode(b, &blobTxWithBlobsV0{
|
|
||||||
BlobTx: tx,
|
|
||||||
Blobs: tx.Sidecar.Blobs,
|
|
||||||
Commitments: tx.Sidecar.Commitments,
|
|
||||||
Proofs: tx.Sidecar.Proofs,
|
|
||||||
})
|
|
||||||
|
|
||||||
case tx.Sidecar.Version == BlobSidecarVersion1:
|
|
||||||
return rlp.Encode(b, &blobTxWithBlobsV1{
|
|
||||||
BlobTx: tx,
|
|
||||||
Version: tx.Sidecar.Version,
|
|
||||||
Blobs: tx.Sidecar.Blobs,
|
|
||||||
Commitments: tx.Sidecar.Commitments,
|
|
||||||
Proofs: tx.Sidecar.Proofs,
|
|
||||||
})
|
|
||||||
|
|
||||||
default:
|
|
||||||
return errors.New("unsupported sidecar version")
|
|
||||||
}
|
}
|
||||||
|
if tx.Sidecar != nil {
|
||||||
|
return rlp.Encode(b, tx.Sidecar)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *BlobTx) decode(input []byte) error {
|
func (tx *BlobTx) decode(input []byte) error {
|
||||||
// Here we need to support two outer formats: the network protocol encoding of the tx
|
bLen, err := rlp.DecodeBytesV1(input, tx)
|
||||||
// (with blobs) or the canonical encoding without blobs.
|
|
||||||
//
|
|
||||||
// The canonical encoding is just a list of fields:
|
|
||||||
//
|
|
||||||
// [chainID, nonce, ...]
|
|
||||||
//
|
|
||||||
// The network encoding is a list where the first element is the tx in the canonical encoding,
|
|
||||||
// and the remaining elements are the 'sidecar':
|
|
||||||
//
|
|
||||||
// [[chainID, nonce, ...], ...]
|
|
||||||
//
|
|
||||||
// The two outer encodings can be distinguished by checking whether the first element
|
|
||||||
// of the input list is itself a list. If it's the canonical encoding, the first
|
|
||||||
// element is the chainID, which is a number.
|
|
||||||
|
|
||||||
firstElem, _, err := rlp.SplitList(input)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
firstElemKind, _, secondElem, err := rlp.Split(firstElem)
|
// If the input is shorter than the RLP-encoded transaction, it means
|
||||||
if err != nil {
|
// that the transaction does not have a sidecar.
|
||||||
|
if len(input) > bLen {
|
||||||
|
var sidecar *BlobTxSidecar
|
||||||
|
if err = rlp.DecodeBytes(input[bLen:], &sidecar); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if firstElemKind != rlp.List {
|
tx.Sidecar = sidecar
|
||||||
// Blob tx without blobs.
|
|
||||||
return rlp.DecodeBytes(input, tx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we know it's the network encoding with the blob sidecar. Here we again need to
|
|
||||||
// support multiple encodings: legacy sidecars (v0) with a blob proof, and versioned
|
|
||||||
// sidecars.
|
|
||||||
//
|
|
||||||
// The legacy encoding is:
|
|
||||||
//
|
|
||||||
// [tx, blobs, commitments, proofs]
|
|
||||||
//
|
|
||||||
// The versioned encoding is:
|
|
||||||
//
|
|
||||||
// [tx, version, blobs, ...]
|
|
||||||
//
|
|
||||||
// We can tell the two apart by checking whether the second element is the version byte.
|
|
||||||
// For legacy sidecar the second element is a list of blobs.
|
|
||||||
|
|
||||||
secondElemKind, _, _, err := rlp.Split(secondElem)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var payload blobTxWithBlobs
|
|
||||||
if secondElemKind == rlp.List {
|
|
||||||
// No version byte: blob sidecar v0.
|
|
||||||
payload = new(blobTxWithBlobsV0)
|
|
||||||
} else {
|
|
||||||
// It has a version byte. Decode as v1, version is checked by assign()
|
|
||||||
payload = new(blobTxWithBlobsV1)
|
|
||||||
}
|
|
||||||
if err := rlp.DecodeBytes(input, payload); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sc := new(BlobTxSidecar)
|
|
||||||
if err := payload.assign(sc); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*tx = *payload.tx()
|
|
||||||
tx.Sidecar = sc
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,23 @@ func DecodeBytes(b []byte, val interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeBytesV1 parses RLP data from b into val. Please see package-level documentation for
|
||||||
|
// the decoding rules. The input must contain exactly one value and no trailing data.
|
||||||
|
// DecodeBytesV1 is similar to DecodeBytes, but it returns the number of bytes read from b.
|
||||||
|
func DecodeBytesV1(b []byte, val interface{}) (int, error) {
|
||||||
|
r := (*sliceReader)(&b)
|
||||||
|
|
||||||
|
stream := streamPool.Get().(*Stream)
|
||||||
|
defer streamPool.Put(stream)
|
||||||
|
|
||||||
|
bLen := len(b)
|
||||||
|
stream.Reset(r, uint64(bLen))
|
||||||
|
if err := stream.Decode(val); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return bLen - len(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
type decodeError struct {
|
type decodeError struct {
|
||||||
msg string
|
msg string
|
||||||
typ reflect.Type
|
typ reflect.Type
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue