Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Construction API Tester #81

Merged
merged 93 commits into from
Jul 29, 2020
Merged
Show file tree
Hide file tree
Changes from 84 commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
7611c46
Update rosetta-sdk-go
patrick-ogrady Jul 27, 2020
24adbfd
Migrate to offical Coin type
patrick-ogrady Jul 27, 2020
1b46c25
Add more configuration options
patrick-ogrady Jul 27, 2020
7ac38d0
Update scenario for new coin model
patrick-ogrady Jul 27, 2020
e2f3555
Add ability to randomly get key
patrick-ogrady Jul 27, 2020
2c3c451
First pass at construction loggers
patrick-ogrady Jul 27, 2020
9d9765b
First pass at broadcast storage handler and helper
patrick-ogrady Jul 27, 2020
6db488d
First pass at integration
patrick-ogrady Jul 27, 2020
39921c4
Working on ETH
patrick-ogrady Jul 27, 2020
aade14c
Misc improvements
patrick-ogrady Jul 27, 2020
741e440
Get on the master commit of rosetta-sdk-go
patrick-ogrady Jul 27, 2020
fdc4d34
Rough first pass on change support
patrick-ogrady Jul 27, 2020
6590269
Allow for clearning of pending broadcasts when there is a known error
patrick-ogrady Jul 27, 2020
b1efa54
Test change address population
patrick-ogrady Jul 27, 2020
492484c
Fix sender amount bug on utxo
patrick-ogrady Jul 27, 2020
94d6e5c
Lock on all active addresses
patrick-ogrady Jul 27, 2020
9889c8f
First pass at using balance storage for sender balance
patrick-ogrady Jul 27, 2020
93c39f8
Add example configurations for bitcoin and ethereum
patrick-ogrady Jul 27, 2020
79f8327
Change view:network to view:networks
patrick-ogrady Jul 27, 2020
34376f4
Add comments to tester
patrick-ogrady Jul 27, 2020
ef12901
Fix block broadcast limit bug
patrick-ogrady Jul 27, 2020
d95c8cb
Add interesting only mode to balance storage helper initialization
patrick-ogrady Jul 27, 2020
90f61ad
nits
patrick-ogrady Jul 27, 2020
48bdb70
Fix scientific notation printing
patrick-ogrady Jul 27, 2020
2e7b61e
Add max address option
patrick-ogrady Jul 28, 2020
8ee8f3a
Refactor change to be an operation we can add
patrick-ogrady Jul 28, 2020
1fd1e6b
Cleanup construction amount code prior to testing
patrick-ogrady Jul 28, 2020
4137d57
Add assertions for created transfers
patrick-ogrady Jul 28, 2020
0b564b8
Cleanup logging code
patrick-ogrady Jul 28, 2020
308cf00
pseudo code for core loop refactor
patrick-ogrady Jul 28, 2020
79b4a2d
making progress on refactor
patrick-ogrady Jul 28, 2020
22eb4e6
First pass at refactor
patrick-ogrady Jul 28, 2020
3e8d292
Keep cleaning
patrick-ogrady Jul 28, 2020
37d3804
Continue cleaning
patrick-ogrady Jul 28, 2020
29887a4
Working on ETH
patrick-ogrady Jul 28, 2020
ef3fd2f
Update gitignore
patrick-ogrady Jul 28, 2020
4f41136
Add comments
patrick-ogrady Jul 28, 2020
0c51b16
Cleanup distinction between public and private functions
patrick-ogrady Jul 28, 2020
e340260
Remove functions from main loop
patrick-ogrady Jul 28, 2020
b7247d5
Fix copier
patrick-ogrady Jul 28, 2020
d76c397
Add a default configuration file
patrick-ogrady Jul 28, 2020
f85cbc0
Nits
patrick-ogrady Jul 28, 2020
73dc626
Break out common functions to utils
patrick-ogrady Jul 28, 2020
c701b0e
Move log scenario to logger
patrick-ogrady Jul 28, 2020
6f76f1f
Reorganize construction test file
patrick-ogrady Jul 28, 2020
3d33a7f
Start utils tests
patrick-ogrady Jul 28, 2020
1726abb
Move concurrency to base config
patrick-ogrady Jul 28, 2020
22ac254
Change tip definition to be time based
patrick-ogrady Jul 28, 2020
e48bc95
Add more utils tests
patrick-ogrady Jul 28, 2020
41acbc1
Start constructor refactor
patrick-ogrady Jul 28, 2020
c98f1f0
Constructor refactor with no comments
patrick-ogrady Jul 28, 2020
4b9623f
Create constructors
patrick-ogrady Jul 28, 2020
7937273
Add CreateTransactions
patrick-ogrady Jul 28, 2020
15d068b
Constructor refactor complete, now tests
patrick-ogrady Jul 28, 2020
bd4ff10
Make mocks
patrick-ogrady Jul 28, 2020
a0a9e57
Happy path address working with mocks!!
patrick-ogrady Jul 29, 2020
d210692
Test createTransaction
patrick-ogrady Jul 29, 2020
7879fb2
Add tests for minimum required balance
patrick-ogrady Jul 29, 2020
2dd45cb
Test TestBestUnlockedSender_Account
patrick-ogrady Jul 29, 2020
955afb1
Add test for best unlocked sender utxo
patrick-ogrady Jul 29, 2020
17d7ecc
Test find recipients for account
patrick-ogrady Jul 29, 2020
7051397
Add find recipients test for UTXO
patrick-ogrady Jul 29, 2020
6d7e9c2
Add test for create scenario context
patrick-ogrady Jul 29, 2020
9ce6993
Add test for canGetNewAddress
patrick-ogrady Jul 29, 2020
2102b3c
clarify where to run coverage
patrick-ogrady Jul 29, 2020
ad76de8
Test failure of GenerateScenario_Account
patrick-ogrady Jul 29, 2020
aeebed4
Basic account transfer with new account
patrick-ogrady Jul 29, 2020
2969d83
Test many cases with account send
patrick-ogrady Jul 29, 2020
aa239f3
Basic fullsend test
patrick-ogrady Jul 29, 2020
b13b8e3
UTXO no change testing covered
patrick-ogrady Jul 29, 2020
1b5be76
Insufficient funds on UTXO
patrick-ogrady Jul 29, 2020
8210de7
First change test
patrick-ogrady Jul 29, 2020
4b37db1
Change tests in UTXO
patrick-ogrady Jul 29, 2020
0ae6ef5
Add coverage for find sender
patrick-ogrady Jul 29, 2020
2e43d04
nits
patrick-ogrady Jul 29, 2020
15a1e34
Write initial funds load test
patrick-ogrady Jul 29, 2020
6a13925
Fix linter
patrick-ogrady Jul 29, 2020
217a2c8
Add missing comments
patrick-ogrady Jul 29, 2020
36a2219
Remove unnecessary logic from helper
patrick-ogrady Jul 29, 2020
ae476aa
use unix nano for source
patrick-ogrady Jul 29, 2020
59593de
fix config key
patrick-ogrady Jul 29, 2020
b8f2296
Error if unknown fields in file
patrick-ogrady Jul 29, 2020
23dfa05
Update README
patrick-ogrady Jul 29, 2020
d24a66c
nits
patrick-ogrady Jul 29, 2020
be35d7c
Change confirmation depth behavior to match bitcoin
patrick-ogrady Jul 29, 2020
801ff18
Broadcast as soon as recieve
patrick-ogrady Jul 29, 2020
6e2ccba
nits
patrick-ogrady Jul 29, 2020
6a4e24f
Add better error logging when network not supported
patrick-ogrady Jul 29, 2020
eed3970
Ensure found block is returned not confirmed block in broadcast handler
patrick-ogrady Jul 29, 2020
ea8afcc
Fix stale depth calculation
patrick-ogrady Jul 29, 2020
598dd31
nits
patrick-ogrady Jul 29, 2020
1856b2f
Fix reconciler regression
patrick-ogrady Jul 29, 2020
ec5dccd
Find transactions in context of block addition transaction
patrick-ogrady Jul 29, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
validator-data
rosetta-cli
bootstrap_balances.csv
13 changes: 11 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.PHONY: deps lint format check-format test test-cover add-license \
check-license shorten-lines salus validate watch-blocks \
watch-transactions watch-balances watch-reconciliations \
view-block-benchmarks view-account-benchmarks
view-block-benchmarks view-account-benchmarks mocks

