Skip to content

Commit

Permalink
go/consensus/api: Add GetTransactionsWithResults method
Browse files Browse the repository at this point in the history
  • Loading branch information
ptrus committed Jul 6, 2020
1 parent 99e3a69 commit 0e28065
Show file tree
Hide file tree
Showing 18 changed files with 682 additions and 391 deletions.
4 changes: 4 additions & 0 deletions .changelog/3047.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
go/consensus/api: Add `GetTransactionsWithResults` method

`GetTransactionsWithResults` returns a list of transactions and their
execution results, contained within a consensus block at a specific height.
16 changes: 10 additions & 6 deletions go/common/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ import (
"sync"
)

// UnknownModule is the module name used when the module is unknown.
const UnknownModule = "unknown"
const (
// UnknownModule is the module name used when the module is unknown.
UnknownModule = "unknown"

// CodeNoError is the reserved "no error" code.
CodeNoError = 0
)

var errUnknownError = New(UnknownModule, 1, "unknown error")

Expand Down Expand Up @@ -37,11 +42,10 @@ func (e *codedError) Error() string {
// Module and code pair must be unique. If they are not, this method
// will panic.
//
// The error code must not be equal to zero as that value is reserved
// to mean "no error".
// The error code must not be equal to the reserved "no error" code.
func New(module string, code uint32, msg string) error {
if code == 0 {
panic(fmt.Errorf("error: code cannot be zero"))
if code == CodeNoError {
panic(fmt.Errorf("error: code reserved 'no error' code: %d", CodeNoError))
}

e := &codedError{
Expand Down
14 changes: 14 additions & 0 deletions go/consensus/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/oasisprotocol/oasis-core/go/common/node"
"github.com/oasisprotocol/oasis-core/go/common/pubsub"
"github.com/oasisprotocol/oasis-core/go/consensus/api/transaction"
"github.com/oasisprotocol/oasis-core/go/consensus/api/transaction/results"
epochtime "github.com/oasisprotocol/oasis-core/go/epochtime/api"
genesis "github.com/oasisprotocol/oasis-core/go/genesis/api"
keymanager "github.com/oasisprotocol/oasis-core/go/keymanager/api"
Expand Down Expand Up @@ -77,6 +78,11 @@ type ClientBackend interface {
// NOTE: Any of these transactions could be invalid.
GetTransactions(ctx context.Context, height int64) ([][]byte, error)

// GetTransactionsWithResults returns a list of transactions and their
// execution results, contained within a consensus block at a specific
// height.
GetTransactionsWithResults(ctx context.Context, height int64) (*TransactionsWithResults, error)

// WatchBlocks returns a channel that produces a stream of consensus
// blocks as they are being finalized.
WatchBlocks(ctx context.Context) (<-chan *Block, pubsub.ClosableSubscription, error)
Expand Down Expand Up @@ -244,3 +250,11 @@ type GetSignerNonceRequest struct {
AccountAddress staking.Address `json:"account_address"`
Height int64 `json:"height"`
}

// TransactionsWithResults is GetTransactionsWithResults response.
//
// Results[i] are the results of executing Transactions[i].
type TransactionsWithResults struct {
Transactions [][]byte `json:"transactions"`
Results []*results.Result `json:"results"`
}
37 changes: 37 additions & 0 deletions go/consensus/api/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ var (
methodGetBlock = serviceName.NewMethod("GetBlock", int64(0))
// methodGetTransactions is the GetTransactions method.
methodGetTransactions = serviceName.NewMethod("GetTransactions", int64(0))
// methodGetTransactionsWithResults is the GetTransactionsWithResults method.
methodGetTransactionsWithResults = serviceName.NewMethod("GetTransactionsWithResults", int64(0))
// methodGetGenesisDocument is the GetGenesisDocument method.
methodGetGenesisDocument = serviceName.NewMethod("GetGenesisDocument", nil)
// methodGetStatus is the GetStatus method.
Expand Down Expand Up @@ -86,6 +88,10 @@ var (
MethodName: methodGetTransactions.ShortName(),
Handler: handlerGetTransactions,
},
{
MethodName: methodGetTransactionsWithResults.ShortName(),
Handler: handlerGetTransactionsWithResults,
},
{
MethodName: methodGetGenesisDocument.ShortName(),
Handler: handlerGetGenesisDocument,
Expand Down Expand Up @@ -309,6 +315,29 @@ func handlerGetTransactions( // nolint: golint
return interceptor(ctx, height, info, handler)
}

func handlerGetTransactionsWithResults( // nolint: golint
srv interface{},
ctx context.Context,
dec func(interface{}) error,
interceptor grpc.UnaryServerInterceptor,
) (interface{}, error) {
var height int64
if err := dec(&height); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ClientBackend).GetTransactionsWithResults(ctx, height)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: methodGetTransactionsWithResults.FullName(),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClientBackend).GetTransactionsWithResults(ctx, req.(int64))
}
return interceptor(ctx, height, info, handler)
}

func handlerGetGenesisDocument( // nolint: golint
srv interface{},
ctx context.Context,
Expand Down Expand Up @@ -548,6 +577,14 @@ func (c *consensusClient) GetTransactions(ctx context.Context, height int64) ([]
return rsp, nil
}

func (c *consensusClient) GetTransactionsWithResults(ctx context.Context, height int64) (*TransactionsWithResults, error) {
var rsp TransactionsWithResults
if err := c.conn.Invoke(ctx, methodGetTransactionsWithResults.FullName(), height, &rsp); err != nil {
return nil, err
}
return &rsp, nil
}

func (c *consensusClient) GetGenesisDocument(ctx context.Context) (*genesis.Document, error) {
var rsp genesis.Document
if err := c.conn.Invoke(ctx, methodGetGenesisDocument.FullName(), nil, &rsp); err != nil {
Expand Down
34 changes: 34 additions & 0 deletions go/consensus/api/transaction/results/results.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package results

import (
"github.com/oasisprotocol/oasis-core/go/common/errors"
registry "github.com/oasisprotocol/oasis-core/go/registry/api"
roothash "github.com/oasisprotocol/oasis-core/go/roothash/api"
staking "github.com/oasisprotocol/oasis-core/go/staking/api"
)

// Event is a consensus service event that may be emitted during processing of
// a transaction.
type Event struct {
Staking *staking.Event `json:"staking,omitempty"`
Registry *registry.Event `json:"registry,omitempty"`
RootHash *roothash.Event `json:"roothash,omitempty"`
}

// Error is a transaction execution error.
type Error struct {
Module string `json:"module,omitempty"`
Code uint32 `json:"code,omitempty"`
Message string `json:"message,omitempty"`
}

// Result is a transaction execution result.
type Result struct {
Error Error `json:"error"`
Events []*Event `json:"events"`
}

// IsSuccess returns true if transaction execution was successful.
func (r *Result) IsSuccess() bool {
return r.Error.Code == errors.CodeNoError
}
28 changes: 0 additions & 28 deletions go/consensus/tendermint/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
tmtypes "github.com/tendermint/tendermint/types"

"github.com/oasisprotocol/oasis-core/go/common/cbor"
"github.com/oasisprotocol/oasis-core/go/common/crypto/hash"
"github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
"github.com/oasisprotocol/oasis-core/go/common/node"
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
Expand Down Expand Up @@ -131,33 +130,6 @@ func QueryForApp(eventApp string) tmpubsub.Query {
return tmquery.MustParse(fmt.Sprintf("%s EXISTS", EventTypeForApp(eventApp)))
}

// Extend the abci.Event struct with the transaction hash if the event was the result of a
// transaction. Block events have Hash set to the empty hash.
type EventWithHash struct {
types.Event

TxHash hash.Hash
}

// ConvertBlockEvents converts a list of abci.Events to a list of EventWithHashes by setting the
// TxHash of all converted events to the empty hash.
func ConvertBlockEvents(beginBlockEvents []types.Event, endBlockEvents []types.Event) []EventWithHash {
var tmEvents []EventWithHash
for _, bbe := range beginBlockEvents {
var ev EventWithHash
ev.Event = bbe
ev.TxHash.Empty()
tmEvents = append(tmEvents, ev)
}
for _, ebe := range endBlockEvents {
var ev EventWithHash
ev.Event = ebe
ev.TxHash.Empty()
tmEvents = append(tmEvents, ev)
}
return tmEvents
}

// BlockMeta is the Tendermint-specific per-block metadata that is
// exposed via the consensus API.
type BlockMeta struct {
Expand Down
Loading

0 comments on commit 0e28065

Please sign in to comment.