Function safecoin_clap_utils::keypair::signer_from_path
source · pub fn signer_from_path(
matches: &ArgMatches<'_>,
path: &str,
keypair_name: &str,
wallet_manager: &mut Option<Arc<RemoteWalletManager>>
) -> Result<Box<dyn Signer>, Box<dyn Error>>
Expand description
Loads a Signer from one of several possible sources.
The path
is not strictly a file system path, but is interpreted as various
types of signing source, depending on its format, one of which is a path
to a keypair file. Some sources may require user interaction in the course
of calling this function.
The result of this function is a boxed object of the Signer trait. To load a concrete Keypair, use the keypair_from_path function, though note that it does not support all signer sources.
The matches
argument is the same set of parsed clap matches from which
path
was parsed. It is used to parse various additional command line
arguments, depending on which signing source is requested, as described
below in “Signing sources”.
The keypair_name
argument is the “name” of the signer, and is typically
the name of the clap argument from which the path
argument was parsed,
like “keypair”, “from”, or “fee-payer”. It is used solely for interactively
prompting the user, either when entering seed phrases or selecting from
multiple hardware wallets.
The wallet_manager
is used for establishing connections to a hardware
device such as Ledger. If wallet_manager
is a reference to None
, and a
hardware signer is requested, then this function will attempt to create a
wallet manager, assigning it to the mutable wallet_manager
reference. This
argument is typically a reference to None
.
Signing sources
The path
argument can simply be a path to a keypair file, but it may also
be interpreted in several other ways, in the following order.
Firstly, the path
argument may be interpreted as a URI, with the URI
scheme indicating where to load the signer from. If it parses as a URI, then
the following schemes are supported:
-
file:
— Read the keypair from a JSON keypair file. The path portion of the URI is the file path. -
stdin:
— Read the keypair from stdin, in the JSON format used by the keypair file.Non-scheme parts of the URI are ignored.
-
prompt:
— The user will be prompted at the command line for their seed phrase and passphrase.In this URI the query string may contain zero or one of the following key/value pairs that determine the BIP44 derivation path of the private key from the seed:
-
key
— In this case the value is either one or two numerical indexes separated by a slash, which represent the “account”, and “change” components of the BIP44 derivation path. Example:key=0/0
. -
full-path
— In this case the value is a full derivation path, and the user is responsible for ensuring it is correct. Example:full-path=m/44/501/0/0/0
.
If neither is provided, then the default derivation path is used.
Note that when specifying derivation paths, this routine will convert all indexes into “hardened” indexes, even if written as “normal” indexes.
Other components of the URI besides the scheme and query string are ignored.
If the “skip_seed_phrase_validation” argument, as defined in SKIP_SEED_PHRASE_VALIDATION_ARG is found in
matches
, then the keypair seed will be generated directly from the seed phrase, without parsing or validating it as a BIP39 seed phrase. This allows the use of non-BIP39 seed phrases. -
-
usb:
— Use a USB hardware device as the signer. In this case, the URI host indicates the device type, and is required. The only currently valid host value is “ledger”.Optionally, the first segment of the URI path indicates the base-58 encoded pubkey of the wallet, and the “account” and “change” indices of the derivation path can be specified with the
key=
query parameter, as with theprompt:
URI.Examples:
usb://ledger
usb://ledger?key=0/0
usb://ledger/9rPVSygg3brqghvdZ6wsL2i5YNQTGhXGdJzF65YxaCQd
usb://ledger/9rPVSygg3brqghvdZ6wsL2i5YNQTGhXGdJzF65YxaCQd?key=0/0
Next the path
argument may be one of the following strings:
-
-
— Read the keypair from stdin. This is the same as thestdin:
URI scheme. -
ASK
— The user will be prompted at the command line for their seed phrase and passphrase. This uses a legacy key derivation method and should usually be avoided in favor ofprompt:
.
Next, if the path
argument parses as a base-58 public key, then the signer
is created without a private key, but with presigned signatures, each parsed
from the additional command line arguments, provided by the matches
argument.
In this case, the remaining command line arguments are searched for clap
arguments named “signer”, as defined by SIGNER_ARG, and each is parsed as
a key-value pair of the form “pubkey=signature”, where pubkey
is the same
base-58 public key, and signature
is a serialized signature produced by
the corresponding keypair. One of the “signer” signatures must be for the
pubkey specified in path
or this function will return an error; unless the
“sign_only” clap argument, as defined by SIGN_ONLY_ARG, is present in
matches
, in which case the signer will be created with no associated
signatures.
Finally, if path
, interpreted as a file path, represents a file on disk,
then the signer is created by reading that file as a JSON-serialized
keypair. This is the same as the file:
URI scheme.
Examples
This shows a reasonable way to set up clap to parse all possible signer
sources. Note the use of the OfflineArgs::offline_args
method to add
correct clap definitions of the --signer
and --sign-only
arguments, as
required by the base-58 pubkey offline signing method.
use clap::{App, Arg, value_t_or_exit};
use safecoin_clap_utils::keypair::signer_from_path;
use safecoin_clap_utils::offline::OfflineArgs;
let clap_app = App::new("my-program")
// The argument we'll parse as a signer "path"
.arg(Arg::with_name("keypair")
.required(true)
.help("The default signer"))
.offline_args();
let clap_matches = clap_app.get_matches();
let keypair_str = value_t_or_exit!(clap_matches, "keypair", String);
let mut wallet_manager = None;
let signer = signer_from_path(
&clap_matches,
&keypair_str,
"keypair",
&mut wallet_manager,
)?;