# To run the the following packages as commands,
# it is necessary to use `go run <pkg>`. Running `go get` does
Expand All @@ -11,7 +11,12 @@ ADDLICENSE_CMD=go run github.com/google/addlicense
ADDLICENCE_SCRIPT=${ADDLICENSE_CMD} -c "Coinbase, Inc." -l "apache" -v
GOLINES_CMD=go run github.com/segmentio/golines
GOVERALLS_CMD=go run github.com/mattn/goveralls
COVERAGE_TEST_DIRECTORIES=./configuration/... ./internal/constructor/... \
./internal/logger/... ./internal/scenario/... \
patrick-ogrady marked this conversation as resolved.
Show resolved Hide resolved
./internal/statefulsyncer/... ./internal/storage/... \
./internal/tester/... ./internal/utils/...
TEST_SCRIPT=go test -v ./internal/... ./configuration/...
COVERAGE_TEST_SCRIPT=go test -v ${COVERAGE_TEST_DIRECTORIES}

deps:
go get ./...
Expand All @@ -30,7 +35,7 @@ test:
${TEST_SCRIPT}

test-cover:
if [ "${COVERALLS_TOKEN}" ]; then ${TEST_SCRIPT} -coverprofile=c.out -covermode=count; ${GOVERALLS_CMD} -coverprofile=c.out -repotoken ${COVERALLS_TOKEN}; fi
if [ "${COVERALLS_TOKEN}" ]; then ${COVERAGE_TEST_SCRIPT} -coverprofile=c.out -covermode=count; ${GOVERALLS_CMD} -coverprofile=c.out -repotoken ${COVERALLS_TOKEN}; fi

