Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion beacon-chain/core/transition/transition_no_verify_sig.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ func ProcessBlobKzgs(ctx context.Context, state state.BeaconState, body interfac
return nil, errors.Wrap(err, "could not get transactions from payload")
}
if err := eip4844.VerifyKzgsAgainstTxs(txs, blobKzgsInput); err != nil {
return nil, err
return nil, errors.Wrap(err, "could not verify kzgs against txs")
}
return state, nil
}
Expand Down
61 changes: 55 additions & 6 deletions consensus-types/forks/eip4844/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package eip4844

import (
"bytes"
"errors"
"fmt"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
"github.com/protolambda/ztyp/codec"
)

Expand All @@ -16,16 +16,65 @@ var (
errInvalidNumBlobVersionedHashes = errors.New("invalid number of blob versioned hashes")
)

const (
versionedHashesOffset = 258 // offset the versioned_hash_offset in a serialized blob tx
messageLen = 192 // size in bytes of "message" within the serialized blob tx
)

// TxPeekBlobVersionedHashes is from EIP-4844, and extracts the list of versioned hashes from the
// given blob tx.
//
// Format of the blob tx relevant to this function is as follows:
// 0: type (value should always be BlobTxType, 1 byte)
// 1: message offset (value should always be 69, 4 bytes)
// 5: ECDSA signature (65 bytes)
// 70: start of "message" (192 bytes)
// 258: start of the versioned hash offset within "message" (4 bytes)
// 262-: rest of the tx following message
//
// TODO: unit tests, remove dependency on github.com/protolambda/ztyp
Copy link
Owner

@Inphi Inphi Oct 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, you can test using:

bazel test //beacon-chain/sync:go_default_test --test_filter='TestValidateBeaconBlockPubSub_ValidBlobKzgs'

or if you don't have bazel:

go test ./beacon-chain/sync/... -run 'TestValidateBeaconBlockPubSub.*'

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

though a specific unit test for this function would also be desired.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks! The test seems to also rely on geth so it fails until I point it at my local geth repo, which I guess confirms it's WAI!

func TxPeekBlobVersionedHashes(tx []byte) ([]common.Hash, error) {
// we start our reader at the versioned hash offset within the serialized tx
if len(tx) < versionedHashesOffset {
return nil, errors.New("blob tx invalid: too short")
}
if tx[0] != types.BlobTxType {
return nil, errInvalidBlobTxType
}
// TODO remove geth/ztyp dep
sbt := types.SignedBlobTx{}
if err := sbt.Deserialize(codec.NewDecodingReader(bytes.NewReader(tx[1:]), uint64(len(tx)-1))); err != nil {
return nil, fmt.Errorf("%w: unable to decode Blob Tx", err)
dr := codec.NewDecodingReader(bytes.NewReader(tx[versionedHashesOffset:]), uint64(len(tx)-versionedHashesOffset))

// read the offset to the versioned hashes
var offset uint32
offset, err := dr.ReadOffset()
if err != nil {
return nil, errors.Wrap(err, "could not read versioned hashes offset")
}

// Advance dr to the versioned hash list. We subtract messageLen from the offset here to
// account for the fact that the offset is relative to the position of "message" (70) and we
// are currently positioned at the end of it (262).
skip := uint64(offset) - messageLen
skipped, err := dr.Skip(skip)
if err != nil {
return nil, errors.Wrap(err, "could not skip to versioned hashes")
}
return sbt.Message.BlobVersionedHashes, nil
if skip != uint64(skipped) {
return nil, fmt.Errorf("did not skip to versioned hashes. want %v got %v", skip, skipped)
}

// read the list of hashes one by one until we hit the end of the data
hashes := []common.Hash{}
tmp := make([]byte, 32)
for dr.Scope() > 0 {
if _, err = dr.Read(tmp); err != nil {
return nil, errors.Wrap(err, "could not read versioned hashes")
}
var h common.Hash
copy(h[:], tmp)
hashes = append(hashes, h)
}

return hashes, nil
}

func VerifyKzgsAgainstTxs(txs [][]byte, blobKzgs [][48]byte) error {
Expand Down