From 887827c8f59427d4427e7461f83d873d3bc9aea1 Mon Sep 17 00:00:00 2001 From: hopeyen Date: Mon, 7 Oct 2024 20:53:45 -0700 Subject: [PATCH] chore: inabox e2e test --- inabox/bin.sh | 1 - inabox/deploy/config.go | 11 ++- inabox/deploy/env_vars.go | 10 ++ inabox/deploy/utils.go | 4 +- inabox/tests/integration_test.go | 5 +- inabox/tests/payment_test.go | 151 +++++++++++++++++++++++++++++++ inabox/tests/ratelimit_test.go | 2 +- 7 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 inabox/tests/payment_test.go diff --git a/inabox/bin.sh b/inabox/bin.sh index 7f27cd79f..c2143725f 100755 --- a/inabox/bin.sh +++ b/inabox/bin.sh @@ -1,5 +1,4 @@ #!/bin/bash - pids="" function kill_processes { echo "STOP" diff --git a/inabox/deploy/config.go b/inabox/deploy/config.go index 01795d65f..ef193e76b 100644 --- a/inabox/deploy/config.go +++ b/inabox/deploy/config.go @@ -175,8 +175,15 @@ func (env *Config) generateDisperserVars(ind int, key, address, logPath, dbPath, DISPERSER_SERVER_PER_USER_UNAUTH_BYTE_RATE: "32000,32000", DISPERSER_SERVER_TOTAL_UNAUTH_BLOB_RATE: "10,10", DISPERSER_SERVER_PER_USER_UNAUTH_BLOB_RATE: "2,2", - DISPERSER_SERVER_ENABLE_RATELIMITER: "true", - DISPERSER_SERVER_ALLOWLIST: "3.221.120.68/0/1000/10485760,18.214.113.214/0/1000/10485760", + + DISPERSER_SERVER_ENABLE_PAYMENT_METERER: "true", + DISPERSER_SERVER_RESERVATION_WINDOW: "60", + DISPERSER_SERVER_MIN_CHARGEABLE_SIZE: "100", + DISPERSER_SERVER_PRICE_PER_CHARGEABLE: "100", + DISPERSER_SERVER_ON_DEMAND_GLOBAL_LIMIT: "1000", + + DISPERSER_SERVER_ENABLE_RATELIMITER: "true", + DISPERSER_SERVER_ALLOWLIST: "3.221.120.68/0/1000/10485760,18.214.113.214/0/1000/10485760", DISPERSER_SERVER_RETRIEVAL_BLOB_RATE: "4", DISPERSER_SERVER_RETRIEVAL_BYTE_RATE: "10000000", diff --git a/inabox/deploy/env_vars.go b/inabox/deploy/env_vars.go index f701ce64d..c419feb2f 100644 --- a/inabox/deploy/env_vars.go +++ b/inabox/deploy/env_vars.go @@ -76,6 +76,16 @@ type DisperserVars struct { DISPERSER_SERVER_RETRIEVAL_BLOB_RATE string DISPERSER_SERVER_RETRIEVAL_BYTE_RATE string + + DISPERSER_SERVER_ENABLE_PAYMENT_METERER string + + DISPERSER_SERVER_RESERVATION_WINDOW string + + DISPERSER_SERVER_MIN_CHARGEABLE_SIZE string + + DISPERSER_SERVER_PRICE_PER_CHARGEABLE string + + DISPERSER_SERVER_ON_DEMAND_GLOBAL_LIMIT string } func (vars DisperserVars) getEnvMap() map[string]string { diff --git a/inabox/deploy/utils.go b/inabox/deploy/utils.go index f83dc2232..37cbc590e 100644 --- a/inabox/deploy/utils.go +++ b/inabox/deploy/utils.go @@ -163,8 +163,8 @@ func execForgeScript(script, privateKey string, deployer *ContractDeployer, extr log.Println("Executing forge script with command: ", cmd.String()) err := cmd.Run() if err != nil { - log.Panicf("Failed to execute forge script: %s\n Err: %s\n--- std out ---\n%s\n--- std err ---\n%s\n", - cmd, err, out.String(), stderr.String()) + log.Print(fmt.Sprint(err) + ": " + stderr.String()) + log.Panicf("Failed to execute forge script. Err: %s", err) } else { log.Print(out.String()) } diff --git a/inabox/tests/integration_test.go b/inabox/tests/integration_test.go index 4bfdfa22f..40833926f 100644 --- a/inabox/tests/integration_test.go +++ b/inabox/tests/integration_test.go @@ -12,6 +12,8 @@ import ( rollupbindings "github.com/Layr-Labs/eigenda/contracts/bindings/MockRollup" "github.com/Layr-Labs/eigenda/core/auth" "github.com/Layr-Labs/eigenda/disperser" + "github.com/Layr-Labs/eigenda/disperser/meterer" + "github.com/ethereum/go-ethereum/crypto" "github.com/Layr-Labs/eigenda/encoding/utils/codec" . "github.com/onsi/ginkgo/v2" @@ -36,11 +38,12 @@ var _ = Describe("Inabox Integration", func() { privateKeyHex := "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcded" signer := auth.NewLocalBlobRequestSigner(privateKeyHex) + privateKey, err := crypto.HexToECDSA(privateKeyHex[2:]) // Remove "0x" prefix disp := clients.NewDisperserClient(&clients.Config{ Hostname: "localhost", Port: "32003", Timeout: 10 * time.Second, - }, signer) + }, signer, clients.NewAccountant(meterer.DummyReservation, meterer.DummyOnDemandPayment, 60, meterer.DummyMinimumChargeableSize, meterer.DummyMinimumChargeablePayment, privateKey)) Expect(disp).To(Not(BeNil())) diff --git a/inabox/tests/payment_test.go b/inabox/tests/payment_test.go new file mode 100644 index 000000000..92885bca3 --- /dev/null +++ b/inabox/tests/payment_test.go @@ -0,0 +1,151 @@ +package integration_test + +import ( + "bytes" + "context" + "crypto/rand" + "time" + + "github.com/Layr-Labs/eigenda/api/clients" + disperserpb "github.com/Layr-Labs/eigenda/api/grpc/disperser" + "github.com/Layr-Labs/eigenda/core/auth" + "github.com/Layr-Labs/eigenda/disperser" + "github.com/Layr-Labs/eigenda/disperser/meterer" + "github.com/ethereum/go-ethereum/crypto" + + "github.com/Layr-Labs/eigenda/encoding/utils/codec" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("Inabox Integration", func() { + It("test payment metering", func() { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) + defer cancel() + + gasTipCap, gasFeeCap, err := ethClient.GetLatestGasCaps(ctx) + Expect(err).To(BeNil()) + + privateKeyHex := "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcded" + signer := auth.NewLocalBlobRequestSigner(privateKeyHex) + // Disperser configs: rsv window 60s, min chargeable size 100 bytes, price per chargeable 100, global limit 500 + // -> need to check the mock, can't just use any account for the disperser client, consider using static wallets... + + // say with dataLength of 150 bytes, within a window, we can send 7 blobs with overflow of 50 bytes + // the later requests is then 250 bytes, try send 4 blobs within a second, 2 of them would fail but not charged for + // wait for a second, retry, and that should allow ondemand to work + privateKey, err := crypto.HexToECDSA(privateKeyHex[2:]) // Remove "0x" prefix + Expect(err).To(BeNil()) + disp := clients.NewDisperserClient(&clients.Config{ + Hostname: "localhost", + Port: "32003", + Timeout: 10 * time.Second, + }, signer, clients.NewAccountant(meterer.DummyReservation, meterer.DummyOnDemandPayment, 60, meterer.DummyMinimumChargeableSize, meterer.DummyMinimumChargeablePayment, privateKey)) + + Expect(disp).To(Not(BeNil())) + + singleBlobSize := meterer.DummyMinimumChargeableSize + data := make([]byte, singleBlobSize) + _, err = rand.Read(data) + Expect(err).To(BeNil()) + + paddedData := codec.ConvertByPaddingEmptyByte(data) + + // requests that count towards either reservation or payments + paidBlobStatus := []disperser.BlobStatus{} + paidKeys := [][]byte{} + // TODO: payment calculation unit consistency + for i := 0; i < (int(meterer.DummyReservationBytesLimit)+int(meterer.DummyPaymentLimit))/int(singleBlobSize); i++ { + blobStatus, key, err := disp.PaidDisperseBlob(ctx, paddedData, []uint8{0}) + Expect(err).To(BeNil()) + Expect(key).To(Not(BeNil())) + Expect(blobStatus).To(Not(BeNil())) + Expect(*blobStatus).To(Equal(disperser.Processing)) + paidBlobStatus = append(paidBlobStatus, *blobStatus) + paidKeys = append(paidKeys, key) + } + + // requests that aren't covered by reservation or on-demand payment + blobStatus, key, err := disp.PaidDisperseBlob(ctx, paddedData, []uint8{0}) + Expect(err).To(Not(BeNil())) + Expect(key).To(BeNil()) + Expect(blobStatus).To(BeNil()) + + ticker := time.NewTicker(time.Second * 1) + defer ticker.Stop() + + var replies = make([]*disperserpb.BlobStatusReply, len(paidBlobStatus)) + // now make sure all the paid blobs get confirmed + loop: + for { + select { + case <-ctx.Done(): + Fail("timed out") + case <-ticker.C: + notConfirmed := false + for i, key := range paidKeys { + reply, err := disp.GetBlobStatus(context.Background(), key) + Expect(err).To(BeNil()) + Expect(reply).To(Not(BeNil())) + status, err := disperser.FromBlobStatusProto(reply.GetStatus()) + Expect(err).To(BeNil()) + if *status != disperser.Confirmed { + notConfirmed = true + } + replies[i] = reply + paidBlobStatus[i] = *status + } + + if notConfirmed { + mineAnvilBlocks(numConfirmations + 1) + continue + } + + for _, reply := range replies { + blobHeader := blobHeaderFromProto(reply.GetInfo().GetBlobHeader()) + verificationProof := blobVerificationProofFromProto(reply.GetInfo().GetBlobVerificationProof()) + opts, err := ethClient.GetNoSendTransactOpts() + Expect(err).To(BeNil()) + tx, err := mockRollup.PostCommitment(opts, blobHeader, verificationProof) + Expect(err).To(BeNil()) + tx, err = ethClient.UpdateGas(ctx, tx, nil, gasTipCap, gasFeeCap) + Expect(err).To(BeNil()) + err = ethClient.SendTransaction(ctx, tx) + Expect(err).To(BeNil()) + mineAnvilBlocks(numConfirmations + 1) + _, err = ethClient.EnsureTransactionEvaled(ctx, tx, "PostCommitment") + Expect(err).To(BeNil()) + } + + break loop + } + } + for _, status := range paidBlobStatus { + Expect(status).To(Equal(disperser.Confirmed)) + } + + ctx, cancel = context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + for _, reply := range replies { + retrieved, err := retrievalClient.RetrieveBlob(ctx, + [32]byte(reply.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeaderHash()), + reply.GetInfo().GetBlobVerificationProof().GetBlobIndex(), + uint(reply.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeader().GetReferenceBlockNumber()), + [32]byte(reply.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeader().GetBatchRoot()), + 0, // retrieve blob 1 from quorum 0 + ) + Expect(err).To(BeNil()) + restored := codec.RemoveEmptyByteFromPaddedBytes(retrieved) + Expect(bytes.TrimRight(restored, "\x00")).To(Equal(bytes.TrimRight(data, "\x00"))) + + _, err = retrievalClient.RetrieveBlob(ctx, + [32]byte(reply.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeaderHash()), + reply.GetInfo().GetBlobVerificationProof().GetBlobIndex(), + uint(reply.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeader().GetReferenceBlockNumber()), + [32]byte(reply.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeader().GetBatchRoot()), + 1, // retrieve blob 1 from quorum 1 + ) + Expect(err).NotTo(BeNil()) + } + }) +}) diff --git a/inabox/tests/ratelimit_test.go b/inabox/tests/ratelimit_test.go index 47a93decb..42ee49961 100644 --- a/inabox/tests/ratelimit_test.go +++ b/inabox/tests/ratelimit_test.go @@ -111,7 +111,7 @@ func testRatelimit(t *testing.T, testConfig *deploy.Config, c ratelimitTestCase) Hostname: "localhost", Port: testConfig.Dispersers[0].DISPERSER_SERVER_GRPC_PORT, Timeout: 10 * time.Second, - }, nil) + }, nil, clients.Accountant{}) assert.NotNil(t, disp) data := make([]byte, c.blobSize)