add-license:
${ADDLICENCE_SCRIPT} .
Expand All @@ -51,3 +56,7 @@ build:

install:
go install ./...

mocks:
rm -rf mocks;
mockery --dir internal/constructor --all --case underscore --outpkg constructor --output mocks/constructor;
106 changes: 94 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Available Commands:
version Print rosetta-cli version
view:account View an account balance
view:block View a block
view:network View network status
view:networks View all network statuses

Flags:
--configuration-file string Configuration file that provides connection and test settings.
Expand All @@ -64,7 +64,36 @@ Flags:
Use "rosetta-cli [command] --help" for more information about a command.
```

### version
### Configuration
All `rosetta-cli` parameters are populated from a configuration file (`--configuration-file`)
provided at runtime. If a configuration file is not provided, the default
configuration is used. This default configuration can be viewed
[here](examples/configuration/default.json).

In the `examples/configuration` directory, you can find examples configuration
files for running tests against a Bitcoin Rosetta implementation
([config](examples/configuration/bitcoin.json)) and an Ethereum Rosetta
implementation ([config](examples/configuration/ethereum.json)).

#### Disable Complex Checks
If you are just getting started with your implementation, you may want
to disable balance tracking (did any address balance go below zero?) and
reconciliation (does the balance I calculated match the balance returned
by the `/account/balance` endpoint?). Take a look at the
[simple configuration](examples/configuration/simple.json) for an example of
how to do this.

#### Future Work
In the near future, we will add support for providing complex exit conditions
(i.e. did we reach tip? did we reconcile every account?) for both
`check:construction` and `check:data` so that the `rosetta-cli`
can be integrated into a CI flow. Currently, the only way to exit with a
successful status in the `rosetta-cli` is to provide an `--end` flag
when running `check:data` (returns 0 if no errors up to a block index
are observed).

### Commands
#### version
```
Print rosetta-cli version

Expand All @@ -83,7 +112,7 @@ Global Flags:
default values.
```

### check:data
#### check:data
```
Check all server responses are properly constructed, that
there are no duplicate blocks and transactions, that blocks can be processed
Expand Down Expand Up @@ -137,14 +166,29 @@ Global Flags:
default values.
```

#### Status Codes
##### Status Codes
If there are no issues found while running `check`, it will exit with a `0` status code.
If there are any issues, it will exit with a `1` status code. It can be useful
to run this command as an integration test for any changes to your implementation.

### configuration:create
#### check:construction
```
Check the correctness of a Rosetta Construction API Implementation
The check:construction command runs an automated test of a
Construction API implementation by creating and broadcasting transactions
on a blockchain. In short, this tool generates new addresses, requests
funds, constructs transactions, signs transactions, broadcasts transactions,
and confirms transactions land on-chain. At each phase, a series of tests
are run to ensure that intermediate representations are correct (i.e. does
an unsigned transaction return a superset of operations provided during
construction?).

