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 1, 2020
1 parent d3fba70 commit 654169b
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 3 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.
13 changes: 13 additions & 0 deletions go/consensus/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,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 +249,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 [][]byte `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
26 changes: 26 additions & 0 deletions go/consensus/tendermint/tendermint.go
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,32 @@ func (t *tendermintService) GetTransactions(ctx context.Context, height int64) (
return txs, nil
}

func (t *tendermintService) GetTransactionsWithResults(ctx context.Context, height int64) (*consensusAPI.TransactionsWithResults, error) {
blk, err := t.GetTendermintBlock(ctx, height)
if err != nil {
return nil, err
}
if blk == nil {
return nil, consensusAPI.ErrNoCommittedBlocks
}
results, err := t.GetBlockResults(blk.Height)
if err != nil {
return nil, err
}
var txsWithResults consensusAPI.TransactionsWithResults
for _, tx := range blk.Data.Txs {
txsWithResults.Transactions = append(txsWithResults.Transactions, tx[:])
}
for _, rs := range results.TxsResults {
b, err := rs.Marshal()
if err != nil {
return nil, err
}
txsWithResults.Results = append(txsWithResults.Results, b)
}
return &txsWithResults, nil
}

func (t *tendermintService) GetStatus(ctx context.Context) (*consensusAPI.Status, error) {
status := &consensusAPI.Status{
ConsensusVersion: version.ConsensusProtocol.String(),
Expand Down
17 changes: 15 additions & 2 deletions go/consensus/tests/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
memorySigner "github.com/oasisprotocol/oasis-core/go/common/crypto/signature/signers/memory"
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
"github.com/oasisprotocol/oasis-core/go/consensus/api/transaction"
"github.com/oasisprotocol/oasis-core/go/consensus/tendermint/apps/epochtime_mock"
epochtimemock "github.com/oasisprotocol/oasis-core/go/consensus/tendermint/apps/epochtime_mock"
staking "github.com/oasisprotocol/oasis-core/go/staking/api"
)

Expand Down Expand Up @@ -46,9 +46,22 @@ func ConsensusImplementationTests(t *testing.T, backend consensus.ClientBackend)
require.EqualValues(blk.Height, status.LatestHeight, "latest block heights should match")
require.EqualValues(blk.Hash, status.LatestHash, "latest block hashes should match")

_, err = backend.GetTransactions(ctx, consensus.HeightLatest)
txs, err := backend.GetTransactions(ctx, consensus.HeightLatest)
require.NoError(err, "GetTransactions")

txsWithResults, err := backend.GetTransactionsWithResults(ctx, consensus.HeightLatest)
require.NoError(err, "GetTransactionsWithResults")
require.Len(
txsWithResults.Transactions,
len(txs),
"GetTransactionsWithResults.Transactions length missmatch",
)
require.Len(
txsWithResults.Results,
len(txsWithResults.Transactions),
"GetTransactionsWithResults.Results length missmatch",
)

blockCh, blockSub, err := backend.WatchBlocks(ctx)
require.NoError(err, "WatchBlocks")
defer blockSub.Close()
Expand Down
29 changes: 28 additions & 1 deletion go/oasis-node/cmd/debug/txsource/workload/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,38 @@ func (q *queries) doConsensusQueries(ctx context.Context, rng *rand.Rand, height
}
}

_, err = q.consensus.GetTransactions(ctx, height)
txs, err := q.consensus.GetTransactions(ctx, height)
if err != nil {
return fmt.Errorf("GetTransactions at height %d: %w", height, err)
}

txsWithRes, err := q.consensus.GetTransactionsWithResults(ctx, height)
if err != nil {
return fmt.Errorf("GetTransactionsWithResults at height %d: %w", height, err)
}
if len(txs) != len(txsWithRes.Transactions) {
q.logger.Error("GetTransactionsWithResults transactions length missmatch",
"txs", txs,
"txs_with_results", txsWithRes,
"height", height,
)
return fmt.Errorf(
"GetTransactionsWithResults transactions length missmatch, expected: %d, got: %d",
len(txs), len(txsWithRes.Transactions),
)
}
if len(txsWithRes.Transactions) != len(txsWithRes.Results) {
q.logger.Error("GetTransactionsWithResults results length missmatch",
"txs", txs,
"txs_with_results", txsWithRes,
"height", height,
)
return fmt.Errorf(
"GetTransactionsWithResults results length missmatch, expected: %d, got: %d",
len(txsWithRes.Transactions), len(txsWithRes.Results),
)
}

q.logger.Debug("Consensus queries done",
"height", height,
"epoch", epoch,
Expand Down
5 changes: 5 additions & 0 deletions go/oasis-test-runner/scenario/e2e/early_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ func (sc *earlyQueryImpl) Run(childEnv *env.Env) error {
if !errors.Is(err, consensus.ErrNoCommittedBlocks) {
return fmt.Errorf("GetTransactions query should fail with ErrNoCommittedBlocks (got: %s)", err)
}
// GetTransactionsWithResults.
_, err = cs.GetTransactionsWithResults(ctx, consensus.HeightLatest)
if !errors.Is(err, consensus.ErrNoCommittedBlocks) {
return fmt.Errorf("GetTransactionsWithResults query should fail with ErrNoCommittedBlocks (got: %s)", err)
}

// GetStatus.
status, err := sc.Net.Controller().GetStatus(ctx)
Expand Down

0 comments on commit 654169b

Please sign in to comment.