Skip to content

Commit

Permalink
feat: Add Inclusion proofs for QGB verification (#878)
Browse files Browse the repository at this point in the history
* feat: add data root inclusion proofs

* feat: add tx shares and shares inclusion proof partial support

* feat: add rows proofs support

* feat: add rows proofs support and other cosmetics

* doc: update comments and docs

* chore: remove unnecessary test

* chore: remove residual comment

* chore: refactor RowsFromProto

* chore: remove residuel comment

* fix: nolint

* chore: gofumpt

* chore: revert proto new line

* chore: rename TxShares to SharesRange

* feat: add support for querying the message shares that a transaction contain

* chore: regenerate proto

* chore: remove unnecessary custom queries in preparation for a single one to have all the proofs

* feat: use one query to get shares inclusion proofs

* docs: update ProveShares docs

* docs: update ShareInclusionProofQueryPath docs

* docs: update SharesProof docs and regenerate proto

* docs: update Validate docs

* chore: regenerate proto

* fix: fix data root inclusion proof env

* fix: fix data root inclusion proof environment creation

* chore: rename SharesFromProto to SharesProofFromProto as suggested by @evan-forbes

* docs: update docs for validate proof

* fix: execute the proof validation only once instead of many times

* Update types/tx.go

* Update proto/tendermint/types/types.proto

Co-authored-by: Rootul P <[email protected]>

* Update proto/tendermint/types/types.proto

Co-authored-by: Rootul P <[email protected]>

* chore: regenerate proto

* fix: require the user to provide a root to test the shares proof to it

* docs: shares Proof validate docs

* chore: regenrate proto

* chore: rename begin/end block to first/last block

* chore: rename begin/end Query to first/last Query in blocks_test.go

* Update types/tx.go

Co-authored-by: Callum Waters <[email protected]>

* chore: regenerate proto

* chore: format

* Update types/tx.go

* chore: generate proto

* fix: initialize the state store correctly in test data root inclusion proofs

* fix: make the prove data root inclusion proof use the new encoded commitment

Co-authored-by: Rootul P <[email protected]>
Co-authored-by: Callum Waters <[email protected]>
  • Loading branch information
3 people authored Jan 12, 2023
1 parent 536a3aa commit 2d2a65f
Show file tree
Hide file tree
Showing 15 changed files with 1,357 additions and 155 deletions.
59 changes: 39 additions & 20 deletions light/proxy/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,27 @@ func RPCRoutes(c *lrpc.Client) map[string]*rpcserver.RPCFunc {
"unsubscribe_all": rpcserver.NewWSRPCFunc(c.UnsubscribeAllWS, ""),

// info API
"health": rpcserver.NewRPCFunc(makeHealthFunc(c), ""),
"status": rpcserver.NewRPCFunc(makeStatusFunc(c), ""),
"net_info": rpcserver.NewRPCFunc(makeNetInfoFunc(c), ""),
"blockchain": rpcserver.NewRPCFunc(makeBlockchainInfoFunc(c), "minHeight,maxHeight", rpcserver.Cacheable()),
"genesis": rpcserver.NewRPCFunc(makeGenesisFunc(c), "", rpcserver.Cacheable()),
"genesis_chunked": rpcserver.NewRPCFunc(makeGenesisChunkedFunc(c), "", rpcserver.Cacheable()),
"block": rpcserver.NewRPCFunc(makeBlockFunc(c), "height", rpcserver.Cacheable("height")),
"block_by_hash": rpcserver.NewRPCFunc(makeBlockByHashFunc(c), "hash", rpcserver.Cacheable()),
"block_results": rpcserver.NewRPCFunc(makeBlockResultsFunc(c), "height", rpcserver.Cacheable("height")),
"commit": rpcserver.NewRPCFunc(makeCommitFunc(c), "height", rpcserver.Cacheable("height")),
"data_commitment": rpcserver.NewRPCFunc(makeDataCommitmentFunc(c), "beginBlock,endBlock"),
"tx": rpcserver.NewRPCFunc(makeTxFunc(c), "hash,prove", rpcserver.Cacheable()),
"tx_search": rpcserver.NewRPCFunc(makeTxSearchFunc(c), "query,prove,page,per_page,order_by"),
"block_search": rpcserver.NewRPCFunc(makeBlockSearchFunc(c), "query,page,per_page,order_by"),
"validators": rpcserver.NewRPCFunc(makeValidatorsFunc(c), "height,page,per_page", rpcserver.Cacheable("height")),
"dump_consensus_state": rpcserver.NewRPCFunc(makeDumpConsensusStateFunc(c), ""),
"consensus_state": rpcserver.NewRPCFunc(makeConsensusStateFunc(c), ""),
"consensus_params": rpcserver.NewRPCFunc(makeConsensusParamsFunc(c), "height", rpcserver.Cacheable("height")),
"unconfirmed_txs": rpcserver.NewRPCFunc(makeUnconfirmedTxsFunc(c), "limit"),
"num_unconfirmed_txs": rpcserver.NewRPCFunc(makeNumUnconfirmedTxsFunc(c), ""),
"health": rpcserver.NewRPCFunc(makeHealthFunc(c), ""),
"status": rpcserver.NewRPCFunc(makeStatusFunc(c), ""),
"net_info": rpcserver.NewRPCFunc(makeNetInfoFunc(c), ""),
"blockchain": rpcserver.NewRPCFunc(makeBlockchainInfoFunc(c), "minHeight,maxHeight", rpcserver.Cacheable()),
"genesis": rpcserver.NewRPCFunc(makeGenesisFunc(c), "", rpcserver.Cacheable()),
"genesis_chunked": rpcserver.NewRPCFunc(makeGenesisChunkedFunc(c), "", rpcserver.Cacheable()),
"block": rpcserver.NewRPCFunc(makeBlockFunc(c), "height", rpcserver.Cacheable("height")),
"block_by_hash": rpcserver.NewRPCFunc(makeBlockByHashFunc(c), "hash", rpcserver.Cacheable()),
"block_results": rpcserver.NewRPCFunc(makeBlockResultsFunc(c), "height", rpcserver.Cacheable("height")),
"commit": rpcserver.NewRPCFunc(makeCommitFunc(c), "height", rpcserver.Cacheable("height")),
"data_commitment": rpcserver.NewRPCFunc(makeDataCommitmentFunc(c), "beginBlock,endBlock"),
"data_root_inclusion_proof": rpcserver.NewRPCFunc(makeDataRootInclusionProofFunc(c), "height,firstBlock,lastBlock"),
"tx": rpcserver.NewRPCFunc(makeTxFunc(c), "hash,prove", rpcserver.Cacheable()),
"tx_search": rpcserver.NewRPCFunc(makeTxSearchFunc(c), "query,prove,page,per_page,order_by"),
"block_search": rpcserver.NewRPCFunc(makeBlockSearchFunc(c), "query,page,per_page,order_by"),
"validators": rpcserver.NewRPCFunc(makeValidatorsFunc(c), "height,page,per_page", rpcserver.Cacheable("height")),
"dump_consensus_state": rpcserver.NewRPCFunc(makeDumpConsensusStateFunc(c), ""),
"consensus_state": rpcserver.NewRPCFunc(makeConsensusStateFunc(c), ""),
"consensus_params": rpcserver.NewRPCFunc(makeConsensusParamsFunc(c), "height", rpcserver.Cacheable("height")),
"unconfirmed_txs": rpcserver.NewRPCFunc(makeUnconfirmedTxsFunc(c), "limit"),
"num_unconfirmed_txs": rpcserver.NewRPCFunc(makeNumUnconfirmedTxsFunc(c), ""),

// tx broadcast API
"broadcast_tx_commit": rpcserver.NewRPCFunc(makeBroadcastTxCommitFunc(c), "tx"),
Expand Down Expand Up @@ -140,6 +141,13 @@ type rpcDataCommitmentFunc func(
endBlock uint64,
) (*ctypes.ResultDataCommitment, error)

type rpcDataRootInclusionProofFunc func(
ctx *rpctypes.Context,
height uint64,
firstBlock uint64,
lastBlock uint64,
) (*ctypes.ResultDataRootInclusionProof, error)

func makeDataCommitmentFunc(c *lrpc.Client) rpcDataCommitmentFunc {
return func(
ctx *rpctypes.Context,
Expand All @@ -150,6 +158,17 @@ func makeDataCommitmentFunc(c *lrpc.Client) rpcDataCommitmentFunc {
}
}

func makeDataRootInclusionProofFunc(c *lrpc.Client) rpcDataRootInclusionProofFunc {
return func(
ctx *rpctypes.Context,
height uint64,
firstBlock uint64,
lastBlock uint64,
) (*ctypes.ResultDataRootInclusionProof, error) {
return c.DataRootInclusionProof(ctx.Context(), height, firstBlock, lastBlock)
}
}

type rpcTxFunc func(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error)

func makeTxFunc(c *lrpc.Client) rpcTxFunc {
Expand Down
25 changes: 25 additions & 0 deletions light/rpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,18 @@ func (c *Client) DataCommitment(
return c.next.DataCommitment(ctx, beginBlock, endBlock)
}

// DataRootInclusionProof calls rpcclient#DataRootInclusionProof method and returns
// a merkle proof for the data root of block height `height` to the set of blocks
// defined by `firstBlock` and `lastBlock`.
func (c *Client) DataRootInclusionProof(
ctx context.Context,
height uint64,
firstBlock uint64,
lastBlock uint64,
) (*ctypes.ResultDataRootInclusionProof, error) {
return c.next.DataRootInclusionProof(ctx, height, firstBlock, lastBlock)
}

// Tx calls rpcclient#Tx method and then verifies the proof if such was
// requested.
func (c *Client) Tx(ctx context.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
Expand Down Expand Up @@ -491,6 +503,19 @@ func (c *Client) Tx(ctx context.Context, hash []byte, prove bool) (*ctypes.Resul
return res, err
}

// ProveShares calls rpcclient#ProveShares method and returns an NMT proof for a set
// of shares, defined by `startShare` and `endShare`, to the corresponding rows.
// Then, a binary merkle inclusion proof from the latter rows to the data root.
func (c *Client) ProveShares(
ctx context.Context,
height uint64,
startShare uint64,
endShare uint64,
) (types.SharesProof, error) {
res, err := c.next.ProveShares(ctx, height, startShare, endShare)
return res, err
}

func (c *Client) TxSearch(
ctx context.Context,
query string,
Expand Down
4 changes: 4 additions & 0 deletions pkg/consts/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ const (
// index must be formatted into the path.
TxInclusionProofQueryPath = "custom/txInclusionProof/%d"

// ShareInclusionProofQueryPath is the path used to query the application for the
// shares to data root inclusion proofs via the ABCI query method.
ShareInclusionProofQueryPath = "custom/shareInclusionProof/%d/%d"

// ProtoBlobTxTypeID is included in each encoded BlobTx to help prevent
// decoding binaries that are not actually BlobTxs.
ProtoBlobTxTypeID = "BLOB"
Expand Down
Loading

0 comments on commit 2d2a65f

Please sign in to comment.