Check out the https://github.com/coinbase/rosetta-cli/tree/master/examples
directory for examples of how to configure this test for Bitcoin and
Ethereum.

Right now, this tool only supports transfer testing (for both account-based
and UTXO-based blockchains). However, we plan to add support for testing
arbitrary scenarios (i.e. staking, governance).

Usage:
rosetta-cli check:construction [flags]
Expand All @@ -161,7 +205,45 @@ Global Flags:
default values.
```

### view:network
#### configuration:create
```
Create a default configuration file at the provided path

Usage:
rosetta-cli configuration:create [flags]

Flags:
-h, --help help for configuration:create

Global Flags:
--configuration-file string Configuration file that provides connection and test settings.
If you would like to generate a starter configuration file (populated
with the defaults), run rosetta-cli configuration:create.

Any fields not populated in the configuration file will be populated with
default values.
```

#### configuration:validate
```
Validate the correctness of a configuration file at the provided path

Usage:
rosetta-cli configuration:validate [flags]

Flags:
-h, --help help for configuration:validate

Global Flags:
--configuration-file string Configuration file that provides connection and test settings.
If you would like to generate a starter configuration file (populated
with the defaults), run rosetta-cli configuration:create.

Any fields not populated in the configuration file will be populated with
default values.
```

#### view:networks
```
While debugging a Data API implementation, it can be very
useful to view network(s) status. This command fetches the network
Expand All @@ -171,10 +253,10 @@ If this command errors, it is likely because the /network/* endpoints are
not formatted correctly.

Usage:
rosetta-cli view:network [flags]
rosetta-cli view:networks [flags]

Flags:
-h, --help help for view:network
-h, --help help for view:networks

Global Flags:
--configuration-file string Configuration file that provides connection and test settings.
Expand All @@ -185,7 +267,7 @@ Global Flags:
default values.
```

### view:account
#### view:account
```
While debugging, it is often useful to inspect the state
of an account at a certain block. This command allows you to look up
Expand All @@ -211,7 +293,7 @@ Global Flags:
default values.
```

### view:block
#### view:block
```
While debugging a Data API implementation, it can be very
useful to inspect block contents. This command allows you to fetch any
Expand All @@ -238,7 +320,7 @@ Global Flags:
default values.
```

### utils:asserter-configuration
#### utils:asserter-configuration
```
In production deployments, it is useful to initialize the response
Asserter (https://github.com/coinbase/rosetta-sdk-go/tree/master/asserter) using
Expand Down
97 changes: 94 additions & 3 deletions cmd/check_construction.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,111 @@
package cmd

import (
"context"
"log"
"os"
"time"

"github.com/coinbase/rosetta-cli/internal/tester"
"github.com/coinbase/rosetta-cli/internal/utils"

"github.com/coinbase/rosetta-sdk-go/fetcher"
"github.com/fatih/color"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
)

var (
checkConstructionCmd = &cobra.Command{
Use: "check:construction",
Short: "Check the correctness of a Rosetta Construction API Implementation",
Run: runCheckConstructionCmd,
Long: `The check:construction command runs an automated test of a
Construction API implementation by creating and broadcasting transactions
on a blockchain. In short, this tool generates new addresses, requests
funds, constructs transactions, signs transactions, broadcasts transactions,
and confirms transactions land on-chain. At each phase, a series of tests
are run to ensure that intermediate representations are correct (i.e. does
an unsigned transaction return a superset of operations provided during
construction?).

Check out the https://github.com/coinbase/rosetta-cli/tree/master/examples
directory for examples of how to configure this test for Bitcoin and
Ethereum.

Right now, this tool only supports transfer testing (for both account-based
and UTXO-based blockchains). However, we plan to add support for testing
arbitrary scenarios (i.e. staking, governance).`,
Run: runCheckConstructionCmd,
}
)

func runCheckConstructionCmd(cmd *cobra.Command, args []string) {
// ensureDataDirectoryExists()
log.Fatal("not implemented!")
ensureDataDirectoryExists()
ctx, cancel := context.WithCancel(context.Background())

fetcher := fetcher.New(
Config.OnlineURL,
fetcher.WithBlockConcurrency(Config.BlockConcurrency),
fetcher.WithTransactionConcurrency(Config.TransactionConcurrency),
fetcher.WithRetryElapsedTime(ExtendedRetryElapsedTime),
fetcher.WithTimeout(time.Duration(Config.HTTPTimeout)*time.Second),
)

_, _, err := fetcher.InitializeAsserter(ctx)
if err != nil {
log.Fatalf("%s: unable to initialize asserter", err.Error())
}

_, err = utils.CheckNetworkSupported(ctx, Config.Network, fetcher)
if err != nil {
log.Fatalf("%s: unable to confirm network is supported", err.Error())
}

constructionTester, err := tester.InitializeConstruction(
ctx,
Config,
Config.Network,
fetcher,
cancel,
)
if err != nil {
log.Fatalf("%s: unable to initialize construction tester", err.Error())
}

defer constructionTester.CloseDatabase(ctx)

if err := constructionTester.PerformBroadcasts(ctx); err != nil {
log.Fatalf("%s: unable to perform broadcasts", err.Error())
}

g, ctx := errgroup.WithContext(ctx)
g.Go(func() error {
return constructionTester.StartPeriodicLogger(ctx)
})

g.Go(func() error {
return constructionTester.StartSyncer(ctx, cancel)
})

g.Go(func() error {
return constructionTester.StartConstructor(ctx)
})

sigListeners := []context.CancelFunc{cancel}
go handleSignals(sigListeners)

err = g.Wait()
if SignalReceived {
color.Red("Check halted")
os.Exit(1)
return
}

if err != nil {
color.Red("Check failed: %s", err.Error())
os.Exit(1)
}

// Will only hit this once exit conditions are added
color.Green("Check succeeded")
}
5 changes: 2 additions & 3 deletions cmd/check_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ func runCheckDataCmd(cmd *cobra.Command, args []string) {

fetcher := fetcher.New(
Config.OnlineURL,
fetcher.WithBlockConcurrency(Config.Data.BlockConcurrency),
fetcher.WithTransactionConcurrency(Config.Data.TransactionConcurrency),
fetcher.WithBlockConcurrency(Config.BlockConcurrency),
fetcher.WithTransactionConcurrency(Config.TransactionConcurrency),
fetcher.WithRetryElapsedTime(ExtendedRetryElapsedTime),
fetcher.WithTimeout(time.Duration(Config.HTTPTimeout)*time.Second),
)
Expand Down Expand Up @@ -126,7 +126,6 @@ func runCheckDataCmd(cmd *cobra.Command, args []string) {
defer dataTester.CloseDatabase(ctx)

g, ctx := errgroup.WithContext(ctx)

g.Go(func() error {
return dataTester.StartPeriodicLogger(ctx)
})
Expand Down
4 changes: 2 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ default values.`,
// View Commands
rootCmd.AddCommand(viewBlockCmd)
rootCmd.AddCommand(viewAccountCmd)
rootCmd.AddCommand(viewNetworkCmd)
rootCmd.AddCommand(viewNetworksCmd)

// Utils
rootCmd.AddCommand(utilsAsserterConfigurationCmd)
Expand Down Expand Up @@ -142,6 +142,6 @@ var versionCmd = &cobra.Command{
Use: "version",
Short: "Print rosetta-cli version",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("v0.3.2")
fmt.Println("v0.4.0")
},
}
3 changes: 2 additions & 1 deletion cmd/view_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func runViewAccountCmd(cmd *cobra.Command, args []string) {
lookupBlock = &types.PartialBlockIdentifier{Index: &index}
}

block, amounts, metadata, err := newFetcher.AccountBalanceRetry(
block, amounts, coins, metadata, err := newFetcher.AccountBalanceRetry(
ctx,
Config.Network,
account,
Expand All @@ -98,6 +98,7 @@ func runViewAccountCmd(cmd *cobra.Command, args []string) {
}

log.Printf("Amounts: %s\n", types.PrettyPrintStruct(amounts))
log.Printf("Coins: %s\n", types.PrettyPrintStruct(coins))
log.Printf("Metadata: %s\n", types.PrettyPrintStruct(metadata))
log.Printf("Balance Fetched At: %s\n", types.PrettyPrintStruct(block))
}
Loading