From 664aebd629db03c7470ec771cd50f2a15890779b Mon Sep 17 00:00:00 2001 From: Teja2045 <106052623+Teja2045@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:42:42 +0530 Subject: [PATCH 1/2] feat: add last voting end height (#33) * feat: added transactions * feat: implement client * fix tx issue * feat: pause previous code * adding client injection * custom txclient * fix: client issue debug * new chain client * debug client init * update create client * import mnemonic * docs * Update README.md * update docs * execute submit tx through client * fix keyring issue * import key * fix * refactor * update submitblob tx * new query * feat: changes * handle error * post data to da * execute update tx after da submission * fix * query and tx * update msg * feat: fixed range errors * feat: vote extensions * refactor core lgic * feat: enable vote extensions * feat: enable vote extensions * feat: fix vote extensions bug * feat: fix vote extensions bug * fix: config script for vote extension height * fix typo * fix client * feat: enable vote extensions * remove deadcode * feat: light client data verification * feat: enable light client verification * fix * refactor: review changes * remove unused code * refactor: review changes * refactor: separate params * chore: resolve conflics * chore: conficts * nit: lint fix --------- Co-authored-by: PrathyushaLakkireddy Co-authored-by: Prathyusha Lakkireddy --- go.mod | 2 +- keeper/abci.go | 4 +- keeper/msg_server.go | 4 +- keeper/query_server.go | 10 ++-- keeper/store.go | 16 ++++-- keeper/vote_extension.go | 2 +- keys.go | 4 +- proto/sdk/avail/v1beta1/query.proto | 2 +- types/genesis.pb.go | 23 ++++----- types/query.pb.go | 80 ++++++++++++++--------------- 10 files changed, 80 insertions(+), 67 deletions(-) diff --git a/go.mod b/go.mod index 538c02c..730f2c9 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ require ( cosmossdk.io/log v1.3.1 cosmossdk.io/store v1.1.0 cosmossdk.io/x/upgrade v0.1.4 - github.com/99designs/keyring v1.2.1 github.com/centrifuge/go-substrate-rpc-client/v4 v4.0.12 github.com/cometbft/cometbft v0.38.10 github.com/cosmos/cosmos-proto v1.0.0-beta.5 @@ -31,6 +30,7 @@ require ( ) require ( + github.com/99designs/keyring v1.2.1 // indirect github.com/btcsuite/btcd/btcutil v1.1.5 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/golang/mock v1.6.0 // indirect diff --git a/keeper/abci.go b/keeper/abci.go index b9e84b5..4609866 100644 --- a/keeper/abci.go +++ b/keeper/abci.go @@ -74,7 +74,7 @@ func (h *ProofOfBlobProposalHandler) ProcessProposal(_ sdk.Context, req *abci.Re } func (k *Keeper) PreBlocker(ctx sdk.Context, req *abci.RequestFinalizeBlock) error { - votingEndHeight := k.GetVotingEndHeightFromStore(ctx) + votingEndHeight := k.GetVotingEndHeightFromStore(ctx, false) blobStatus := k.GetBlobStatus(ctx) currentHeight := ctx.BlockHeight() @@ -95,6 +95,8 @@ func (k *Keeper) PreBlocker(ctx sdk.Context, req *abci.RequestFinalizeBlock) err state = ReadyState } + store := ctx.KVStore(k.storeKey) + UpdateVotingEndHeight(ctx, store, 0, false) k.SetBlobStatus(ctx, state) } } diff --git a/keeper/msg_server.go b/keeper/msg_server.go index 0e79f33..81671f8 100644 --- a/keeper/msg_server.go +++ b/keeper/msg_server.go @@ -44,7 +44,9 @@ func (s msgServer) UpdateBlobStatus(ctx context.Context, req *types.MsgUpdateBlo } else { currentHeight := sdkCtx.BlockHeight() UpdateAvailHeight(sdkCtx, store, req.AvailHeight) // updates avail height at which the blocks got submitted to DA - UpdateVotingEndHeight(sdkCtx, store, uint64(currentHeight)+s.k.VotingInterval) + lastVotingEndHeight := s.k.GetVotingEndHeightFromStore(sdkCtx, false) + UpdateVotingEndHeight(sdkCtx, store, uint64(currentHeight)+s.k.VotingInterval, false) + UpdateVotingEndHeight(sdkCtx, store, lastVotingEndHeight, true) } UpdateBlobStatus(sdkCtx, store, newStatus) diff --git a/keeper/query_server.go b/keeper/query_server.go index 654e3ef..6c02a0b 100644 --- a/keeper/query_server.go +++ b/keeper/query_server.go @@ -27,12 +27,12 @@ func (qs queryServer) SubmittedBlobStatus(ctx context.Context, _ *types.QuerySub status := GetStatusFromStore(store) blobStatus := ParseStatus(status) provenHeight := qs.k.GetProvenHeightFromStore(sdkCtx) - votingEndHeight := qs.k.GetVotingEndHeightFromStore(sdkCtx) + votingEndHeight := qs.k.GetVotingEndHeightFromStore(sdkCtx, false) return &types.QuerySubmittedBlobStatusResponse{ - Range: &types.Range{From: startHeight, To: endHeight}, - Status: blobStatus, - ProvenHeight: provenHeight, - LastBlobVotingEndsAt: votingEndHeight, + Range: &types.Range{From: startHeight, To: endHeight}, + Status: blobStatus, + ProvenHeight: provenHeight, + VotingEndsAt: votingEndHeight, }, nil } diff --git a/keeper/store.go b/keeper/store.go index 22733f9..a6fdb2e 100644 --- a/keeper/store.go +++ b/keeper/store.go @@ -79,8 +79,12 @@ func UpdateAvailHeight(_ sdk.Context, store storetypes2.KVStore, availHeight uin return updateHeight(store, availblob1.AvailHeightKey, availHeight) } -func UpdateVotingEndHeight(_ sdk.Context, store storetypes2.KVStore, votingEndHeight uint64) error { - return updateHeight(store, availblob1.VotingEndHeightKey, votingEndHeight) +func UpdateVotingEndHeight(_ sdk.Context, store storetypes2.KVStore, votingEndHeight uint64, isLastVoting bool) error { + key := availblob1.VotingEndHeightKey + if isLastVoting { + key = availblob1.LastVotingEndHeightKey + } + return updateHeight(store, key, votingEndHeight) } func updateHeight(store storetypes2.KVStore, key collections.Prefix, height uint64) error { @@ -100,8 +104,12 @@ func (k *Keeper) GetAvailHeightFromStore(ctx sdk.Context) uint64 { return k.getHeight(ctx, availblob1.AvailHeightKey) } -func (k *Keeper) GetVotingEndHeightFromStore(ctx sdk.Context) uint64 { - return k.getHeight(ctx, availblob1.VotingEndHeightKey) +func (k *Keeper) GetVotingEndHeightFromStore(ctx sdk.Context, isLastVoting bool) uint64 { + key := availblob1.VotingEndHeightKey + if isLastVoting { + key = availblob1.LastVotingEndHeightKey + } + return k.getHeight(ctx, key) } func (k *Keeper) GetStartHeightFromStore(ctx sdk.Context) uint64 { diff --git a/keeper/vote_extension.go b/keeper/vote_extension.go index 10c6ea7..199fcb2 100644 --- a/keeper/vote_extension.go +++ b/keeper/vote_extension.go @@ -45,7 +45,7 @@ func (h *VoteExtHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { blobStatus := h.Keeper.GetBlobStatus(ctx) currentHeight := ctx.BlockHeight() - voteEndHeight := h.Keeper.GetVotingEndHeightFromStore(ctx) + voteEndHeight := h.Keeper.GetVotingEndHeightFromStore(ctx, false) Votes := make(map[string]bool, 1) abciResponseVoteExt := &abci.ResponseExtendVote{} diff --git a/keys.go b/keys.go index 776bf3b..18e8fa3 100644 --- a/keys.go +++ b/keys.go @@ -37,7 +37,9 @@ var ( VotingEndHeightKey = collections.NewPrefix(9) - AvailHeightKey = collections.NewPrefix(10) + LastVotingEndHeightKey = collections.NewPrefix(10) + + AvailHeightKey = collections.NewPrefix(11) ) const ( diff --git a/proto/sdk/avail/v1beta1/query.proto b/proto/sdk/avail/v1beta1/query.proto index 3cc8f87..0805d18 100644 --- a/proto/sdk/avail/v1beta1/query.proto +++ b/proto/sdk/avail/v1beta1/query.proto @@ -18,7 +18,7 @@ message QuerySubmittedBlobStatusResponse { Range range = 1; string status = 2; uint64 proven_height = 3; - uint64 last_blob_voting_ends_at = 4; + uint64 voting_ends_at = 4; } // Query defines the gRPC querier service. diff --git a/types/genesis.pb.go b/types/genesis.pb.go index 72721eb..50c0873 100644 --- a/types/genesis.pb.go +++ b/types/genesis.pb.go @@ -85,23 +85,22 @@ func init() { func init() { proto.RegisterFile("sdk/avail/v1beta1/genesis.proto", fileDescriptor_b83d128538762178) } var fileDescriptor_b83d128538762178 = []byte{ - // 250 bytes of a gzipped FileDescriptorProto + // 239 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2f, 0x4e, 0xc9, 0xd6, 0x4f, 0x2c, 0x4b, 0xcc, 0xcc, 0xd1, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x2c, 0x4e, 0xc9, 0xd6, 0x03, 0x2b, 0xd0, 0x83, 0x2a, 0x90, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xcb, 0xea, 0x83, 0x58, 0x10, 0x85, 0x52, 0x8a, 0x98, 0x26, 0x95, 0x25, 0xe6, 0x64, 0xa6, 0x24, 0x96, 0xe4, 0x17, - 0x41, 0x95, 0xc8, 0x62, 0x2a, 0x29, 0x2c, 0x4d, 0x2d, 0xaa, 0x84, 0x48, 0x2b, 0x95, 0x73, 0xf1, - 0xb8, 0x43, 0xec, 0x0e, 0x2e, 0x49, 0x2c, 0x49, 0x15, 0x72, 0xe2, 0xe2, 0x82, 0x9b, 0x50, 0x2c, - 0xc1, 0xa8, 0xc0, 0xac, 0xc1, 0x6d, 0x24, 0xa3, 0x87, 0xe1, 0x1e, 0xbd, 0x30, 0x98, 0x22, 0x27, - 0x96, 0x13, 0xf7, 0xe4, 0x19, 0x82, 0x90, 0x74, 0x09, 0x29, 0x73, 0xf1, 0x16, 0x14, 0xe5, 0x97, - 0xa5, 0xe6, 0xc5, 0x67, 0xa4, 0x66, 0xa6, 0x67, 0x94, 0x48, 0x30, 0x29, 0x30, 0x6a, 0xb0, 0x04, - 0xf1, 0x40, 0x04, 0x3d, 0xc0, 0x62, 0x4e, 0x8e, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, - 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, - 0xc7, 0x10, 0xa5, 0x9e, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x5f, 0x96, - 0x59, 0x52, 0x9e, 0x59, 0x02, 0x71, 0xbf, 0x6e, 0x4a, 0xa2, 0x6e, 0x6e, 0x7e, 0x4a, 0x69, 0x4e, - 0xaa, 0x7e, 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0xd8, 0x0b, 0xc6, 0x80, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x27, 0x7e, 0xd8, 0xcd, 0x50, 0x01, 0x00, 0x00, + 0x41, 0x94, 0x28, 0x95, 0x73, 0xf1, 0xb8, 0x43, 0x0c, 0x0f, 0x2e, 0x49, 0x2c, 0x49, 0x15, 0x72, + 0xe2, 0xe2, 0x82, 0x2b, 0x29, 0x96, 0x60, 0x54, 0x60, 0xd6, 0xe0, 0x36, 0x92, 0xd1, 0xc3, 0xb0, + 0x50, 0x2f, 0x0c, 0xa6, 0xc8, 0x89, 0xe5, 0xc4, 0x3d, 0x79, 0x86, 0x20, 0x24, 0x5d, 0x42, 0xca, + 0x5c, 0xbc, 0x05, 0x45, 0xf9, 0x65, 0xa9, 0x79, 0xf1, 0x19, 0xa9, 0x99, 0xe9, 0x19, 0x25, 0x12, + 0x4c, 0x0a, 0x8c, 0x1a, 0x2c, 0x41, 0x3c, 0x10, 0x41, 0x0f, 0xb0, 0x98, 0x93, 0xe3, 0x89, 0x47, + 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, + 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0xa9, 0xa7, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, + 0x25, 0xe7, 0xe7, 0xea, 0x97, 0x65, 0x96, 0x94, 0x67, 0x96, 0x40, 0xfc, 0xa0, 0x9b, 0x92, 0xa8, + 0x9b, 0x9b, 0x9f, 0x52, 0x9a, 0x93, 0xaa, 0x5f, 0x52, 0x59, 0x90, 0x5a, 0x9c, 0xc4, 0x06, 0xf6, + 0x82, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x46, 0x1e, 0x50, 0xc0, 0x31, 0x01, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { diff --git a/types/query.pb.go b/types/query.pb.go index 53814ce..db109f8 100644 --- a/types/query.pb.go +++ b/types/query.pb.go @@ -69,10 +69,10 @@ var xxx_messageInfo_QuerySubmittedBlobStatusRequest proto.InternalMessageInfo // query response type QuerySubmittedBlobStatusResponse struct { - Range *Range `protobuf:"bytes,1,opt,name=range,proto3" json:"range,omitempty"` - Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` - ProvenHeight uint64 `protobuf:"varint,3,opt,name=proven_height,json=provenHeight,proto3" json:"proven_height,omitempty"` - LastBlobVotingEndsAt uint64 `protobuf:"varint,4,opt,name=last_blob_voting_ends_at,json=lastBlobVotingEndsAt,proto3" json:"last_blob_voting_ends_at,omitempty"` + Range *Range `protobuf:"bytes,1,opt,name=range,proto3" json:"range,omitempty"` + Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + ProvenHeight uint64 `protobuf:"varint,3,opt,name=proven_height,json=provenHeight,proto3" json:"proven_height,omitempty"` + VotingEndsAt uint64 `protobuf:"varint,4,opt,name=voting_ends_at,json=votingEndsAt,proto3" json:"voting_ends_at,omitempty"` } func (m *QuerySubmittedBlobStatusResponse) Reset() { *m = QuerySubmittedBlobStatusResponse{} } @@ -129,9 +129,9 @@ func (m *QuerySubmittedBlobStatusResponse) GetProvenHeight() uint64 { return 0 } -func (m *QuerySubmittedBlobStatusResponse) GetLastBlobVotingEndsAt() uint64 { +func (m *QuerySubmittedBlobStatusResponse) GetVotingEndsAt() uint64 { if m != nil { - return m.LastBlobVotingEndsAt + return m.VotingEndsAt } return 0 } @@ -144,33 +144,33 @@ func init() { func init() { proto.RegisterFile("sdk/avail/v1beta1/query.proto", fileDescriptor_30ff5d91ce731c68) } var fileDescriptor_30ff5d91ce731c68 = []byte{ - // 413 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0x41, 0x6b, 0xd4, 0x40, - 0x14, 0xc7, 0x77, 0x6a, 0x5b, 0x70, 0xd4, 0x83, 0x63, 0x91, 0x10, 0x34, 0x4d, 0xb7, 0x88, 0x0b, - 0xd2, 0x0c, 0xdd, 0x82, 0xf7, 0x16, 0x04, 0xaf, 0xa6, 0xe0, 0xc1, 0x4b, 0x98, 0x71, 0xc6, 0xd9, - 0xa1, 0xc9, 0xbc, 0x34, 0xf3, 0x12, 0xed, 0xd5, 0x4f, 0x20, 0xf8, 0x31, 0x3c, 0xfb, 0x19, 0xf4, - 0x58, 0xf0, 0xe2, 0x51, 0x76, 0xfd, 0x20, 0x92, 0x49, 0xd0, 0xc3, 0xae, 0x88, 0xb7, 0xcc, 0xfb, - 0xfd, 0xdf, 0x3f, 0xef, 0xff, 0x1e, 0x7d, 0xe8, 0xd5, 0x05, 0x17, 0x9d, 0xb0, 0x25, 0xef, 0x8e, - 0xa5, 0x46, 0x71, 0xcc, 0x2f, 0x5b, 0xdd, 0x5c, 0x65, 0x75, 0x03, 0x08, 0xec, 0xae, 0x57, 0x17, - 0x59, 0xc0, 0xd9, 0x88, 0xe3, 0x3d, 0x03, 0x06, 0x02, 0xe5, 0xfd, 0xd7, 0x20, 0x8c, 0x1f, 0x18, - 0x00, 0x53, 0x6a, 0x2e, 0x6a, 0xcb, 0x85, 0x73, 0x80, 0x02, 0x2d, 0x38, 0x3f, 0xd2, 0x83, 0xf5, - 0xbf, 0x74, 0xa2, 0xb4, 0x4a, 0x20, 0x34, 0xa3, 0x64, 0x7f, 0x34, 0x08, 0x2f, 0xd9, 0xbe, 0xe1, - 0x68, 0x2b, 0xed, 0x51, 0x54, 0xf5, 0x28, 0x88, 0xd7, 0x3d, 0xf0, 0xdd, 0xc0, 0xa6, 0x07, 0x74, - 0xff, 0x45, 0x3f, 0xf5, 0x79, 0x2b, 0x2b, 0x8b, 0xa8, 0xd5, 0x59, 0x09, 0xf2, 0x1c, 0x05, 0xb6, - 0x3e, 0xd7, 0x97, 0xad, 0xf6, 0x38, 0xfd, 0x42, 0x68, 0xfa, 0x77, 0x8d, 0xaf, 0xc1, 0x79, 0xcd, - 0x32, 0xba, 0xd3, 0x08, 0x67, 0x74, 0x44, 0x52, 0x32, 0xbb, 0x35, 0x8f, 0xb2, 0xb5, 0xf8, 0x59, - 0xde, 0xf3, 0x7c, 0x90, 0xb1, 0xfb, 0x74, 0xd7, 0x07, 0x87, 0x68, 0x2b, 0x25, 0xb3, 0x9b, 0xf9, - 0xf8, 0x62, 0x87, 0xf4, 0x4e, 0xdd, 0x40, 0xa7, 0x5d, 0xb1, 0xd0, 0xd6, 0x2c, 0x30, 0xba, 0x91, - 0x92, 0xd9, 0x76, 0x7e, 0x7b, 0x28, 0x3e, 0x0f, 0x35, 0xf6, 0x94, 0x46, 0xa5, 0xf0, 0x58, 0xc8, - 0x12, 0x64, 0xd1, 0x01, 0x5a, 0x67, 0x0a, 0xed, 0x94, 0x2f, 0x04, 0x46, 0xdb, 0x41, 0xbf, 0xd7, - 0xf3, 0x7e, 0xcc, 0x97, 0x81, 0x3e, 0x73, 0xca, 0x9f, 0xe2, 0xfc, 0x33, 0xa1, 0x3b, 0x21, 0x09, - 0xfb, 0x44, 0xe8, 0xbd, 0x0d, 0x71, 0xd8, 0x7c, 0xc3, 0xdc, 0xff, 0xd8, 0x4f, 0x7c, 0xf2, 0x5f, - 0x3d, 0xc3, 0xbe, 0xa6, 0x4f, 0xde, 0x7f, 0xfb, 0xf9, 0x71, 0xeb, 0x11, 0x3b, 0x1c, 0x0e, 0xd3, - 0x27, 0xf9, 0x7d, 0x1c, 0x1f, 0xfa, 0xfe, 0x34, 0x9d, 0x9d, 0x7e, 0x5d, 0x26, 0xe4, 0x7a, 0x99, - 0x90, 0x1f, 0xcb, 0x84, 0x7c, 0x58, 0x25, 0x93, 0xeb, 0x55, 0x32, 0xf9, 0xbe, 0x4a, 0x26, 0xaf, - 0x1e, 0x1b, 0x8b, 0x8b, 0x56, 0x66, 0xaf, 0xa1, 0xe2, 0x9d, 0xc5, 0xb7, 0x16, 0x07, 0xbf, 0x23, - 0x25, 0x8e, 0x2a, 0x50, 0x6d, 0xa9, 0x39, 0x5e, 0xd5, 0xda, 0xcb, 0xdd, 0x70, 0xee, 0x93, 0x5f, - 0x01, 0x00, 0x00, 0xff, 0xff, 0xc3, 0x61, 0x4c, 0xe1, 0xb6, 0x02, 0x00, 0x00, + // 401 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xcf, 0x6e, 0xd4, 0x30, + 0x10, 0xc6, 0xd7, 0xa5, 0xad, 0x84, 0xf9, 0x23, 0x61, 0x10, 0x8a, 0x22, 0x48, 0xd3, 0x2d, 0x88, + 0x95, 0x50, 0x63, 0x75, 0xfb, 0x04, 0xad, 0x84, 0xc4, 0x95, 0xf4, 0xc6, 0x65, 0x65, 0x63, 0xe3, + 0xb5, 0x9a, 0x78, 0xd2, 0x78, 0x12, 0xe8, 0x95, 0x27, 0x40, 0xe2, 0x31, 0x38, 0xf7, 0x1d, 0x38, + 0x56, 0xe2, 0xc2, 0x11, 0xed, 0xf2, 0x20, 0x68, 0xed, 0x08, 0x0e, 0xbb, 0x08, 0xf5, 0x96, 0x99, + 0xef, 0x37, 0x5f, 0x3e, 0xcf, 0xd0, 0xa7, 0x5e, 0x9d, 0x73, 0xd1, 0x0b, 0x5b, 0xf1, 0xfe, 0x48, + 0x6a, 0x14, 0x47, 0xfc, 0xa2, 0xd3, 0xed, 0x65, 0xd1, 0xb4, 0x80, 0xc0, 0x1e, 0x78, 0x75, 0x5e, + 0x04, 0xb9, 0x18, 0xe4, 0xf4, 0x91, 0x01, 0x03, 0x41, 0xe5, 0xab, 0xaf, 0x08, 0xa6, 0x4f, 0x0c, + 0x80, 0xa9, 0x34, 0x17, 0x8d, 0xe5, 0xc2, 0x39, 0x40, 0x81, 0x16, 0x9c, 0x1f, 0xd4, 0xfd, 0xf5, + 0xbf, 0xf4, 0xa2, 0xb2, 0x4a, 0x20, 0xb4, 0x03, 0xb2, 0x37, 0x18, 0x84, 0x4a, 0x76, 0xef, 0x39, + 0xda, 0x5a, 0x7b, 0x14, 0x75, 0x33, 0x00, 0xe9, 0xba, 0x07, 0x7e, 0x8c, 0xda, 0x78, 0x9f, 0xee, + 0xbd, 0x59, 0xa5, 0x3e, 0xeb, 0x64, 0x6d, 0x11, 0xb5, 0x3a, 0xad, 0x40, 0x9e, 0xa1, 0xc0, 0xce, + 0x97, 0xfa, 0xa2, 0xd3, 0x1e, 0xc7, 0x57, 0x84, 0xe6, 0xff, 0x66, 0x7c, 0x03, 0xce, 0x6b, 0x56, + 0xd0, 0x9d, 0x56, 0x38, 0xa3, 0x13, 0x92, 0x93, 0xc9, 0x9d, 0x69, 0x52, 0xac, 0x3d, 0xbf, 0x28, + 0x57, 0x7a, 0x19, 0x31, 0xf6, 0x98, 0xee, 0xfa, 0xe0, 0x90, 0x6c, 0xe5, 0x64, 0x72, 0xbb, 0x1c, + 0x2a, 0x76, 0x40, 0xef, 0x35, 0x2d, 0xf4, 0xda, 0xcd, 0xe6, 0xda, 0x9a, 0x39, 0x26, 0xb7, 0x72, + 0x32, 0xd9, 0x2e, 0xef, 0xc6, 0xe6, 0xeb, 0xd0, 0x63, 0xcf, 0xe8, 0xfd, 0x1e, 0xd0, 0x3a, 0x33, + 0xd3, 0x4e, 0xf9, 0x99, 0xc0, 0x64, 0x3b, 0x52, 0xb1, 0xfb, 0xca, 0x29, 0x7f, 0x82, 0xd3, 0x2b, + 0x42, 0x77, 0x42, 0x6e, 0xf6, 0x95, 0xd0, 0x87, 0x1b, 0xc2, 0xb3, 0xe9, 0x86, 0x94, 0xff, 0xd9, + 0x46, 0x7a, 0x7c, 0xa3, 0x99, 0xb8, 0x9d, 0xf1, 0xcb, 0x4f, 0xdf, 0x7f, 0x7d, 0xd9, 0x7a, 0xce, + 0x0e, 0xe2, 0x19, 0x64, 0x05, 0xf2, 0xcf, 0x29, 0x7c, 0x98, 0xfb, 0x3b, 0x74, 0x7a, 0xf2, 0x6d, + 0x91, 0x91, 0xeb, 0x45, 0x46, 0x7e, 0x2e, 0x32, 0xf2, 0x79, 0x99, 0x8d, 0xae, 0x97, 0xd9, 0xe8, + 0xc7, 0x32, 0x1b, 0xbd, 0x7d, 0x61, 0x2c, 0xce, 0x3b, 0x59, 0xbc, 0x83, 0x9a, 0xf7, 0x16, 0x3f, + 0x58, 0x8c, 0x7e, 0x87, 0x4a, 0x1c, 0xd6, 0xa0, 0xba, 0x4a, 0x73, 0xbc, 0x6c, 0xb4, 0x97, 0xbb, + 0xe1, 0xb8, 0xc7, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xcd, 0x4b, 0xa4, 0x7d, 0xa4, 0x02, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -298,8 +298,8 @@ func (m *QuerySubmittedBlobStatusResponse) MarshalToSizedBuffer(dAtA []byte) (in _ = i var l int _ = l - if m.LastBlobVotingEndsAt != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.LastBlobVotingEndsAt)) + if m.VotingEndsAt != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.VotingEndsAt)) i-- dAtA[i] = 0x20 } @@ -367,8 +367,8 @@ func (m *QuerySubmittedBlobStatusResponse) Size() (n int) { if m.ProvenHeight != 0 { n += 1 + sovQuery(uint64(m.ProvenHeight)) } - if m.LastBlobVotingEndsAt != 0 { - n += 1 + sovQuery(uint64(m.LastBlobVotingEndsAt)) + if m.VotingEndsAt != 0 { + n += 1 + sovQuery(uint64(m.VotingEndsAt)) } return n } @@ -547,9 +547,9 @@ func (m *QuerySubmittedBlobStatusResponse) Unmarshal(dAtA []byte) error { } case 4: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field LastBlobVotingEndsAt", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field VotingEndsAt", wireType) } - m.LastBlobVotingEndsAt = 0 + m.VotingEndsAt = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -559,7 +559,7 @@ func (m *QuerySubmittedBlobStatusResponse) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.LastBlobVotingEndsAt |= uint64(b&0x7F) << shift + m.VotingEndsAt |= uint64(b&0x7F) << shift if b < 0x80 { break } From 6ab8d2be3e4d4b4c099f81296321b9eaa841a3de Mon Sep 17 00:00:00 2001 From: Teja2045 <106052623+Teja2045@users.noreply.github.com> Date: Thu, 19 Sep 2024 11:09:58 +0530 Subject: [PATCH 2/2] docs: add specs (#34) * feat: added transactions * feat: implement client * fix tx issue * feat: pause previous code * adding client injection * custom txclient * fix: client issue debug * new chain client * debug client init * update create client * import mnemonic * docs * Update README.md * update docs * execute submit tx through client * fix keyring issue * import key * fix * refactor * update submitblob tx * new query * feat: changes * handle error * post data to da * execute update tx after da submission * fix * query and tx * update msg * feat: fixed range errors * feat: vote extensions * refactor core lgic * feat: enable vote extensions * feat: enable vote extensions * feat: fix vote extensions bug * feat: fix vote extensions bug * fix: config script for vote extension height * fix typo * fix client * feat: enable vote extensions * remove deadcode * feat: light client data verification * feat: enable light client verification * fix * docs: add specs * feat: docs: add abstract * Update README.md * feat: add specs * feat: spec * feat: update docs * docs: update specs * Update README.md * Update README.md * Update README.md * nit: small changes * chore: conflicts * Update 07_vote_extension.md * docs: add requirements * Update README.md --------- Co-authored-by: PrathyushaLakkireddy Co-authored-by: Prathyusha Lakkireddy --- README.md | 53 ++--------------------- specs/01_concepts.md | 32 ++++++++++++++ specs/02_state.md | 64 +++++++++++++++++++++++++++ specs/03_msg.md | 14 ++++++ specs/04_client.md | 35 +++++++++++++++ specs/05_prepare_proposal.md | 59 +++++++++++++++++++++++++ specs/06_preblocker.md | 83 ++++++++++++++++++++++++++++++++++++ specs/07_vote_extension.md | 81 +++++++++++++++++++++++++++++++++++ specs/README.md | 68 +++++++++++++++++++++++++++++ 9 files changed, 440 insertions(+), 49 deletions(-) create mode 100644 specs/01_concepts.md create mode 100644 specs/02_state.md create mode 100644 specs/03_msg.md create mode 100644 specs/04_client.md create mode 100644 specs/05_prepare_proposal.md create mode 100644 specs/06_preblocker.md create mode 100644 specs/07_vote_extension.md create mode 100644 specs/README.md diff --git a/README.md b/README.md index f90fc06..a123e17 100644 --- a/README.md +++ b/README.md @@ -4,57 +4,12 @@ CADA is a module designed to connect Cosmos sovereign chains with the Avail netw For example: Let blobInterval = 10, + - At height `11`, blocks from `1` to `10` are posted. - At height `21`, blocks from `11` to `20` are posted. -#### Relayer -The `Relayer` acts as the transport layer, responsible for handling requests from the `prepareBlocker` and facilitating transactions between the Cosmos chain and the Avail DA network. It performs key functions such as submitting block data to Avail and updating block status on the Cosmos chain. Every validator in the network is required to run the relayer process. - -#### Proven Height -The `Proven Height` signifies the most recent block height of the Cosmos chain where data has been successfully transmitted to Avail and validated by the network. - -## Architecture - -![Screenshot from 2024-08-27 11-35-01](https://github.com/user-attachments/assets/1a8657f6-4c1b-418a-8295-05c039baa6d0) - - -1. **Block Interval Trigger**: - - At each block interval, a request is sent from `PrepareProposal` abci method to the relayer, specifying the range of block heights to be posted to the Avail DA network. This request should be made by the block proposer only. - -2. **MsgSubmitBlobRequest Transaction**: - - The relayer submits a `MsgSubmitBlobRequest` transaction on the Cosmos chain, signaling that the block data for the specified range is pending: - ``` - status[range] = pending - ``` - - The relayer monitors the transaction to confirm its successful inclusion and processing on the chain. - -3. **Data Submission to Avail DA**: - - Once the `MsgSubmitBlobRequest` transaction is confirmed, the relayer fetches the block data for the specified range and submits it to the Avail DA layer. - -4. **MsgUpdateBlobStatusRequest Transaction**: - - After confirming that the data is available on Avail, the relayer submits a `MsgUpdateBlobStatusRequest` transaction on the Cosmos chain, updating the block status to pre-verification: - ``` - status[range] = IN_VOTING - ``` - -5. **Validator Confirmation**: - - Within a preconfigured block limit, all validators are required to verify the data's availability on the Avail network using their Avail light clients and cast their votes. - - we could use voteExtension to cast the votes - -6. **Consensus and Proven Height Update**: - - If the number of votes exceeds the consensus threshold, the status of the block range is updated to success, and the `Proven Height` is advanced: - ``` - status[range] = success - - // Update the proven height - if range.from == provenHeight + 1 { - provenHeight = range.to - } - ``` +Refer to the module specification available [here](./specs/README.md) for more detailed information. -7. **Failure Handling**: - - In case of any failures or expiration of the verification window, the data will be reposted following the same procedure. +Note: Use the latest maintained [Go](https://go.dev/dl/) version to work with this module. ---- -For detailed instructions on how to integrate the module with a spawn generated application, please refer to the [integration guide](./docs/spawn.md). +Ensure that the Avail light client URL is correctly configured for the module to function as expected. For instructions on running Avail locally, refer to [this documentation](https://github.com/rollkit/avail-da?tab=readme-ov-file#avail-da). diff --git a/specs/01_concepts.md b/specs/01_concepts.md new file mode 100644 index 0000000..dd18f5a --- /dev/null +++ b/specs/01_concepts.md @@ -0,0 +1,32 @@ + + +# Concepts + +### MaxBlocksLimitForBlob + +- The `maxBlocksLimitForBlob` defines the maximum number blobs to be posted to Avail DA at once (in on Avail Transaction). + +### Blob Interval + +- The `Blob Interval` defines the frequency at which block data is posted to the Avail Network. +- For example, if the interval is set to `5`, data will be submitted at block heights `6`, `11`, `16`, and so on. +- At each of these intervals, the block data from the proven height to min(current height, proven height + maxBlocksLimitForBlob) will be posted. + +Example: +For Blob Interval = 5 and Maximum Blocks Limit for Blob = 10 :- + +- At height `6` and provenHeight = `0`, blocks from `1` to `5` are posted. + +- At height `11` and provenHeight still `0`, blocks from `1` to `10` are posted. + +### Relayer + +- The `Relayer` acts as the transport layer, responsible for handling requests from the `preBlocker` and facilitating transactions between the Cosmos chain and the Avail DA network. +- It performs key functions such as submitting block data to Avail and updating block status on the Cosmos chain. Every validator in the network is required to run the relayer process. +- Relayer should initialized with a chain account so that the validator can use this account to sign `MsgUpdateStatusBlob` transaction. + +### Voting Interval + +- The `Voting Interval` is the period before validators verify whether data is truly included in Avail and confirm it with the network using vote extensions. diff --git a/specs/02_state.md b/specs/02_state.md new file mode 100644 index 0000000..4b750fb --- /dev/null +++ b/specs/02_state.md @@ -0,0 +1,64 @@ + + +# State + +The module keeps state of the following primary objects: + +## Blocks Range + +Tracks the start and end of the current blocks range being posted to `Avail`. + +### Blocks Range Start Height + +Stores the start height of the range of current blocks being posted to `Avail`. + +It is stored in the state as follows: + +- PrevHeightKey `0x07` -> Start Height (Uint64) + +### Blocks Range End Height + +Stores the end height of the range of current blocks being posted to `Avail`. + +It is stored in the state as follows: + +- NextHeightKey `0x08` -> End Height (Uint64) + +## Blocks Submission Status + +Indicates the status of the current blocks submission (`READY`, `PENDING`, `IN_VOTING`, `FAILURE`). + +** PENDING ** : Blocks data submission has been initiated and is awaiting confirmation +** IN_VOTING ** : Blocks data has been posted to `Avail` and is now pending validators' verification +** FAILURE ** : Blocks data submission or verification has failed and needs to be resubmitted +** READY ** : blocks data submission is successful; the next set of blocks is ready to be posted + +It is stored in the state as follows: + +- BlobStatusKey `0x06` : status (uint32) + +## Voting End Height + +The block height at which the voting for the current blocks should conclude. + +It is stored in the state as follows: + +- VotingEndHeightKey `0x09` : voting end block height (uint64) + +## Avail Height + +The Avail block height at which the latest blocks data is made available. + +It is stored in the state as follows: + +AvailHeightKey `0x0A` : avail block height (uint64) + +## Proven Height + +The latest block height of the Cosmos chain for which data has been successfully posted to Avail and verified by the network. + +It is stored in the state as follows: + +ProvenHeightKey `0x02` : proven block height (uint64) diff --git a/specs/03_msg.md b/specs/03_msg.md new file mode 100644 index 0000000..248f45d --- /dev/null +++ b/specs/03_msg.md @@ -0,0 +1,14 @@ + + +# Messages + +## UpdateBlobStatus + +The `MsgUpdateBlobStatus` is used to update the status of blocks submission from `PENDING` to either `IN_VOTING` if the submission is successful, or `FAILURE` if it fails. The responsibility for executing this transaction lies with the individual who originally submitted the blocks data to `Avail` (the proposer of the block where the blocks data submission was initiated). + +This message will fail under the following conditions: + + If the status is nil, meaning it is neither true nor false. + If the status is true but the Avail height is not a valid number. \ No newline at end of file diff --git a/specs/04_client.md b/specs/04_client.md new file mode 100644 index 0000000..3d028f5 --- /dev/null +++ b/specs/04_client.md @@ -0,0 +1,35 @@ + + +# Client + +A user can query and interact with the `cada` module using the CLI. + + +## Query + +The `query` commands allows users to query `cada` state. + + +```sh +simd query cada --help +``` + +#### Query the Status +The `get-da-status` command enables users to retrieve comprehensive information, including the range of blocks currently being posted to Avail, the current status, the last proven height, the Avail height where the data is made available, and the voting block height by which voting should conclude. + +```sh +$ simd query cada get-da-status +``` + +Output: + +```yml +last_blob_voting_ends_at: "23" +proven_height: "0" +range: + from: "1" + to: "5" +status: IN_VOTING +``` \ No newline at end of file diff --git a/specs/05_prepare_proposal.md b/specs/05_prepare_proposal.md new file mode 100644 index 0000000..4ad655c --- /dev/null +++ b/specs/05_prepare_proposal.md @@ -0,0 +1,59 @@ + + +# ProofOfBlobProposalHandler: PrepareProposal Method + +This documentation provides an overview of the `PrepareProposal` method within the `ProofOfBlobProposalHandler`. This method is critical for preparing a block proposal by aggregating and injecting vote information into the proposal transactions. + +## Method Overview + +The `PrepareProposal` method performs the following key steps: + +### 1. Proposer Address Initialization + +The method starts by setting the `proposerAddress` in the keeper with the address provided in the `RequestPrepareProposal`. This address represents the proposer of the current block. Since the `PrepareProposal` ABCI method is exclusively executed by the block proposer, this address can later be used for posting block data to `Avail`. + +```go +h.keeper.proposerAddress = req.ProposerAddress +``` + + +### 2. Vote Aggregation + +The method then aggregates votes by calling the `aggregateVotes` function, which takes in the current context and the `LocalLastCommit` from the request. This function collects votes from the last commit, which are essential for the consensus process for da verification. + +```go +votes, err := h.aggregateVotes(ctx, req.LocalLastCommit) +if err != nil { + fmt.Println("error while aggregating votes", err) + return nil, err +} +``` + + + +### 3. Injection of Aggregated Votes + +The method creates a new structure, `StakeWeightedVotes`, to hold the aggregated votes and the extended commit information (`ExtendedCommitInfo`). + +```go +injectedVoteExtTx := StakeWeightedVotes{ + Votes: votes, + ExtendedCommitInfo: req.LocalLastCommit, +} +bz, err := json.Marshal(injectedVoteExtTx) +if err != nil { + fmt.Println("failed to encode injected vote extension tx", "err", err) +} +``` + +The serialized vote information (`injectedVoteExtTx`) is appended to the list of proposal transactions, which can be later processed in `PreBlocker` abci method. + +```go +proposalTxs = append(proposalTxs, bz) + +return &abci.ResponsePrepareProposal{ + Txs: proposalTxs, +}, nil +``` \ No newline at end of file diff --git a/specs/06_preblocker.md b/specs/06_preblocker.md new file mode 100644 index 0000000..1870b1a --- /dev/null +++ b/specs/06_preblocker.md @@ -0,0 +1,83 @@ + + +# ProofOfBlobProposalHandler: PreBlocker Method + +This documentation provides a detailed overview of the `PreBlocker` method within the `ProofOfBlobProposalHandler`. This method is crucial for processing vote extensions, updating statuses, and initiating block data submissions to Avail. + +## Method Overview + +The `PreBlocker` method is responsible for two primary tasks: processing votes from vote extensions to update the status and initiating the submission of blocks' data to Avail. Below is a step-by-step explanation of how this method works. + +### 1. Process Votes from Vote Extensions and Update the Status + +When the current block height matches the voting end height and the status is `IN_VOTING`, the method processes the voting results and updates the state accordingly. + +- **Success Condition:** If the collective voting power exceeds 66%, the status is updated to `READY`, and the `provenHeight` is set to the end of the current block range. +- **Failure Condition:** If the voting power is 66% or less, the status is updated to `FAILURE`. + +```go +if len(req.Txs) > 0 && currentHeight == int64(votingEndHeight) && blobStatus == IN_VOTING_STATE { + var injectedVoteExtTx StakeWeightedVotes + if err := json.Unmarshal(req.Txs[0], &injectedVoteExtTx); err != nil { + fmt.Println("preblocker failed to decode injected vote extension tx", "err", err) + } else { + from := k.GetStartHeightFromStore(ctx) + to := k.GetEndHeightFromStore(ctx) + + pendingRangeKey := Key(from, to) + votingPower := injectedVoteExtTx.Votes[pendingRangeKey] + + if votingPower > 66 { // Voting power is greater than 66% + k.setBlobStatusSuccess(ctx) + } else { + k.SetBlobStatusFailure(ctx) + } + } +} +``` + +### 2. Initiate Block Data Availability (DA) Submission + +If the current block height aligns with a voting interval and the status is either `READY` or `FAILURE`, the method updates the block range and sets the status to `PENDING` for the next round of blocks data submission. + +- **Range Calculation:** The pending block range to be submitted is calculated based on the last proven height and the current block height. +- **Status Update:** The status is set to `PENDING` to mark the start of the data submission process. + +```go +// The following code is executed at block heights that are multiples of the voteInterval, +// i.e., voteInterval+1, 2*voteInterval+1, 3*voteInterval+1, etc. +if !k.IsValidBlockToPostTODA(uint64(currentBlockHeight)) { + return nil +} + +provenHeight := k.GetProvenHeightFromStore(ctx) +fromHeight := provenHeight + 1 // Calculate pending range of blocks to post data +endHeight := min(fromHeight+uint64(k.MaxBlocksForBlob), uint64(ctx.BlockHeight())) // Exclusive range i.e., [fromHeight, endHeight) + +sdkCtx := sdk.UnwrapSDKContext(ctx) +ok := k.SetBlobStatusPending(sdkCtx, fromHeight, endHeight-1) +if !ok { + return nil +} +``` + +### 3. Proposer Submits Block Data to Avail DA + +If the node running this method is the proposer of the block, it takes responsibility for submitting the blocks data to Avail DA. + +- **Block Data Submission:** The proposer gathers the blocks within the calculated range and posts them to Avail DA. + +```go +var blocksToSubmit []int64 + +for i := fromHeight; i < endHeight; i++ { + blocksToSubmit = append(blocksToSubmit, int64(i)) +} + +// Only the proposer should execute the following code +if bytes.Equal(req.ProposerAddress, k.proposerAddress) { + k.relayer.PostBlocks(ctx, blocksToSubmit, k.cdc, req.ProposerAddress) +} +``` \ No newline at end of file diff --git a/specs/07_vote_extension.md b/specs/07_vote_extension.md new file mode 100644 index 0000000..4043aa7 --- /dev/null +++ b/specs/07_vote_extension.md @@ -0,0 +1,81 @@ + + +# Vote Extensions + +Vote extensions are used to propagate arbitrary data across the network without needing to implement transactions that modify the state. Validators utilize vote extensions to verify data availability of a specific range of blocks and update the state of the Cada module accordingly. + +This specification details the functionality and purpose of the `ExtendVoteHandler` and `VerifyVoteExtensionHandler` methods within the VoteExtHandler struct. These methods are part of a voting extension process where validators extend their votes based on the availability of data in the Avail DA network. + +### ExtendVoteHandler + +The `ExtendVoteHandler` method is responsible for generating a `vote extension`. It checks the availability of specific data in the Avail by interacting with an Avail light client. The vote extension is then created based on the outcome of this check. + +* The method first begins by retrieving several voting-related parameters, including the start and end heights of the blocks being processed, the Avail block height, and the status of the current blob (data) + +```go +from := h.Keeper.GetStartHeightFromStore(ctx) + end := h.Keeper.GetEndHeightFromStore(ctx) + + availHeight := h.Keeper.GetAvailHeightFromStore(ctx) + + pendingRangeKey := Key(from, end) + + blobStatus := h.Keeper.GetBlobStatus(ctx) + currentHeight := ctx.BlockHeight() + voteEndHeight := h.Keeper.GetVotingEndHeightFromStore(ctx) +``` + +* The method checks if the current height is just before the end of the voting period and if the blob is in the voting state. If not, it generates a basic vote extension indicating that no data was verified + +```go +if currentHeight+1 != int64(voteEndHeight) || blobStatus != IN_VOTING_STATE { + voteExt := VoteExtension{ + Votes: Votes, + } + + // json marshalling + votesBytes, err := json.Marshal(voteExt) + if err != nil { + return nil, fmt.Errorf("failed to marshal vote extension: %w", err) + } + abciResponseVoteExt.VoteExtension = votesBytes + return abciResponseVoteExt, nil + } +``` + +* If the conditions are met, the method queries the Avail light client to determine if the relevant data is available. The result of this check is recorded in a map +```go + ok, err := h.Keeper.relayer.IsDataAvailable(ctx, from, end, availHeight, "http://localhost:8000") + if ok { + h.logger.Info("submitted data to Avail verified successfully at", + "block_height", availHeight, + ) + } + + + Votes[pendingRangeKey] = ok +``` + +* The outcome (whether the data was available or not) is marshaled into a vote extension and returned as part of the abci.ResponseExtendVote + +```go + voteExt := VoteExtension{ + Votes: Votes, + } + + votesBytes, err := json.Marshal(voteExt) + if err != nil { + return nil, fmt.Errorf("failed to marshal vote extension: %w", err) + } + + return &abci.ResponseExtendVote{ + VoteExtension: votesBytes, + }, nil +``` + +### VerifyVoteExtensionHandler +The `VerifyVoteExtensionHandler` method is responsible for validating the format and content of the vote extensions generated by the `ExtendVoteHandler`. + +This method performs a basic validation check on the received vote extension, ensuring it meets the necessary format requirements. It then returns a response indicating whether the vote extension is accepted. diff --git a/specs/README.md b/specs/README.md new file mode 100644 index 0000000..0563811 --- /dev/null +++ b/specs/README.md @@ -0,0 +1,68 @@ + +# `x/cada` + +## Table of Conetents +- [Abstract](#abstract) +- [Concepts](01_concepts.md#concepts) +- [State](02_state.md#state) +- [Transactions](03_msg.md#messages) +- [Client](04_client.md#client) +- [PrepareProposal Abci method](05_prepare_proposal.md#proofofblobproposalhandler-prepareproposal-method) +- [PreBlocker Abci method](06_preblocker.md#proofofblobproposalhandler-preblocker-method) +- [Vote Extensions](07_vote_extension.md#vote-extensions) +- [Architecture](#architecture) + + +## Abstract + +This document specifies the cada module of the Cosmos SDK. + +CADA is a module designed to connect Cosmos sovereign chains with the Avail network, making it easier for any Cosmos chain or rollapp to use Avail as their Data Availability (DA) layer. With CADA, developers can improve the scalability and security of their decentralized applications within the Cosmos ecosystem. It enables better data handling and availability, allowing Cosmos-based chains to tap into the strengths of Avail and build a more connected and resilient blockchain network. + + + + +## Architecture + +![blocks-data-submission](https://github.com/user-attachments/assets/4e17b98f-ca8c-4b4c-a79e-8c60f123cb2c) + + +- At each block interval, a request is sent from the `PreBlocker` ABCI method to the Keeper, specifying the range of block heights that are ready to be posted to the `Avail` DA network. +- The range of block heights should be from `provenHeight + 1` to `min(provenHeight + MaxBlocksLimitForBlob, CurrentBlockHeight)`. + +- If the status of the previous blocks is either `READY` or `FAILURE`, the status can be updated to `PENDING`. + + ``` + range = [fromBlock, toBlock] // (fromBlock < toBlock < CurrentBlock) + status = PENDING + ``` + +- The `Proposer` of the block will make a request to the `Relayer` to post the blocks data by passing the range of blocks to be posted. + +- The `Relayer` fetches the blocks data from the local provider, converts the blocks data to bytes, and posts that data to `Avail`. + +- Once the success of data availability is confirmed, the `Relayer` broadcasts the `Avail height` at which the blob data is made available using the `MsgUpdateBlobStatus` transaction. + +- The status, Avail height, and voting deadline will be updated in the state. + + ``` + status = IN_VOTING + availHeight = tx.availHeight + votingEndBlock = currentBlock + votingInterval + ``` + +![vote-extension](https://github.com/user-attachments/assets/c0edb8e7-20fd-468a-9109-4f31718e4467) + +- At block height `VotingEndBlock - 1`, all the validators verify if the specified blocks data is truly made available at the specified Avail height. They cast their vote (YES or NO) using `vote extensions`. + +- At block height `VotingEndBlock`, all the votes from `vote_extensions` will be collected and aggregated. If the collective `voting power is > 66%`, the status will be updated + + ``` + status = READY // success and ready for next blocks + provenHeight = Range End + + ``` +- In case of failure at any stage, the whole flow will be repeated. + + +---