The hardware walllet daemon provides an HTTP API to interface with the wallets supported by skycoin. It uses the go bindings provided by the hardware wallet go library.
Hardware Daemon supports go1.10+.
Golang 1.10+ Installation/Setup
The API has two modes:
You can use the -daemon-mode
flag to enable the required mode or use the make
commands.
Example(USB Mode):
$ cd $GOPATH/src/github.com/skycoin/hardware-wallet-daemon
$ make run-usb
Example(Emulator Mode):
$ cd $GOPATH/src/github.com/skycoin/hardware-wallet-daemon
$ make run-emulator
$ cd $GOPATH/src/github.com/skycoin/hardware-wallet-daemon
$ make run-help
Code added in this repository should comply to development guidelines documented in Skycoin wiki.
The project has two branches: master
and develop
.
develop
is the default branch and will always have the latest code.master
will always be equal to the current stable release on the website, and should correspond with the latest release tag.Hardware wallet daemon uses swagger for the API specification. It follows OpenAPI 2.0.
The go client has been automatically generated using go-swagger and the swagger specification.
Note: The go client uses a slightly modified response template.
The swagger specification can be used to generate more libraries in the required language.
Library test suite can be run by running the following command
$ make test
There are integration tests for the HTTP API interfaces. They have two run modes, "wallet" and "emulator".
The emulator
integration tests are run only when an emulator is running.
The wallet
integration tests are run only when a physical skycoin hardware wallet is connected.
$ make test-integration-emulator
or
$ ./ci-scripts/integration-test.sh -m emulator -v
The -m emulator
option, runs emulator integration tests.
The -v
option, shows verbose logs.
$ make test-integration-wallet
or
$ ./ci-scripts/integration-test.sh -m wallet -v
The -m wallet
option, runs wallet integration tests.
The -v
option, shows verbose logs.
Run specific test case:
It's annoying and a waste of time to run all tests to see if the test we real care
is working correctly. There's an option: -r
, which can be used to run specific test case.
For example: if we only want to test TestEmulatorFeatures
and see the result, we can run:
$ ./ci-scripts/integration-test.sh -m emulator -v -r TestEmulatorFeatures
Golden files are expected data responses from the HTTP API saved to disk. When some of the tests are run, their output is compared to the golden files.
To update golden files, use the provided make
command:
Wallet
$ make DEVICE_TYPE=USB update-golden-files
EMULATOR
$ make DEVICE_TYPE=USB update-golden-files
We can also update a specific test case's golden file with the -r
option.
For example:
$ ./ci-scripts/integration-test.sh -m emulator -v -u -r TestEmulatorFeatures
Coverage is automatically generated for make test
and integration tests run against a stable node.
This includes integration test coverage. The coverage output files are placed in coverage/
.
To merge coverage from all tests into a single HTML file for viewing:
$ make check
$ make merge-coverage
Then open coverage/all-coverage.html
in the browser.
All .go
source files should be formatted goimports
. You can do this with:
$ make format
Install prerequisites:
$ make install-linters
Run linters:
$ make lint
A full CPU profile of the program from start to finish can be obtained by running the node with the -profile-cpu
flag.
Once the node terminates, a profile file is written to -profile-cpu-file
(defaults to cpu.prof
).
This profile can be analyzed with
go tool pprof cpu.prof
The HTTP interface for obtaining more profiling data or obtaining data while running can be enabled with -http-prof
.
The HTTP profiling interface can be controlled with -http-prof-host
and listens on localhost:6060
by default.
See https://golang.org/pkg/net/http/pprof/ for guidance on using the HTTP profiler.
Some useful examples include:
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=10
go tool pprof http://localhost:6060/debug/pprof/heap
A web page interface is provided by http/pprof at http://localhost:6060/debug/pprof/.
Dependencies are managed with dep.
To install dep
for development:
go get -u github.com/golang/dep/cmd/dep
dep
vendors all dependencies into the repo.
If you change the dependencies, you should update them as needed with dep ensure
.
Use dep help
for instructions on vendoring a specific version of a dependency, or updating them.
When updating or initializing, dep
will find the latest version of a dependency that will compile.
Examples:
Initialize all dependencies:
dep init
Update all dependencies:
dep ensure -update -v
Add a single dependency (latest version):
dep ensure github.com/foo/bar
Add a single dependency (more specific version), or downgrade an existing dependency:
dep ensure github.com/foo/bar@tag
master
branch has commits that are not in develop
(e.g. due to a hotfix applied to master
), merge master
into develop
(and fix any build or test failures)release-X.Y.Z
for preparing the release.CHANGELOG.md
: move the "unreleased" changes to the version and add the date.master
master
branch with the version number. Version tags start with v
, e.g. v0.20.0
. Sign the tag. If you have your GPG key in github, creating a release on the Github website will automatically tag the release. It can be tagged from the command line with git tag -as v0.20.0 $COMMIT_ID
, but Github will not recognize it as a "release".develop
branch and bump VERSION
to next dev
version number.Pre-release testing procedure requires skycoin-cli of version strictly greater than 0.26.0
. Please install it if not available in your system. Some operations in the process require running a Skycoin node. Also clone Skywallet firmware repository in advance.
The instructions that follow are meant to be followed for Skywallet devices flashed without memory protection. If your device memory is protected then some values might be different e.g. firmware_features
.
During the process beware of the fact that running an Skycoin node in the background can block the Skycoin desktop wallet from running.
Some values need to be known during the process. They are represented by the following variables:
WALLET1
, WALLET2
, ... names of wallets created by skycoin-cli
ADDRESS1
, ADDRESS2
, ... Skycoin addressesTXN1_RAW
, TXN2_RAW
, ... transactions data encoded in hex dump formatTXN1_JSON
, TXN2_JSON
, ... transactions data encoded in JSON format, if numeric index value matches the one of another variable with RAW
prefix then both refer to the same transactionTXN1_ID
, TXN2_ID
, ... Hash ID of transactions after broadcasting to the P2P networkAMOUNT
represents an arbitrary number of coinsID1
, ID2
, ID3
, ... unique ID values , usually strings identifying hardware or software artifactsAUTHTOKEN
is a CSRF token for the Skycoin REST APIPerform these actions before releasing.
Note : In all cases skycoin-cli
would be equivalent to go run cmd/cli/cli.go
if current working directory set to $GOPATH/src/github.com/SkycoinProject/skycoin
.
Perform these actions before releasing:
make lint
make check
cd $GOPATH/src/github.com/skycoin/hardware-wallet-daemon/
make run-usb
skycoin-cli
(or reuse existing wallet for testing purposes)
skycoin-cli walletCreate -f $WALLET1.wlt -l $WALLET1
SEED1
and address ADDRESS1
ADDRESS1
is the only value in the list.
skycoin-cli listAddresses $WALLET1.wlt
ADDRESS1
in new wallet in two transactionsskycoin-cli addressBalance $ADDRESS1
WALLET1
and check in response that head_outputs
includes two outputs with address
set to ADDRESS1
skycoin-cli walletOutputs $WALLET1.wlt
vendor
is set to Skycoin Foundation
device_id
is a string of 24 chars, which we'll refer to as ID1
bootloader_hash
i.e. ID2
model
is set to '1'
fw_major
is set to expected firmware major version numberfw_minor
is set to expected firmware minor version numberfw_patch
is set to expected firmware patch version numberfirmware_features
is set to 0
NEEDS SEED!
message at the top.SEED1
in Skywallet device (dry-run=false
, word_count=12
).vendor
is set to Skycoin Foundation
device_id
is set to ID1
pin_protection
is set to to false
passphrase_protection
is set to false
label
is set to ID1
initialized
is set to true
bootloader_hash
is set to ID2
passphrase_cached
is set to false
needs_backup
is set to false
model
is set to '1'
fw_major
is set to expected firmware major version numberfw_minor
is set to expected firmware minor version numberfw_patch
is set to expected firmware patch version numberfirmware_features
is set to 0
ID3
. Specify usePassphrase=false
.label
is set to ID3
device_id
ADDRESS2
, ADDRESS3
respectivelyskycoin-cli
skycoin-cli walletAddAddresses -f $WALLET1.wlt -n 5
ADDRESS1
to ADDRESS2
in test wallet (say TXN_RAW1
) for an spendable amount higher than individual output's coins
export TXN1_RAW="$(skycoin-cli createRawTransaction -a $ADDRESS1 -f $WALLET1.wlt $ADDRESS2 $AMOUNT)"
echo $TXN1_RAW
export TXN1_JSON=$(skycoin-cli decodeRawTransaction $TXN1_RAW)
echo $TXN1_JSON
inputs
array there should be an item in messsage transactions_inputs
array with hash
field set to the very same hash and index
set to 0
.outputs
array there should be an item in messsage transaction_outputs
array with fields set as follows:address
: source item's dst
coins
: source item's coins
hours
: source item's hours
address_index
: set to 0
if source item address
equals ADDRESS1
or to 1
otherwisesignatures
array returned by hardware wallet includes entries for each and every transaction inputTXN2_JSON
by
TXN1_JSON
signatures with the array returned by SkyWalletTXN2_JSON
to obtain encoded transaction TXN2_RAW
export $TXN2_RAW=$( echo "$TXN2_JSON" | skycoin-cli encodeJsonTransaction --fix - | grep '"rawtx"' | cut -d '"' -f4)
echo $TXN2_RAW
TXN2_ID
export TXN2_ID=$(skycoin-cli broadcastTransaction $TXN2_RAW)
skycoin-cli walletBalance $WALLET1.wlt
WALLET2
skycoin-cli walletCreate -f $WALLET2.wlt -l $WALLET2
SEED2
and address ADDRESS4
WALLET2
addresses and confirm that ADDRESS4
is the only value in the list.
skycoin-cli listAddresses $WALLET2.wlt
WALLET2
(if not already done) and check balance
skycoin-cli addressBalance $ADDRESS4
AUTHTOKEN
) using Skycoin REST API.
curl http://127.0.0.1:6420/api/v1/csrf
ADDRESS1
(i.e. first address in WALLET1
previously recovered in Skywallet device), ADDRESS2
(i.e. second address in WALLET1
previously recovered in Skywallet device) and ADDRESS4
(i.e. first address in WALLET2
) so as to transfer to the third address of WALLET1
(i.e. ADDRESS3
). Change should be sent back to ADDRESS1
. In server response transaction JSON object (a.k.a TNX3_JSON
) would be the object at data.transaction
JSON path. If Skycoin node was started with default parameters this can be achieved as follows:
curl -X POST http://127.0.0.1:6420/api/v2/transaction -H 'content-type: application/json' -H "X-CSRF-Token: $AUTHTOKEN" -d "{
\"hours_selection\": {
\"type\": \"auto\",
\"mode\": \"share\",
\"share_factor\": \"0.5\"
},
\"addresses\": [\"$ADDRESS1\", \"$ADDRESS2\", \"$ADDRESS4\"],
\"change_address\": \"$ADDRESS1\",
\"to\": [{
\"address\": \"$ADDRESS3\",
\"coins\": \"$AMOUNT\"
}],
\"ignore_unconfirmed\": false
}"
TXN3_JSON
for inputs owned by Skywallet (i.e. WALLET1
)
inputs
array there should be an item in messsage transaction_inputs
array with:hash
field set to the value bound to object's uxid
keyindex
set as follows
null
if input address
is ADDRESS4
0
if input address
is ADDRESS1
1
if input address
is ADDRESS2
outputs
array there should be an item in messsage transaction_outputs
array with fields set as follows:address
: source item's address
coins
: source item's coins * 1000000
hours
: source item's hours
address_index
set to 2 (since destination address is ADDRESS3
)ADDRESS4
, which should be an empty stringNEEDS SEED!
message at the top.SEED2
in Skywallet device (dry-run=false
, word_count=12
).TXN3_JSON
for inputs owned by Skywallet (i.e. WALLET2
)
inputs
array there should be an item in messsage transaction_inputs
array with:hash
field set to the value bound to object's uxid
keyindex
as follows
null
if input address
is ADDRESS1
null
if input address
is ADDRESS2
0
if input address
is ADDRESS4
outputs
array there should be an item in messsage transaction_outputs
array with fields set as follows:address
: source item's dst
coins
: source item's coins * 1000000
hours
: source item's hours
address_index
set to null
TXN4_JSON
) from TXN3_JSON
and the previous signatures like this
type
same as in TXN3_JSON
inner_hash
should be an empty stringsigs
returned by SkyWallet in same order as corresponding inputinputs
is an array of strings. For each item in TXN3_JSON
inputs
include the value of its uxid
field in TXN4_JSON
inputs
array. Respect original order.outputs
is an array of objects constructed out of TXN3_JSON
outputs
items, in te same order, as followsdst
: source item's address
coins
: source item's coins * 1000000
hours
: source item's hours
as integerTXN4_JSON
to obtain encoded transaction TXN4_RAW
export $TXN4_RAW=$( echo "$TXN4_JSON" | skycoin-cli encodeJsonTransaction --fix - | grep '"rawtx"' | cut -d '"' -f4)
echo $TXN4_RAW
TXN4_ID
export TXN4_ID=$(skycoin-cli broadcastTransaction $TXN4_RAW)
skycoin-cli walletBalance $WALLET1.wlt
skycoin-cli walletBalance $WALLET2.wlt
The following instruction creates a full release:
make release
Daemon version will be take from VERSION
.
Security flaws in the source of any software provided by skycoin or infrastructure can be sent to security@skycoin.net. Bounties are available for accepted critical bug reports.
PGP Key for signing:
-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEWaj46RYJKwYBBAHaRw8BAQdApB44Kgde4Kiax3M9Ta+QbzKQQPoUHYP51fhN
1XTSbRi0I0daLUMgU0tZQ09JTiA8dG9rZW5AcHJvdG9ubWFpbC5jb20+iJYEExYK
AD4CGwMFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AWIQQQpyK3by/+e9I4AiJYAWMb
0nx4dAUCWq/TNwUJCmzbzgAKCRBYAWMb0nx4dKzqAP4tKJIk1vV2bO60nYdEuFB8
FAgb5ITlkj9PyoXcunETVAEAhigo4miyE/nmE9JT3Q/ZAB40YXS6w3hWSl3YOF1P
VQq4OARZqPjpEgorBgEEAZdVAQUBAQdAa8NkEMxo0dr2x9PlNjTZ6/gGwhaf5OEG
t2sLnPtYxlcDAQgHiH4EGBYKACYCGwwWIQQQpyK3by/+e9I4AiJYAWMb0nx4dAUC
Wq/TTQUJCmzb5AAKCRBYAWMb0nx4dFPAAQD7otGsKbV70UopH+Xdq0CDTzWRbaGw
FAoZLIZRcFv8zwD/Z3i9NjKJ8+LS5oc8rn8yNx8xRS+8iXKQq55bDmz7Igw=
=5fwW
-----END PGP PUBLIC KEY BLOCK-----
Key ID: 0x5801631BD27C7874
The fingerprint for this key is:
pub ed25519 2017-09-01 [SC] [expires: 2023-03-18]
10A7 22B7 6F2F FE7B D238 0222 5801 631B D27C 7874
uid GZ-C SKYCOIN <token@protonmail.com>
sub cv25519 2017-09-01 [E] [expires: 2023-03-18]
Keybase.io account: https://keybase.io/gzc