Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: length trust assumption #20

Closed
19 changes: 13 additions & 6 deletions arbitrator/prover/src/kzgbn254.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,15 @@ pub fn prove_kzg_preimage_bn254(

let commitment_x_bigint: BigUint = blob_commitment.x.into();
let commitment_y_bigint: BigUint = blob_commitment.y.into();
let mut commitment_encoded_bytes = Vec::with_capacity(32);
append_left_padded_biguint_be(&mut commitment_encoded_bytes, &commitment_x_bigint);
append_left_padded_biguint_be(&mut commitment_encoded_bytes, &commitment_y_bigint);
let length_bigint: BigUint = blob.len().into();

let mut commitment_encoded_length_bytes = Vec::with_capacity(68);
append_left_padded_biguint_be(&mut commitment_encoded_length_bytes, &commitment_x_bigint);
append_left_padded_biguint_be(&mut commitment_encoded_length_bytes, &commitment_y_bigint);
append_left_padded_biguint_be(&mut commitment_encoded_length_bytes, &length_bigint);

let mut keccak256_hasher = Keccak256::new();
keccak256_hasher.update(&commitment_encoded_bytes);
keccak256_hasher.update(&commitment_encoded_length_bytes);
let commitment_hash: Bytes32 = keccak256_hasher.finalize().into();

ensure!(
Expand All @@ -68,6 +71,11 @@ pub fn prove_kzg_preimage_bn254(
offset,
);

let mut commitment_encoded_bytes = Vec::with_capacity(64);

append_left_padded_biguint_be(&mut commitment_encoded_bytes, &commitment_x_bigint);
append_left_padded_biguint_be(&mut commitment_encoded_bytes, &commitment_y_bigint);

let mut proving_offset = offset;
let length_usize = preimage.len() as u64;

Expand All @@ -81,8 +89,7 @@ pub fn prove_kzg_preimage_bn254(
proving_offset = 0;
}

// Y = ϕ(offset) --> evaluation point for computing quotient proof
// confirming if this is actually ok ?
// Y = ϕ(offset)
let proven_y_fr = blob_polynomial_evaluation_form
.get_at_index(proving_offset as usize / 32)
.ok_or_else(|| {
Expand Down
8 changes: 8 additions & 0 deletions arbitrator/prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,14 @@ unsafe fn handle_preimage_resolution(
Some(data)
}

#[no_mangle]
pub unsafe extern "C" fn arbitrator_get_opcode(mach: *mut Machine) -> u16 {
match (*mach).get_next_instruction() {
Some(instruction) => return instruction.opcode.repr(),
None => panic!("Failed to get next opcode for Machine"),
}
}

#[no_mangle]
#[cfg(feature = "native")]
pub unsafe extern "C" fn arbitrator_set_preimage_resolver(
Expand Down
19 changes: 15 additions & 4 deletions arbitrator/prover/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,23 @@ pub fn hash_preimage(preimage: &[u8], ty: PreimageType) -> Result<[u8; 32]> {

let commitment_x_bigint: BigUint = blob_commitment.x.into();
let commitment_y_bigint: BigUint = blob_commitment.y.into();
let mut commitment_encoded_bytes = Vec::with_capacity(32);
append_left_padded_biguint_be(&mut commitment_encoded_bytes, &commitment_x_bigint);
append_left_padded_biguint_be(&mut commitment_encoded_bytes, &commitment_y_bigint);
let length_bigint: BigUint = blob.len().into();
// 32 bytes per each commitment coordinate (64 bytes)
// 25 bits for length considering 32mb blobs padded to nearest power of 2 (2^25)
// pad to 32 bits or 4 bytes so 68 bytes total
let mut commitment_length_encoded_bytes = Vec::with_capacity(68);
append_left_padded_biguint_be(
&mut commitment_length_encoded_bytes,
&commitment_x_bigint,
);
append_left_padded_biguint_be(
&mut commitment_length_encoded_bytes,
&commitment_y_bigint,
);
append_left_padded_biguint_be(&mut commitment_length_encoded_bytes, &length_bigint);

let mut keccak256_hasher = Keccak256::new();
keccak256_hasher.update(&commitment_encoded_bytes);
keccak256_hasher.update(&commitment_length_encoded_bytes);
let commitment_hash: [u8; 32] = keccak256_hasher.finalize().into();

Ok(commitment_hash)
Expand Down
2 changes: 1 addition & 1 deletion arbitrator/prover/test-cases/go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ func main() {
}
}
// EIGENDA COMMIT HASH
_, err = wavmio.ResolveTypedPreimage(arbutil.EigenDaPreimageType, common.HexToHash("13bbacb54f9aa9896af97156ca4dfc626e94031c5ed78fea68659e4ec9c9c55a"))
_, err = wavmio.ResolveTypedPreimage(arbutil.EigenDaPreimageType, common.HexToHash("12deeb4e7b4288fcab2d46116afdd708f606e2e44157d0c423a5a0d310f88483"))
if err != nil {
panic(fmt.Sprintf("failed to resolve eigenda preimage: %v", err))
}
Expand Down
2 changes: 1 addition & 1 deletion arbitrator/prover/test-cases/rust/src/bin/host-io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ fn main() {
for i in 0..5{
// test-files srs 011e229d75b13559dcb2d757ecae9b66fa579268e28e196789503322115c06e1
// mainnet srs 01605220b6928163676612ca50bbe5e0c595052876796dbedeae8ef597c9fdcf
let eigen_hash = hex!("13bbacb54f9aa9896af97156ca4dfc626e94031c5ed78fea68659e4ec9c9c55a");
let eigen_hash = hex!("12deeb4e7b4288fcab2d46116afdd708f606e2e44157d0c423a5a0d310f88483");
bytebuffer = Bytes32(eigen_hash);

let actual_len = wavm_read_eigen_da_hash_preimage(bytebuffer.0.as_mut_ptr(), i * 32);
Expand Down
17 changes: 4 additions & 13 deletions cmd/replay/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package main
import (
"bytes"
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -155,25 +154,17 @@ type EigenDAPreimageReader struct{}
// QueryBlob returns the blob for the given cert from the preimage oracle using the hash of the
// certificate kzg commitment for identifying the preimage.
func (dasReader *EigenDAPreimageReader) QueryBlob(ctx context.Context, cert *eigenda.EigenDABlobInfo, domain string) ([]byte, error) {
kzgCommit, err := cert.SerializeCommitment()
hash, err := cert.PreimageHash()
if err != nil {
return nil, err
}

shaDataHash := sha256.New()
shaDataHash.Write(kzgCommit)
dataHash := shaDataHash.Sum([]byte{})
dataHash[0] = 1

hash := common.BytesToHash(dataHash)
preimage, err := wavmio.ResolveTypedPreimage(arbutil.EigenDaPreimageType, hash)
preimage, err := wavmio.ResolveTypedPreimage(arbutil.EigenDaPreimageType, *hash)
if err != nil {
return nil, err
}

// since the preimage is in encoded co-efficient form, we need to decode it to get the actual blob
// i.e,polynomial -> FFT -> length decode -> inverse onec -> blob
decodedBlob, err := eigenda.DecodeiFFTBlob(preimage)
decodedBlob, err := eigenda.GenericDecodeBlob(preimage)
if err != nil {
println("Error decoding blob: ", err)
return nil, err
Expand Down Expand Up @@ -254,7 +245,7 @@ func main() {
dapReaders = append(dapReaders, daprovider.NewReaderForDAS(dasReader))
}
if eigenDAReader != nil {
dapReaders = append(dapReaders, eigenda.NewBinaryReaderForEigenDA(eigenDAReader))
dapReaders = append(dapReaders, eigenda.NewReaderForEigenDA(eigenDAReader))
}

dapReaders = append(dapReaders, daprovider.NewReaderForBlobReader(&BlobPreimageReader{}))
Expand Down
2 changes: 1 addition & 1 deletion contracts
23 changes: 17 additions & 6 deletions eigenda/eigenda.go

Large diffs are not rendered by default.

42 changes: 5 additions & 37 deletions eigenda/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (c *EigenDAProxyClient) Put(ctx context.Context, data []byte) (*disperser.B
return &blobInfo, nil
}

func (c *EigenDAProxyClient) Get(ctx context.Context, blobInfo *DisperserBlobInfo, domainFilter string) ([]byte, error) {
func (c *EigenDAProxyClient) Get(ctx context.Context, blobInfo *DisperserBlobInfo) ([]byte, error) {
commitment, err := rlp.EncodeToBytes(blobInfo)
if err != nil {
return nil, fmt.Errorf("failed to encode blob info: %w", err)
Expand All @@ -46,46 +46,14 @@ func (c *EigenDAProxyClient) Get(ctx context.Context, blobInfo *DisperserBlobInf
// TODO: support more strict versioning
commitWithVersion := append([]byte{0x0}, commitment...)

data, err := c.client.GetData(ctx, commitWithVersion, StrToDomainType(domainFilter))
data, err := c.client.GetData(ctx, commitWithVersion)
if err != nil {
return nil, fmt.Errorf("failed to get data: %w", err)
}

return data, nil
}

// DomainType is a enumeration type for the different data domains for which a
// blob can exist between
type DomainType uint8

const (
BinaryDomain DomainType = iota
PolyDomain
UnknownDomain
)

func (d DomainType) String() string {
switch d {
case BinaryDomain:
return "binary"
case PolyDomain:
return "polynomial"
default:
return "unknown"
}
}

func StrToDomainType(s string) DomainType {
switch s {
case "binary":
return BinaryDomain
case "polynomial":
return PolyDomain
default:
return UnknownDomain
}
}

// TODO: Add support for custom http client option
type Config struct {
URL string
Expand All @@ -94,7 +62,7 @@ type Config struct {
// ProxyClient is an interface for communicating with the EigenDA proxy server
type ProxyClient interface {
Health() error
GetData(ctx context.Context, cert []byte, domain DomainType) ([]byte, error)
GetData(ctx context.Context, cert []byte) ([]byte, error)
SetData(ctx context.Context, b []byte) ([]byte, error)
}

Expand Down Expand Up @@ -135,8 +103,8 @@ func (c *client) Health() error {
}

// GetData fetches blob data associated with a DA certificate
func (c *client) GetData(ctx context.Context, comm []byte, domain DomainType) ([]byte, error) {
url := fmt.Sprintf("%s/get/0x%x?domain=%s&commitment_mode=simple", c.cfg.URL, comm, domain.String())
func (c *client) GetData(ctx context.Context, comm []byte) ([]byte, error) {
url := fmt.Sprintf("%s/get/0x%x?commitment_mode=simple", c.cfg.URL, comm)

req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
Expand Down
56 changes: 10 additions & 46 deletions eigenda/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,15 @@ package eigenda

import (
"context"
"crypto/sha256"
"encoding/binary"
"errors"
"strings"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/offchainlabs/nitro/arbstate/daprovider"
"github.com/offchainlabs/nitro/arbutil"
)

// NewReaderForEigenDA is generally meant to be only used by nitro.
// DA Providers should implement methods in the Reader interface independently
func NewReaderForEigenDA(reader EigenDAReader) *readerForEigenDA {
return &readerForEigenDA{readerEigenDA: reader}
}
Expand All @@ -23,8 +19,6 @@ type readerForEigenDA struct {
readerEigenDA EigenDAReader
}

const sequencerMsgOffset = 41

func (d *readerForEigenDA) IsValidHeaderByte(headerByte byte) bool {
return IsEigenDAMessageHeaderByte(headerByte)
}
Expand Down Expand Up @@ -59,42 +53,31 @@ func RecoverPayloadFromEigenDABatch(ctx context.Context,
return nil, err
}

// record preimage data for EigenDA using the hash of the commitment
// for lookups in the replay script
kzgCommit, err := blobInfo.SerializeCommitment()
hash, err := blobInfo.PreimageHash()
if err != nil {
return nil, err
}

shaDataHash := sha256.New()
shaDataHash.Write(kzgCommit)
dataHash := shaDataHash.Sum([]byte{})
dataHash[0] = 1
if preimageRecoder != nil {
// iFFT the preimage data
preimage, err := EncodeBlob(data)
preimage, err := GenericEncodeBlob(data)
if err != nil {
return nil, err
}
preimageRecoder(common.BytesToHash(dataHash), preimage, arbutil.EigenDaPreimageType)
preimageRecoder(*hash, preimage, arbutil.EigenDaPreimageType)
}
return data, nil
}

// ParseSequencerMsg parses the inbox tx calldata into a structured EigenDABlobInfo
func ParseSequencerMsg(calldata []byte) (*EigenDABlobInfo, error) {

// this should never happen, but just in case
if len(calldata) < 4 {
return nil, errors.New("calldata is shorter than expected method signature length")
}

// TODO: Construct the ABI struct at node initialization
abi, err := abi.JSON(strings.NewReader(sequencerInboxABI))
if err != nil {
return nil, err
}

method, err := abi.MethodById(calldata[0:4])
method, err := sequencerInboxABI.MethodById(calldata[0:4])
if err != nil {
return nil, err
}
Expand All @@ -118,27 +101,8 @@ func ParseSequencerMsg(calldata []byte) (*EigenDABlobInfo, error) {

}

// NewReaderForEigenDA is generally meant to be only used by nitro.
// DA Providers should implement methods in the Reader interface independently
func NewBinaryReaderForEigenDA(reader EigenDAReader) *binaryReaderForEigenDA {
return &binaryReaderForEigenDA{readerEigenDA: reader}
}

type binaryReaderForEigenDA struct {
readerEigenDA EigenDAReader
}

func (d *binaryReaderForEigenDA) IsValidHeaderByte(headerByte byte) bool {
return IsEigenDAMessageHeaderByte(headerByte)
}

func (d *binaryReaderForEigenDA) RecoverPayloadFromBatch(
ctx context.Context,
batchNum uint64,
batchBlockHash common.Hash,
sequencerMsg []byte,
preimageRecorder daprovider.PreimageRecorder,
validateSeqMsg bool,
) ([]byte, error) {
return RecoverPayloadFromEigenDABatch(ctx, sequencerMsg[sequencerMsgOffset:], d.readerEigenDA, preimageRecorder, "binary")
func uint32ToBytes(n uint32) []byte {
bytes := make([]byte, 4)
binary.BigEndian.PutUint32(bytes, n)
return bytes
}
Loading
Loading