From 54066453a8a8a3446401fb14602e220eab3090f1 Mon Sep 17 00:00:00 2001 From: Ethen Pociask Date: Wed, 14 Aug 2024 04:43:33 -0400 Subject: [PATCH] fix: Compute EigenDA preimage hash using preimage length - refactors and reworks --- arbitrator/prover/src/kzgbn254.rs | 20 ++++-- arbitrator/prover/src/utils.rs | 14 +++-- arbitrator/prover/test-cases/go/main.go | 2 +- .../prover/test-cases/rust/src/bin/host-io.rs | 2 +- cmd/replay/main.go | 4 +- contracts | 2 +- eigenda/eigenda.go | 19 ++++-- eigenda/proxy.go | 42 ++----------- eigenda/reader.go | 14 +---- eigenda/{decoding.go => serialize.go} | 63 ++----------------- eigenda/serialize_test.go | 22 +++++++ eigenda/types.go | 4 +- 12 files changed, 81 insertions(+), 127 deletions(-) rename eigenda/{decoding.go => serialize.go} (60%) create mode 100644 eigenda/serialize_test.go diff --git a/arbitrator/prover/src/kzgbn254.rs b/arbitrator/prover/src/kzgbn254.rs index b72eb5d19..d56ad8539 100644 --- a/arbitrator/prover/src/kzgbn254.rs +++ b/arbitrator/prover/src/kzgbn254.rs @@ -45,14 +45,18 @@ pub fn prove_kzg_preimage_bn254( blob.to_polynomial(PolynomialFormat::InCoefficientForm)?; let blob_commitment = kzg.commit(&blob_polynomial_evaluation_form)?; + 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(69); + 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!( @@ -68,6 +72,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; @@ -81,8 +90,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(|| { diff --git a/arbitrator/prover/src/utils.rs b/arbitrator/prover/src/utils.rs index d8880b845..68bc0ba31 100644 --- a/arbitrator/prover/src/utils.rs +++ b/arbitrator/prover/src/utils.rs @@ -232,12 +232,18 @@ 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) diff --git a/arbitrator/prover/test-cases/go/main.go b/arbitrator/prover/test-cases/go/main.go index fe174d075..5b357fb94 100644 --- a/arbitrator/prover/test-cases/go/main.go +++ b/arbitrator/prover/test-cases/go/main.go @@ -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)) } diff --git a/arbitrator/prover/test-cases/rust/src/bin/host-io.rs b/arbitrator/prover/test-cases/rust/src/bin/host-io.rs index aadfcb78c..9fdb9bf06 100644 --- a/arbitrator/prover/test-cases/rust/src/bin/host-io.rs +++ b/arbitrator/prover/test-cases/rust/src/bin/host-io.rs @@ -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); diff --git a/cmd/replay/main.go b/cmd/replay/main.go index 6e7e54caa..ebb9e1929 100644 --- a/cmd/replay/main.go +++ b/cmd/replay/main.go @@ -164,9 +164,7 @@ func (dasReader *EigenDAPreimageReader) QueryBlob(ctx context.Context, cert *eig 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 diff --git a/contracts b/contracts index 13f4041ab..5965f44e5 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 13f4041ab59f697bd04aaadb3692b8ca8da2cbe1 +Subproject commit 5965f44e581a31e1d54cefb365c2c8b517109209 diff --git a/eigenda/eigenda.go b/eigenda/eigenda.go index 5471adea7..127600c1f 100644 --- a/eigenda/eigenda.go +++ b/eigenda/eigenda.go @@ -4,16 +4,25 @@ import ( "context" "errors" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/offchainlabs/nitro/arbstate/daprovider" + "github.com/offchainlabs/nitro/solgen/go/bridgegen" ) -const ( - // NOTE - this will need to be updated everytime there are changes to the Inbox interface - // TODO - consoldiate ABI to only include `addSequencerBatchFromEigenDA` method signature or add ingestion of ABI file upon initialization of an arbitrum node - sequencerInboxABI = `[{"type":"constructor","inputs":[{"name":"_maxDataSize","type":"uint256","internalType":"uint256"},{"name":"reader4844_","type":"address","internalType":"contract IReader4844"},{"name":"eigenDAServiceManager_","type":"address","internalType":"contract IEigenDAServiceManager"},{"name":"eigenDARollupManager_","type":"address","internalType":"contract IRollupManager"},{"name":"_isUsingFeeToken","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"BROTLI_MESSAGE_HEADER_FLAG","inputs":[],"outputs":[{"name":"","type":"bytes1","internalType":"bytes1"}],"stateMutability":"view"},{"type":"function","name":"DAS_MESSAGE_HEADER_FLAG","inputs":[],"outputs":[{"name":"","type":"bytes1","internalType":"bytes1"}],"stateMutability":"view"},{"type":"function","name":"DATA_AUTHENTICATED_FLAG","inputs":[],"outputs":[{"name":"","type":"bytes1","internalType":"bytes1"}],"stateMutability":"view"},{"type":"function","name":"DATA_BLOB_HEADER_FLAG","inputs":[],"outputs":[{"name":"","type":"bytes1","internalType":"bytes1"}],"stateMutability":"view"},{"type":"function","name":"EIGENDA_MESSAGE_HEADER_FLAG","inputs":[],"outputs":[{"name":"","type":"bytes1","internalType":"bytes1"}],"stateMutability":"view"},{"type":"function","name":"HEADER_LENGTH","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"TREE_DAS_MESSAGE_HEADER_FLAG","inputs":[],"outputs":[{"name":"","type":"bytes1","internalType":"bytes1"}],"stateMutability":"view"},{"type":"function","name":"ZERO_HEAVY_MESSAGE_HEADER_FLAG","inputs":[],"outputs":[{"name":"","type":"bytes1","internalType":"bytes1"}],"stateMutability":"view"},{"type":"function","name":"addSequencerL2Batch","inputs":[{"name":"sequenceNumber","type":"uint256","internalType":"uint256"},{"name":"data","type":"bytes","internalType":"bytes"},{"name":"afterDelayedMessagesRead","type":"uint256","internalType":"uint256"},{"name":"gasRefunder","type":"address","internalType":"contract IGasRefunder"},{"name":"prevMessageCount","type":"uint256","internalType":"uint256"},{"name":"newMessageCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addSequencerL2BatchFromBlobs","inputs":[{"name":"sequenceNumber","type":"uint256","internalType":"uint256"},{"name":"afterDelayedMessagesRead","type":"uint256","internalType":"uint256"},{"name":"gasRefunder","type":"address","internalType":"contract IGasRefunder"},{"name":"prevMessageCount","type":"uint256","internalType":"uint256"},{"name":"newMessageCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addSequencerL2BatchFromEigenDA","inputs":[{"name":"sequenceNumber","type":"uint256","internalType":"uint256"},{"name":"blobVerificationProof","type":"tuple","internalType":"struct EigenDARollupUtils.BlobVerificationProof","components":[{"name":"batchId","type":"uint32","internalType":"uint32"},{"name":"blobIndex","type":"uint32","internalType":"uint32"},{"name":"batchMetadata","type":"tuple","internalType":"struct IEigenDAServiceManager.BatchMetadata","components":[{"name":"batchHeader","type":"tuple","internalType":"struct IEigenDAServiceManager.BatchHeader","components":[{"name":"blobHeadersRoot","type":"bytes32","internalType":"bytes32"},{"name":"quorumNumbers","type":"bytes","internalType":"bytes"},{"name":"signedStakeForQuorums","type":"bytes","internalType":"bytes"},{"name":"referenceBlockNumber","type":"uint32","internalType":"uint32"}]},{"name":"signatoryRecordHash","type":"bytes32","internalType":"bytes32"},{"name":"confirmationBlockNumber","type":"uint32","internalType":"uint32"}]},{"name":"inclusionProof","type":"bytes","internalType":"bytes"},{"name":"quorumIndices","type":"bytes","internalType":"bytes"}]},{"name":"blobHeader","type":"tuple","internalType":"struct IEigenDAServiceManager.BlobHeader","components":[{"name":"commitment","type":"tuple","internalType":"struct BN254.G1Point","components":[{"name":"X","type":"uint256","internalType":"uint256"},{"name":"Y","type":"uint256","internalType":"uint256"}]},{"name":"dataLength","type":"uint32","internalType":"uint32"},{"name":"quorumBlobParams","type":"tuple[]","internalType":"struct IEigenDAServiceManager.QuorumBlobParam[]","components":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"adversaryThresholdPercentage","type":"uint8","internalType":"uint8"},{"name":"confirmationThresholdPercentage","type":"uint8","internalType":"uint8"},{"name":"chunkLength","type":"uint32","internalType":"uint32"}]}]},{"name":"gasRefunder","type":"address","internalType":"contract IGasRefunder"},{"name":"afterDelayedMessagesRead","type":"uint256","internalType":"uint256"},{"name":"prevMessageCount","type":"uint256","internalType":"uint256"},{"name":"newMessageCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addSequencerL2BatchFromOrigin","inputs":[{"name":"","type":"uint256","internalType":"uint256"},{"name":"","type":"bytes","internalType":"bytes"},{"name":"","type":"uint256","internalType":"uint256"},{"name":"","type":"address","internalType":"contract IGasRefunder"}],"outputs":[],"stateMutability":"pure"},{"type":"function","name":"addSequencerL2BatchFromOrigin","inputs":[{"name":"sequenceNumber","type":"uint256","internalType":"uint256"},{"name":"data","type":"bytes","internalType":"bytes"},{"name":"afterDelayedMessagesRead","type":"uint256","internalType":"uint256"},{"name":"gasRefunder","type":"address","internalType":"contract IGasRefunder"},{"name":"prevMessageCount","type":"uint256","internalType":"uint256"},{"name":"newMessageCount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"batchCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"batchPosterManager","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"bridge","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IBridge"}],"stateMutability":"view"},{"type":"function","name":"dasKeySetInfo","inputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"isValidKeyset","type":"bool","internalType":"bool"},{"name":"creationBlock","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"eigenDARollupManager","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IRollupManager"}],"stateMutability":"view"},{"type":"function","name":"eigenDAServiceManager","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IEigenDAServiceManager"}],"stateMutability":"view"},{"type":"function","name":"forceInclusion","inputs":[{"name":"_totalDelayedMessagesRead","type":"uint256","internalType":"uint256"},{"name":"kind","type":"uint8","internalType":"uint8"},{"name":"l1BlockAndTime","type":"uint64[2]","internalType":"uint64[2]"},{"name":"baseFeeL1","type":"uint256","internalType":"uint256"},{"name":"sender","type":"address","internalType":"address"},{"name":"messageDataHash","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getKeysetCreationBlock","inputs":[{"name":"ksHash","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"inboxAccs","inputs":[{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"bridge_","type":"address","internalType":"contract IBridge"},{"name":"maxTimeVariation_","type":"tuple","internalType":"struct ISequencerInbox.MaxTimeVariation","components":[{"name":"delayBlocks","type":"uint256","internalType":"uint256"},{"name":"futureBlocks","type":"uint256","internalType":"uint256"},{"name":"delaySeconds","type":"uint256","internalType":"uint256"},{"name":"futureSeconds","type":"uint256","internalType":"uint256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"invalidateKeysetHash","inputs":[{"name":"ksHash","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isBatchPoster","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isSequencer","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isUsingFeeToken","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isValidKeysetHash","inputs":[{"name":"ksHash","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"maxDataSize","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxTimeVariation","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"},{"name":"","type":"uint256","internalType":"uint256"},{"name":"","type":"uint256","internalType":"uint256"},{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"postUpgradeInit","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"reader4844","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IReader4844"}],"stateMutability":"view"},{"type":"function","name":"removeDelayAfterFork","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"rollup","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IOwnable"}],"stateMutability":"view"},{"type":"function","name":"setBatchPosterManager","inputs":[{"name":"newBatchPosterManager","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setIsBatchPoster","inputs":[{"name":"addr","type":"address","internalType":"address"},{"name":"isBatchPoster_","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setIsSequencer","inputs":[{"name":"addr","type":"address","internalType":"address"},{"name":"isSequencer_","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setMaxTimeVariation","inputs":[{"name":"maxTimeVariation_","type":"tuple","internalType":"struct ISequencerInbox.MaxTimeVariation","components":[{"name":"delayBlocks","type":"uint256","internalType":"uint256"},{"name":"futureBlocks","type":"uint256","internalType":"uint256"},{"name":"delaySeconds","type":"uint256","internalType":"uint256"},{"name":"futureSeconds","type":"uint256","internalType":"uint256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setValidKeyset","inputs":[{"name":"keysetBytes","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"totalDelayedMessagesRead","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"event","name":"InboxMessageDelivered","inputs":[{"name":"messageNum","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"data","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"InboxMessageDeliveredFromOrigin","inputs":[{"name":"messageNum","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"InvalidateKeyset","inputs":[{"name":"keysetHash","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"OwnerFunctionCalled","inputs":[{"name":"id","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"SequencerBatchData","inputs":[{"name":"batchSequenceNumber","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"data","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"SequencerBatchDelivered","inputs":[{"name":"batchSequenceNumber","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"beforeAcc","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"afterAcc","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"delayedAcc","type":"bytes32","indexed":false,"internalType":"bytes32"},{"name":"afterDelayedMessagesRead","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"timeBounds","type":"tuple","indexed":false,"internalType":"struct IBridge.TimeBounds","components":[{"name":"minTimestamp","type":"uint64","internalType":"uint64"},{"name":"maxTimestamp","type":"uint64","internalType":"uint64"},{"name":"minBlockNumber","type":"uint64","internalType":"uint64"},{"name":"maxBlockNumber","type":"uint64","internalType":"uint64"}]},{"name":"dataLocation","type":"uint8","indexed":false,"internalType":"enum IBridge.BatchDataLocation"}],"anonymous":false},{"type":"event","name":"SetValidKeyset","inputs":[{"name":"keysetHash","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"keysetBytes","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"error","name":"AlreadyInit","inputs":[]},{"type":"error","name":"AlreadyValidDASKeyset","inputs":[{"name":"","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"BadMaxTimeVariation","inputs":[]},{"type":"error","name":"BadPostUpgradeInit","inputs":[]},{"type":"error","name":"BadSequencerNumber","inputs":[{"name":"stored","type":"uint256","internalType":"uint256"},{"name":"received","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"DataBlobsNotSupported","inputs":[]},{"type":"error","name":"DataTooLarge","inputs":[{"name":"dataLength","type":"uint256","internalType":"uint256"},{"name":"maxDataLength","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"DelayedBackwards","inputs":[]},{"type":"error","name":"DelayedTooFar","inputs":[]},{"type":"error","name":"Deprecated","inputs":[]},{"type":"error","name":"ForceIncludeBlockTooSoon","inputs":[]},{"type":"error","name":"ForceIncludeTimeTooSoon","inputs":[]},{"type":"error","name":"HadZeroInit","inputs":[]},{"type":"error","name":"IncorrectMessagePreimage","inputs":[]},{"type":"error","name":"InitParamZero","inputs":[{"name":"name","type":"string","internalType":"string"}]},{"type":"error","name":"InvalidHeaderFlag","inputs":[{"name":"","type":"bytes1","internalType":"bytes1"}]},{"type":"error","name":"MissingDataHashes","inputs":[]},{"type":"error","name":"NativeTokenMismatch","inputs":[]},{"type":"error","name":"NoSuchKeyset","inputs":[{"name":"","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"NotBatchPoster","inputs":[]},{"type":"error","name":"NotBatchPosterManager","inputs":[{"name":"","type":"address","internalType":"address"}]},{"type":"error","name":"NotForked","inputs":[]},{"type":"error","name":"NotOrigin","inputs":[]},{"type":"error","name":"NotOwner","inputs":[{"name":"sender","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"}]}]` +var sequencerInboxABI *abi.ABI + +func init() { + var err error + sequencerInboxABI, err = bridgegen.SequencerInboxMetaData.GetAbi() + if err != nil { + panic(err) + } +} +const ( + sequencerMsgOffset = 41 MaxBatchSize = 2_000_000 // 2MB ) @@ -63,7 +72,7 @@ func (e *EigenDA) QueryBlob(ctx context.Context, cert *EigenDABlobInfo, domainFi return nil, err } - data, err := e.client.Get(ctx, info, domainFilter) + data, err := e.client.Get(ctx, info) if err != nil { return nil, err } diff --git a/eigenda/proxy.go b/eigenda/proxy.go index 40b0188cd..2827354eb 100644 --- a/eigenda/proxy.go +++ b/eigenda/proxy.go @@ -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) @@ -46,7 +46,7 @@ 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) } @@ -54,38 +54,6 @@ func (c *EigenDAProxyClient) Get(ctx context.Context, blobInfo *DisperserBlobInf 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 @@ -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) } @@ -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 { diff --git a/eigenda/reader.go b/eigenda/reader.go index 39379cb65..ac1f858ec 100644 --- a/eigenda/reader.go +++ b/eigenda/reader.go @@ -4,9 +4,7 @@ import ( "context" "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" @@ -23,7 +21,6 @@ type readerForEigenDA struct { readerEigenDA EigenDAReader } -const sequencerMsgOffset = 41 func (d *readerForEigenDA) IsValidHeaderByte(headerByte byte) bool { return IsEigenDAMessageHeaderByte(headerByte) @@ -67,7 +64,7 @@ func RecoverPayloadFromEigenDABatch(ctx context.Context, if preimageRecoder != nil { // iFFT the preimage data - preimage, err := EncodeBlob(data) + preimage, err := GenericEncodeBlob(data) if err != nil { return nil, err } @@ -79,17 +76,12 @@ func RecoverPayloadFromEigenDABatch(ctx context.Context, // 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 } diff --git a/eigenda/decoding.go b/eigenda/serialize.go similarity index 60% rename from eigenda/decoding.go rename to eigenda/serialize.go index 83bf8327e..a9ef45988 100644 --- a/eigenda/decoding.go +++ b/eigenda/serialize.go @@ -4,10 +4,8 @@ import ( "bytes" "encoding/binary" "fmt" - "math" "github.com/Layr-Labs/eigenda/encoding" - "github.com/Layr-Labs/eigenda/encoding/fft" "github.com/Layr-Labs/eigenda/encoding/rs" "github.com/Layr-Labs/eigenda/encoding/utils/codec" "github.com/consensys/gnark-crypto/ecc/bn254/fr" @@ -18,49 +16,13 @@ import ( - https://github.com/Layr-Labs/eigenda/blob/44569ec461c9a1dd1191e7999a72e63bd1e7aba9/api/clients/codecs/ifft_codec.go#L27-L38 */ -func FFT(data []byte) ([]byte, error) { - dataFr, err := rs.ToFrArray(data) - if err != nil { - return nil, fmt.Errorf("error converting data to fr.Element: %w", err) - } - dataFrLen := uint64(len(dataFr)) - dataFrLenPow2 := encoding.NextPowerOf2(dataFrLen) - - if dataFrLenPow2 != dataFrLen { - return nil, fmt.Errorf("data length %d is not a power of 2", dataFrLen) - } - - maxScale := uint8(math.Log2(float64(dataFrLenPow2))) - - fs := fft.NewFFTSettings(maxScale) - - dataFFTFr, err := fs.FFT(dataFr, false) - if err != nil { - return nil, fmt.Errorf("failed to perform FFT: %w", err) - } - - return rs.ToByteArray(dataFFTFr, dataFrLenPow2*encoding.BYTES_PER_SYMBOL), nil -} - -func DecodeiFFTBlob(data []byte) ([]byte, error) { - if len(data) == 0 { - return nil, fmt.Errorf("blob has length 0, meaning it is malformed") - } - var err error - data, err = FFT(data) - if err != nil { - return nil, fmt.Errorf("error FFTing data: %w", err) - } - - return GenericDecodeBlob(data) -} func GenericDecodeBlob(data []byte) ([]byte, error) { if len(data) <= 32 { return nil, fmt.Errorf("data is not of length greater than 32 bytes: %d", len(data)) } - data, err := DecodeBlob(data) + data, err := decodeBlob(data) if err != nil { return nil, err } @@ -68,11 +30,7 @@ func GenericDecodeBlob(data []byte) ([]byte, error) { return data, nil } -func DecodeBlob(data []byte) ([]byte, error) { - if len(data) < 32 { - return nil, fmt.Errorf("blob does not contain 32 header bytes, meaning it is malformed") - } - +func decodeBlob(data []byte) ([]byte, error) { length := binary.BigEndian.Uint32(data[2:6]) // decode raw data modulo bn254 @@ -93,14 +51,14 @@ func DecodeBlob(data []byte) ([]byte, error) { } -func EncodeBlob(data []byte) ([]byte, error) { +func GenericEncodeBlob(data []byte) ([]byte, error) { var err error data, err = encodeBlob(data) if err != nil { return nil, fmt.Errorf("error encoding data: %w", err) } - return IFFT(data) + return padPow2(data) } func encodeBlob(rawData []byte) ([]byte, error) { @@ -122,7 +80,7 @@ func encodeBlob(rawData []byte) ([]byte, error) { return encodedData, nil } -func IFFT(data []byte) ([]byte, error) { +func padPow2(data []byte) ([]byte, error) { // we now IFFT data regardless of the encoding type // convert data to fr.Element dataFr, err := rs.ToFrArray(data) @@ -143,14 +101,5 @@ func IFFT(data []byte) ([]byte, error) { } } - maxScale := uint8(math.Log2(float64(dataFrLenPow2))) - - // perform IFFT - fs := fft.NewFFTSettings(maxScale) - dataIFFTFr, err := fs.FFT(paddedDataFr, true) - if err != nil { - return nil, fmt.Errorf("failed to perform IFFT: %w", err) - } - - return rs.ToByteArray(dataIFFTFr, dataFrLenPow2*encoding.BYTES_PER_SYMBOL), nil + return rs.ToByteArray(paddedDataFr, dataFrLenPow2*encoding.BYTES_PER_SYMBOL), nil } diff --git a/eigenda/serialize_test.go b/eigenda/serialize_test.go new file mode 100644 index 000000000..d6464b15d --- /dev/null +++ b/eigenda/serialize_test.go @@ -0,0 +1,22 @@ +package eigenda + +import "testing" + + +func Test_EncodeDecodeBlob(t *testing.T) { + rawBlob := []byte("optimistic nihilism") + + encodedBlob, err := GenericEncodeBlob(rawBlob) + if err != nil { + t.Fatalf("failed to encode blob: %v", err) + } + + decodedBlob, err := GenericDecodeBlob(encodedBlob) + if err != nil { + t.Fatalf("failed to decode blob: %v", err) + } + + if string(decodedBlob) != string(rawBlob) { + t.Fatalf("decoded blob does not match raw blob") + } +} \ No newline at end of file diff --git a/eigenda/types.go b/eigenda/types.go index 711358b52..4d8395134 100644 --- a/eigenda/types.go +++ b/eigenda/types.go @@ -22,6 +22,9 @@ type EigenDABlobInfo struct { BlobVerificationProof BlobVerificationProof `json:"blobVerificationProof"` } +/* + Unlike 4844 there's no need to inject a version byte into the 0th offset of the hash +*/ func (e *EigenDABlobInfo) PreimageHash() (*common.Hash, error) { kzgCommit, err := e.SerializeCommitment() if err != nil { @@ -32,7 +35,6 @@ func (e *EigenDABlobInfo) PreimageHash() (*common.Hash, error) { digest := append(kzgCommit, uint32ToBytes(e.BlobHeader.DataLength)...) shaDataHash.Write(digest) dataHash := shaDataHash.Sum([]byte{}) - dataHash[0] = 1 h := common.BytesToHash(dataHash)