Begin adding proof calls

This commit is contained in:
Ethan Frey
2017-01-10 15:49:26 +01:00
parent 98c4679f39
commit 58ea995032
14 changed files with 131 additions and 2 deletions

View File

@ -21,6 +21,7 @@ type Client interface {
DeliverTxAsync(tx []byte) *ReqRes
CheckTxAsync(tx []byte) *ReqRes
QueryAsync(tx []byte) *ReqRes
ProofAsync(tx []byte) *ReqRes
CommitAsync() *ReqRes
FlushSync() error
@ -30,6 +31,7 @@ type Client interface {
DeliverTxSync(tx []byte) (res types.Result)
CheckTxSync(tx []byte) (res types.Result)
QuerySync(tx []byte) (res types.Result)
ProofSync(tx []byte) (res types.Result)
CommitSync() (res types.Result)
InitChainAsync(validators []*types.Validator) *ReqRes

View File

@ -182,6 +182,15 @@ func (cli *grpcClient) QueryAsync(query []byte) *ReqRes {
return cli.finishAsyncCall(req, &types.Response{&types.Response_Query{res}})
}
func (cli *grpcClient) ProofAsync(key []byte) *ReqRes {
req := types.ToRequestProof(key)
res, err := cli.client.Proof(context.Background(), req.GetProof(), grpc.FailFast(true))
if err != nil {
cli.StopForError(err)
}
return cli.finishAsyncCall(req, &types.Response{&types.Response_Proof{res}})
}
func (cli *grpcClient) CommitAsync() *ReqRes {
req := types.ToRequestCommit()
res, err := cli.client.Commit(context.Background(), req.GetCommit(), grpc.FailFast(true))
@ -301,6 +310,15 @@ func (cli *grpcClient) CheckTxSync(tx []byte) (res types.Result) {
return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log}
}
func (cli *grpcClient) ProofSync(key []byte) (res types.Result) {
reqres := cli.ProofAsync(key)
if res := cli.checkErrGetResult(); res.IsErr() {
return res
}
resp := reqres.Response.GetProof()
return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log}
}
func (cli *grpcClient) QuerySync(query []byte) (res types.Result) {
reqres := cli.QueryAsync(query)
if res := cli.checkErrGetResult(); res.IsErr() {

View File

@ -99,6 +99,16 @@ func (app *localClient) QueryAsync(tx []byte) *ReqRes {
)
}
func (app *localClient) ProofAsync(key []byte) *ReqRes {
app.mtx.Lock()
res := app.Application.Proof(key)
app.mtx.Unlock()
return app.callback(
types.ToRequestProof(key),
types.ToResponseQuery(res.Code, res.Data, res.Log),
)
}
func (app *localClient) CommitAsync() *ReqRes {
app.mtx.Lock()
res := app.Application.Commit()
@ -192,6 +202,13 @@ func (app *localClient) QuerySync(query []byte) (res types.Result) {
return res
}
func (app *localClient) ProofSync(key []byte) (res types.Result) {
app.mtx.Lock()
res = app.Application.Proof(key)
app.mtx.Unlock()
return res
}
func (app *localClient) CommitSync() (res types.Result) {
app.mtx.Lock()
res = app.Application.Commit()

View File

@ -255,6 +255,10 @@ func (cli *socketClient) QueryAsync(query []byte) *ReqRes {
return cli.queueRequest(types.ToRequestQuery(query))
}
func (cli *socketClient) ProofAsync(key []byte) *ReqRes {
return cli.queueRequest(types.ToRequestProof(key))
}
func (cli *socketClient) CommitAsync() *ReqRes {
return cli.queueRequest(types.ToRequestCommit())
}
@ -345,6 +349,15 @@ func (cli *socketClient) QuerySync(query []byte) (res types.Result) {
return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log}
}
func (cli *socketClient) ProofSync(key []byte) (res types.Result) {
reqres := cli.queueRequest(types.ToRequestProof(key))
cli.FlushSync()
if err := cli.Error(); err != nil {
return types.ErrInternalError.SetLog(err.Error())
}
resp := reqres.Response.GetProof()
return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log}
}
func (cli *socketClient) CommitSync() (res types.Result) {
reqres := cli.queueRequest(types.ToRequestCommit())
cli.FlushSync()
@ -437,6 +450,8 @@ func resMatchesReq(req *types.Request, res *types.Response) (ok bool) {
_, ok = res.Value.(*types.Response_Commit)
case *types.Request_Query:
_, ok = res.Value.(*types.Response_Query)
case *types.Request_Proof:
_, ok = res.Value.(*types.Response_Proof)
case *types.Request_InitChain:
_, ok = res.Value.(*types.Response_InitChain)
case *types.Request_BeginBlock:

View File

@ -131,6 +131,13 @@ func main() {
return cmdQuery(c)
},
},
{
Name: "proof",
Usage: "Get proof for a key",
Action: func(c *cli.Context) error {
return cmdProof(c)
},
},
}
app.Before = before
err := app.Run(os.Args)
@ -305,6 +312,18 @@ func cmdQuery(c *cli.Context) error {
return nil
}
// Prove application state
func cmdProof(c *cli.Context) error {
args := c.Args()
if len(args) != 1 {
return errors.New("Command proof takes 1 argument")
}
keyBytes := stringOrHexToBytes(c.Args()[0])
res := client.ProofSync(keyBytes)
printResponse(c, res, string(res.Data), true)
return nil
}
//--------------------------------------------------------------------------------
func printResponse(c *cli.Context, rsp *response) {

View File

@ -61,6 +61,10 @@ func (app *ChainAwareApplication) Query(query []byte) types.Result {
return types.NewResultOK([]byte(Fmt("%d,%d", app.beginCount, app.endCount)), "")
}
func (app *ChainAwareApplication) Proof(key []byte) types.Result {
return types.NewResultOK(nil, Fmt("Proof is not supported"))
}
func (app *ChainAwareApplication) BeginBlock(hash []byte, header *types.Header) {
app.beginCount += 1
return

View File

@ -83,3 +83,7 @@ func (app *CounterApplication) Query(query []byte) types.Result {
return types.ErrUnknownRequest.SetLog(Fmt("Invalid nonce. Expected hash or tx, got %v", queryStr))
}
func (app *CounterApplication) Proof(key []byte) types.Result {
return types.NewResultOK(nil, Fmt("Proof is not supported"))
}

View File

@ -53,6 +53,10 @@ func (app *DummyApplication) Query(query []byte) types.Result {
return types.NewResultOK(wire.JSONBytes(queryResult), "")
}
func (app *DummyApplication) Proof(key []byte) types.Result {
return types.NewResultOK(nil, Fmt("TODO: support proof!"))
}
type QueryResult struct {
Index int `json:"index"`
Value string `json:"value"`

View File

@ -93,6 +93,10 @@ func (app *PersistentDummyApplication) Query(query []byte) types.Result {
return app.app.Query(query)
}
func (app *PersistentDummyApplication) Proof(key []byte) types.Result {
return types.NewResultOK(nil, Fmt("TODO: support proof!"))
}
// Save the validators in the merkle tree
func (app *PersistentDummyApplication) InitChain(validators []*types.Validator) {
for _, v := range validators {

View File

@ -34,3 +34,7 @@ func (app *NilApplication) Commit() types.Result {
func (app *NilApplication) Query(query []byte) types.Result {
return types.NewResultOK(nil, "")
}
func (app *NilApplication) Proof(key []byte) types.Result {
return types.NewResultOK(nil, "")
}

View File

@ -186,6 +186,9 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types
case *types.Request_Query:
res := s.app.Query(r.Query.Query)
responses <- types.ToResponseQuery(res.Code, res.Data, res.Log)
case *types.Request_Proof:
res := s.app.Proof(r.Proof.Key, r.Proof.Height)
responses <- types.ToResponseProof(res.Code, res.Data, res.Log)
case *types.Request_InitChain:
if app, ok := s.app.(types.BlockchainAware); ok {
app.InitChain(r.InitChain.Validators)

View File

@ -22,6 +22,9 @@ type Application interface {
// Query for state
Query(query []byte) Result
// Get proof for state
Proof(key []byte, blockHeight int) Result
// Return the application Merkle root hash
Commit() Result
}
@ -82,6 +85,11 @@ func (app *GRPCApplication) Query(ctx context.Context, req *RequestQuery) (*Resp
return &ResponseQuery{r.Code, r.Data, r.Log}, nil
}
func (app *GRPCApplication) Proof(ctx context.Context, req *RequestProof) (*ResponseQuery, error) {
r := app.app.Proof(req.Key, req.Height)
return &ResponseProof{r.Code, r.Data, r.Log}, nil
}
func (app *GRPCApplication) Commit(ctx context.Context, req *RequestCommit) (*ResponseCommit, error) {
r := app.app.Commit()
return &ResponseCommit{r.Code, r.Data, r.Log}, nil

View File

@ -55,6 +55,12 @@ func ToRequestQuery(queryBytes []byte) *Request {
}
}
func ToRequestProof(key []byte, blockHeight int) *Request {
return &Request{
Value: &Request_Proof{&RequestProof{key, blockHeight}},
}
}
func ToRequestInitChain(validators []*Validator) *Request {
return &Request{
Value: &Request_InitChain{&RequestInitChain{validators}},
@ -129,6 +135,12 @@ func ToResponseQuery(code CodeType, data []byte, log string) *Response {
}
}
func ToResponseProof(code CodeType, data []byte, log string) *Response {
return &Response{
Value: &Response_Proof{&ResponseProof{code, data, log}},
}
}
func ToResponseInitChain() *Response {
return &Response{
Value: &Response_InitChain{&ResponseInitChain{}},

View File

@ -25,6 +25,7 @@ enum MessageType {
InitChain = 0x15;
BeginBlock = 0x16;
EndBlock = 0x17;
Proof = 0x18;
}
//----------------------------------------
@ -116,6 +117,12 @@ message RequestQuery{
bytes query = 1;
}
message RequestProof{
bytes key = 1;
int64 height = 2;
}
message RequestCommit{
}
@ -150,6 +157,7 @@ message Response {
ResponseInitChain init_chain = 10;
ResponseBeginBlock begin_block = 11;
ResponseEndBlock end_block = 12;
ResponseProof proof = 13;
}
}
@ -193,6 +201,12 @@ message ResponseQuery{
string log = 3;
}
message ResponseProof{
CodeType code = 1;
bytes data = 2;
string log = 3;
}
message ResponseCommit{
CodeType code = 1;
bytes data = 2;
@ -251,6 +265,7 @@ service ABCIApplication {
rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx);
rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx);
rpc Query(RequestQuery) returns (ResponseQuery);
rpc Proof(RequestProof) returns (ResponseProof);
rpc Commit(RequestCommit) returns (ResponseCommit);
rpc InitChain(RequestInitChain) returns (ResponseInitChain);
rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock);