Repository navigation
Ledger command line
Upcoming. This page describes the
ledger-nodebranch. It is not part of a release, and details may change.
Part of Ledger. The command hedgehog cli ledger reads the ledger of a running node and sends it
transfers, claims and votes. It is a client of the /ledger endpoints of the REST interface,
so it works on any node that runs the ledger, also one on another machine. Every transaction is signed by the
command itself and only the signed bytes go to the node, so a key never leaves your machine. The command does
not run the ledger: for that, see Running a ledger node.
| Command | What it does |
|---|---|
hedgehog cli ledger info |
Show the chain, the tip, the supply, the validators and the minimum fee of the node |
hedgehog cli ledger balance <address> |
Show the balance of an account or a legacy address |
hedgehog cli ledger block <height> |
Show a block and its transactions |
hedgehog cli ledger transfer |
Send coins from an account, signed with a key file |
hedgehog cli ledger claim |
Move the coins of a legacy address to an account, signed in the legacy wallet |
hedgehog cli ledger vote |
Vote, as a validator, to add or remove a validator |
The three reading commands print the answer of the node as JSON. The three that send print the answer of
the node as well, which holds the id of the transaction.
Like every cli command, these talk to localhost on port 52884, and take --resthost, --restport and
--resttoken to reach another node, see Running Hedgehog. On the machine of the
daemon the token is found without configuration. On a node that was not started with --ledger, info says
"running" : false and the other commands report The ledger is not running and exit with 1.
Naming the chain. The certificate of the REST interface is not verified, so a program that is not on the
machine of the node cannot know that it speaks to the right node. A node that is wrong, or in someone else's
hands, could tell a command the wrong chain, fee and nonce. --chain <chain id> guards against that: the
command signs only if the node reports that chain id. Get the id from info on a node you trust, or compare
it with other operators. --chain is required by transfer, vote and claim when --resthost is not
localhost or another loopback address, and optional on the same machine. Without it such a command exits
with 2 before it connects:
Pass --chain: a node at node.example.org cannot prove which chain it is on; `cli ledger info` on a node you trust shows it
A command that signs writes what it signed on standard error, before the answer of the node, and leaves standard output to the JSON of the answer:
Signed for chain 9c41…e7: transfer 12.50000000 to 8be0…14 fee 0.00100000 nonce 3
Signed for chain 9c41…e7: vote to add 5d7c…02 in round 12
Signed for chain 9c41…e7: claim of Uexample1111111111111111111111111 to 8be0…14
$ hedgehog cli ledger info
{
"running" : true,
"halted" : false,
"haltReason" : "",
"signing" : false,
"chainId" : "9c41…e7",
"height" : 1204,
"tipHash" : "5b0e…a2",
"supply" : "21530000.00000000",
"round" : 12,
"validators" : [ "3f2a…c9", "8be0…14" ],
"minimumFee" : "0.00100000",
"droppedInbound" : 0,
"unsetSporks" : [ ],
"laggingSporks" : [ ]
}The fields are described on REST interface. A spork in unsetSporks or
laggingSporks means the node answers no for what it governs, see Ledger sporks.
balance takes an account as 64 hex characters, in any case, or a legacy address. It prints the balance, and
for an account the nonce, the number of transfers it has made. For a legacy address it prints what a claim
would move and, once it is claimed, the account that claimed it:
$ hedgehog cli ledger balance Uexample1111111111111111111111111
{
"address" : "Uexample1111111111111111111111111",
"kind" : "legacy",
"balance" : "0.00000000",
"mintedBySporks" : "0.00000000",
"claimable" : "1250.00000000"
}block takes a height from 1 up to the tip and prints the block with its transactions, the validators that
signed it and the hashes that tie it to the chain. A height above the tip is refused with
No block at height <n>.
-
Amounts are coins as plain decimal text, such as
12.5. At most eight decimals, above zero, with no sign, exponent, comma or space. A value that does not fit is refused, never rounded. - An address is an account, 64 hex characters, or a legacy address as the old wallet writes it. A legacy address is spelled exactly as written, since case is part of it.
-
A key file is one made by
hedgehog util ledger-key-generate <file>, one line of 64 hex characters that only its owner can read, see Running a ledger node. The account of a key is the public key that the command printed. The key of a holder and the key of a validator are the same kind of file.
transfer sends coins from the account of a key file:
| Option | Meaning |
|---|---|
--key <file> |
The key file of the sender. Required |
--to <address> |
The account or legacy address that gets the coins. Required |
--amount <coins> |
How many coins to send. Required |
--fee <coins> |
The fee. The minimum fee of the node when left out |
--nonce <n> |
The number of transfers the sender has made. The next one, asked of the node, when left out |
--chain <chain id> |
Sign only if the node is on this chain. Required for a node that is not on this machine |
Send 12.5 coins with the fee and the nonce that the node asks for:
$ hedgehog cli ledger transfer --key ~/.account.key --to 8be0…14 --amount 12.5
{
"accepted" : true,
"id" : "e208…5d"
}The answer means the node took the transfer in, not that a block holds it. When a block does, the id is
the id of the transaction in hedgehog cli ledger block <height>.
-
The default fee is the minimum of the node, the
minimumFeeofinfo. With no fee spork set the node has no minimum, and the command asks for--fee. It asks for it also when the node reports a minimum that no fee spork could set, a negative one or one above a coin. To pay more than the minimum, say so:--fee 0.002. Like every amount, a fee of zero is refused, so a zero fee is sent only by leaving--feeout on a node whose minimum is zero. -
The default nonce is the next one of the account. Give
--nonceto queue several transfers at once. The ledger holds up to 16 waiting transfers of a sender from its next nonce on, and makes them in the order of their nonces. - Pin the chain for a node on another machine:
$ hedgehog cli --resthost node.example.org --resttoken <token> ledger transfer \
--key ~/.account.key --to 8be0…14 --amount 12.5 --chain 9c41…e7A transfer that the node refuses ends with the node's own reason on standard error and exit code 1, such as
Balance does not cover the transfer, Transfer nonce is already used or
Fee is below what this node demands. The command refuses a node that has no ledger, before it signs.
A claim moves what a legacy address holds to a ledger account. Its owner proves it with a signature of the old wallet, which a command cannot make: the private key of a legacy address is never asked for. The claim is made in two runs of the command, with the wallet in between:
sequenceDiagram
participant U as You
participant C as hedgehog cli ledger claim
participant W as Legacy wallet
participant N as Node
U->>C: --address and --to
C->>N: GET /ledger
N-->>C: the chain id
C-->>U: the text to sign and the signmessage line
U->>W: signmessage "address" "text"
W-->>U: a signature in base64
U->>C: --address, --to and --signature
C->>C: recover the key, check the address and the signature
C->>N: POST /ledger/transaction
N-->>C: accepted, or the reason
The first run. Give the legacy address and the account that gets the coins. The command asks the node for the chain, prints the text to sign and the line to run in the legacy wallet, and stops. Nothing is sent:
$ hedgehog cli ledger claim --address Uexample1111111111111111111111111 --to 3f2a…c9
Text to sign: claim 9c41…e7 3f2a…c9
Run this in the legacy wallet, then run this command again with --signature <what it prints>:
signmessage "Uexample1111111111111111111111111" "claim 9c41…e7 3f2a…c9"The text is claim <chain id> <account>, with the chain id as 128 hex characters and the account as 64, all lower
case, as printed. It names the chain and the recipient, so the signature is good for this claim only: it cannot
be replayed on another chain or used to pay another account.
The second run. Run the signmessage line in the console of the legacy wallet. It prints the signature as base64.
Run the command again with it:
$ hedgehog cli ledger claim --address Uexample1111111111111111111111111 --to 3f2a…c9 \
--signature H1v8…Q4=
{
"accepted" : true,
"id" : "7c0d…3b"
}The wallet prints a signature and no key. The command recovers the public key from the signature, checks that
it belongs to --address, and checks the signature against the text for this chain, all before it sends.
A signature of another text, or from another wallet, is refused at once, with a message that names both
possibilities. Blanks around the signature, from copying it, are ignored.
A claim has no amount: it takes what the snapshot holds for the address and what the ledger sent to it, all at once. Once it is made, later mints and transfers to the legacy address go to the account. A node holds a claim back when its policy says so, for example for an address on the blacklist, and then the command ends with the reason and exit code 1; see Ledger sporks.
| Option | Meaning |
|---|---|
--address <address> |
The legacy address that holds the coins. Required |
--to <account> |
The ledger account, 64 hex characters, that gets them. Required |
--signature <base64> |
What signmessage printed. Without it, the command prints the text to sign |
--chain <chain id> |
Sign only if the node is on this chain. Required for a node that is not on this machine |
A validator votes to add a key to the validator set, or to remove one. The vote counts in the current round, and changes take effect only at its end, when more than two thirds of the set have voted for them, see Ledger. The command signs with the key file of the validator:
$ hedgehog cli ledger vote --key ~/.ledger.key --candidate 5a77…0e --add
{
"accepted" : true,
"id" : "b3f1…9a"
}| Option | Meaning |
|---|---|
--key <file> |
The key file of the voter. Required |
--candidate <account> |
The account to add or remove, 64 hex characters. Required |
--add, --remove
|
One of them is required |
--chain <chain id> |
Sign only if the node is on this chain. Required for a node that is not on this machine |
The command reads the round and the validators from the node and refuses early, with exit code 2, a key that is not a validator, an addition of one who is a validator already, and a removal of one who is not. The genesis validators can never be removed: the node refuses that vote with its reason. A validator votes once per candidate and casts at most 64 votes in a round.
| Code | Meaning |
|---|---|
| 0 | Done. The node answered, or the first run of a claim printed the text to sign |
| 1 | The node refused, or could not be reached. The reason is on standard error: the ledger's own words for a refused transaction, or Could not reach the node at <host>:<port>, or that there is no REST token to read |
| 2 | The command was misused and nothing was sent: a missing or malformed option, an amount that is not valid, an address of the wrong kind, a key file that others can read, a signature that does not fit the text or the address, or a vote that cannot be cast |
-
application/src/main/java/org/unigrid/hedgehog/command/cli/ledger/LedgerCommand.java: the group, withLedgerInfoCommand.java,LedgerBalanceCommand.java,LedgerBlockCommand.java,LedgerTransferCommand.java,LedgerClaimCommand.javaandLedgerVoteCommand.javabeside it -
application/src/main/java/org/unigrid/hedgehog/command/cli/ledger/LedgerClient.java: the requests to the node and the exit codes -
application/src/main/java/org/unigrid/hedgehog/command/cli/ledger/ChainOption.java: the--chainoption -
application/src/main/java/org/unigrid/hedgehog/model/bootstrap/LedgerText.java: how addresses and amounts are read -
ledger/src/main/java/org/unigrid/hedgehog/ledger/LegacySignature.java: the check of a legacy signature, and the recovery of its key -
ledger/src/main/java/org/unigrid/hedgehog/ledger/Claim.java: the text that is signed,Claim.message
Using Hedgehog
Code
Network
Releases
Upcoming