From 3c20c31e17bc49c78cd94dfe5b39bdab12281eb2 Mon Sep 17 00:00:00 2001 From: Ian Shim <100327837+ian-shim@users.noreply.github.com> Date: Tue, 27 Feb 2024 10:08:41 -0800 Subject: [PATCH] Fix: Include all batch quorums in batch metadata (#273) --- disperser/apiserver/server.go | 19 ++++-- inabox/tests/integration_test.go | 104 ++++++++++++++++++++----------- 2 files changed, 82 insertions(+), 41 deletions(-) diff --git a/disperser/apiserver/server.go b/disperser/apiserver/server.go index 9d20d04fe8..1022f77d61 100644 --- a/disperser/apiserver/server.go +++ b/disperser/apiserver/server.go @@ -467,13 +467,24 @@ func (s *DispersalServer) GetBlobStatus(ctx context.Context, req *pb.BlobStatusR if isConfirmed { confirmationInfo := metadata.ConfirmationInfo dataLength := uint32(confirmationInfo.BlobCommitment.Length) + quorumResults := confirmationInfo.QuorumResults + batchQuorumIDs := make([]uint8, 0, len(quorumResults)) + for quorumID := range quorumResults { + batchQuorumIDs = append(batchQuorumIDs, quorumID) + } + slices.Sort(batchQuorumIDs) + quorumNumbers := make([]byte, len(batchQuorumIDs)) + quorumPercentSigned := make([]byte, len(batchQuorumIDs)) + for i, quorumID := range batchQuorumIDs { + quorumNumbers[i] = quorumID + quorumPercentSigned[i] = confirmationInfo.QuorumResults[quorumID].PercentSigned + } + quorumInfos := confirmationInfo.BlobQuorumInfos slices.SortStableFunc[[]*core.BlobQuorumInfo](quorumInfos, func(a, b *core.BlobQuorumInfo) int { return int(a.QuorumID) - int(b.QuorumID) }) blobQuorumParams := make([]*pb.BlobQuorumParam, len(quorumInfos)) - quorumNumbers := make([]byte, len(quorumInfos)) - quorumPercentSigned := make([]byte, len(quorumInfos)) quorumIndexes := make([]byte, len(quorumInfos)) for i, quorumInfo := range quorumInfos { blobQuorumParams[i] = &pb.BlobQuorumParam{ @@ -482,9 +493,7 @@ func (s *DispersalServer) GetBlobStatus(ctx context.Context, req *pb.BlobStatusR QuorumThresholdPercentage: uint32(quorumInfo.QuorumThreshold), ChunkLength: uint32(quorumInfo.ChunkLength), } - quorumNumbers[i] = quorumInfo.QuorumID - quorumPercentSigned[i] = confirmationInfo.QuorumResults[quorumInfo.QuorumID].PercentSigned - quorumIndexes[i] = byte(i) + quorumIndexes[i] = byte(slices.Index(quorumNumbers, quorumInfo.QuorumID)) } return &pb.BlobStatusReply{ diff --git a/inabox/tests/integration_test.go b/inabox/tests/integration_test.go index 8531919d47..d81d5140be 100644 --- a/inabox/tests/integration_test.go +++ b/inabox/tests/integration_test.go @@ -61,11 +61,6 @@ var _ = Describe("Inabox Integration", func() { Expect(err).To(BeNil()) blobStatus1, key1, err := disp.DisperseBlob(ctx, data, []*core.SecurityParam{ - { - QuorumID: 0, - AdversaryThreshold: 80, - QuorumThreshold: 100, - }, { QuorumID: 1, AdversaryThreshold: 80, @@ -97,58 +92,95 @@ var _ = Describe("Inabox Integration", func() { ticker := time.NewTicker(time.Second * 1) defer ticker.Stop() - var blobStatus *disperser.BlobStatus - var reply *disperserpb.BlobStatusReply + var reply1 *disperserpb.BlobStatusReply + var reply2 *disperserpb.BlobStatusReply loop: for { select { case <-ctx.Done(): Fail("timed out") case <-ticker.C: - reply, err = disp.GetBlobStatus(context.Background(), key1) + reply1, err = disp.GetBlobStatus(context.Background(), key1) Expect(err).To(BeNil()) - Expect(reply).To(Not(BeNil())) - blobStatus, err = disperser.FromBlobStatusProto(reply.GetStatus()) + Expect(reply1).To(Not(BeNil())) + blobStatus1, err = disperser.FromBlobStatusProto(reply1.GetStatus()) Expect(err).To(BeNil()) - if *blobStatus == disperser.Confirmed { - 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 - } else { + + reply2, err = disp.GetBlobStatus(context.Background(), key2) + Expect(err).To(BeNil()) + Expect(reply2).To(Not(BeNil())) + blobStatus2, err = disperser.FromBlobStatusProto(reply2.GetStatus()) + Expect(err).To(BeNil()) + + if *blobStatus1 != disperser.Confirmed || *blobStatus2 != disperser.Confirmed { mineAnvilBlocks(numConfirmations + 1) + continue } + blobHeader := blobHeaderFromProto(reply1.GetInfo().GetBlobHeader()) + verificationProof := blobVerificationProofFromProto(reply1.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()) + + blobHeader = blobHeaderFromProto(reply2.GetInfo().GetBlobHeader()) + verificationProof = blobVerificationProofFromProto(reply2.GetInfo().GetBlobVerificationProof()) + 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 } } - Expect(*blobStatus).To(Equal(disperser.Confirmed)) + Expect(*blobStatus1).To(Equal(disperser.Confirmed)) + Expect(*blobStatus2).To(Equal(disperser.Confirmed)) ctx, cancel = context.WithTimeout(context.Background(), time.Second*5) defer cancel() + _, err = retrievalClient.RetrieveBlob(ctx, + [32]byte(reply1.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeaderHash()), + reply1.GetInfo().GetBlobVerificationProof().GetBlobIndex(), + uint(reply1.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeader().GetReferenceBlockNumber()), + [32]byte(reply1.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeader().GetBatchRoot()), + 0, // retrieve blob 1 from quorum 0, which should not be available + ) + Expect(err).NotTo(BeNil()) 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 from quorum 0 + [32]byte(reply1.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeaderHash()), + reply1.GetInfo().GetBlobVerificationProof().GetBlobIndex(), + uint(reply1.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeader().GetReferenceBlockNumber()), + [32]byte(reply1.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeader().GetBatchRoot()), + 1, // retrieve blob 1 from quorum 1 ) Expect(err).To(BeNil()) Expect(bytes.TrimRight(retrieved, "\x00")).To(Equal(bytes.TrimRight(data, "\x00"))) 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()), + [32]byte(reply2.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeaderHash()), + reply2.GetInfo().GetBlobVerificationProof().GetBlobIndex(), + uint(reply2.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeader().GetReferenceBlockNumber()), + [32]byte(reply2.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeader().GetBatchRoot()), + 0, // retrieve from quorum 0 + ) + Expect(err).To(BeNil()) + Expect(bytes.TrimRight(retrieved, "\x00")).To(Equal(bytes.TrimRight(data, "\x00"))) + retrieved, err = retrievalClient.RetrieveBlob(ctx, + [32]byte(reply2.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeaderHash()), + reply2.GetInfo().GetBlobVerificationProof().GetBlobIndex(), + uint(reply2.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeader().GetReferenceBlockNumber()), + [32]byte(reply2.GetInfo().GetBlobVerificationProof().GetBatchMetadata().GetBatchHeader().GetBatchRoot()), 1, // retrieve from quorum 1 ) Expect(err).To(BeNil())