Our CLI tools don't facilitate offline transaction signing. This is a requirement for paper wallets and airgapped key management solutions.
TX Signing: Add a new flag --sign-only which, when passed, stops after the signing step and prints the signature to stdout encoded as base58.
TX submission: Add two new flags --signature=BASE58_SIG and --signer-pubkey=PUBKEY that, when passed, skip the signing step and instead verify that BASE58_SIG is a valid signature of the transaction by PUBKEY
@t-nelson
I need more information on the high level goal of this issue
The CLI tools generate the transactions based on input parameters. Printing out the signature for one of these internally constructed transactions doesn't seem that helpful. Do we also want the transaction itself output and add a new command to send a new tx that can take the output of the offline signed tx and submit it?
@jackcmay the offline and online CLI clients _should_ create the same transaction for the same inputs. We'd punted on I/Oing the TX in some other format (than command line "format").
However, this may have changed as per a recent request from one of our custodial solutions. @mvines do you have any more info on the human review requirement?
I have nothing to add at the moment. Human review might be better doable with another command that allows transactions to be decoded. But donno yet.
@t-nelson Which CLI commands need the ability to offline sign and do we have a priority list of which ones?
Of the current commands available I see potentially:
Custodial solutions will want to be testing pay on testnets before SLP1. *stake* (minus withdraw-stake) are all that will be in play for SLP1, since voting requires a hot key. The rest can probably be future.
cc/ @mvines for sanity
Right now I think all we need for SLP1 is delegate-stake, but yes pay for easier testing would also be nice. The rest of the commands can be dealt with post-SLP1.
Note that these two transactions need to support Nonces once that work lands too (potentially as a separate issue)
Regarding TX Signing: and TX submission, we should to build in support for multiple signatures too:
--sign-only may cause more than one signature to be printed--signature=BASE58_SIG and --signer-pubkey=PUBKEY can each be specified multiple times if the transaction requires more than one signer. Perhaps merge those two arguments into a single --signer PUBKEY=BASE58_SIG argument so it's easier to supply N of themThe non-privileged signer doesn't have access to the private keys to pass to CLI. @mvines, @t-nelson are you thinking that the pubkey and signature would be written into the transaction in the order they are provided on the command line and require the number of signers provided to equal the number of signers required by the transaction?
For example, if a transaction takes two signers:
tx.signature[0] = signer[0].signaturre;
tx.message.account_keys[0] = signere[0].pubkey
tx.signature[1] = signer[1].signaturre;
tx.message.account_keys[1] = signere[1].pubkey
Then verify the signatures against the message?
Yep. Perhaps --sign-only could even output the required set of CLI options to reconstitute the transaction outside of the signing environment.
FYI I created this issue for creating a CLI command for creating a nonce account. It will yield two important pieces of the puzzle for offline transaction signing:
Ok, so when passing in the nonce I should take a nonce and a signature . NONCE=SIGNATURE
@mvines, @t-nelson, any reason the signer CLI doesn't just spit out a signed serialized transaction that can be passed by the sender opaquely? That would remove a foot gun of the sender not writing or not copying the CLI parameters correctly to recreate the same transaction.
It could also output the fully serialized transaction, that'd be a fine addition. The reason why we want to support "only signature" is when you're copying bits out of a faraday cage by papernet, you want the payload to be as small as possible
Ok, so when passing in the nonce I should take a nonce and a signature .
NONCE=SIGNATURE
You'll need the nonce on the offline system to create the signature as well
I smell an --output-format coming
@mvines 1k seems pretty small... what's the risk?
@t-nelson Wouldn't the online system create the nonce and sign the transaction with it, if so we can provide the nonce and another --signer PUBKEY=SIGNATURE
1k seems pretty small... what's the risk?
Are you suggesting that a human write down ~1k digits on a piece of paper for each offline transaction?
I'm suggesting that humans don't write down anything, HSMs don't have to be physically air-gapped
@t-nelson Wouldn't the online system create the nonce and sign the transaction with it, if so we can provide the nonce and another
--signer PUBKEY=SIGNATURE
Sure. I'm just thinking the online system can query the nonce, so doesn't necessarily need to pass it.
I'm suggesting that humans don't write down anything, HSMs don't have to be physically air-gapped
A scenario we must be prepared for _does_ have this requirement
To summarize current action items for this issue:
The following only apply to: pay, delegate-stake, and deactivate-stake
--sign-only parameter that will not send a transaction but instead print the blockhash used (could be the nonce) as well as all the PUBKEY=SIGNATURE pairs.--blockhash parameter which provides the ability to pass a blockhash to be used rather than querying the network--signer PUBKEY=SIGNATURE parameter that can be used to construct a transaction without requiring keypairs. All the pubkey/signature pairs required by the transaction must be specified.@mvines @t-nelson @jstarry Above summary look good?
Yup. Sounds like a plan!
Most helpful comment
Right now I think all we need for SLP1 is
delegate-stake, but yespayfor easier testing would also be nice. The rest of the commands can be dealt with post-SLP1.Note that these two transactions need to support Nonces once that work lands too (potentially as a separate issue)
Regarding
TX Signing:andTX submission, we should to build in support for multiple signatures too:--sign-onlymay cause more than one signature to be printed--signature=BASE58_SIGand--signer-pubkey=PUBKEYcan each be specified multiple times if the transaction requires more than one signer. Perhaps merge those two arguments into a single--signer PUBKEY=BASE58_SIGargument so it's easier to supply N of them