|
@@ -12,22 +12,21 @@
|
|
|
help: help notes functions for MMGen suite commands
|
|
|
"""
|
|
|
|
|
|
-from ..cfg import gc
|
|
|
-
|
|
|
class help_notes:
|
|
|
|
|
|
def __init__(self, proto, cfg):
|
|
|
self.proto = proto
|
|
|
self.cfg = cfg
|
|
|
|
|
|
- def txcreate_args(self, target):
|
|
|
+ def txcreate_args(self):
|
|
|
return (
|
|
|
- 'COIN1 [AMT CHG_ADDR] COIN2 [ADDR]'
|
|
|
- if target == 'swaptx' else
|
|
|
'[ADDR,AMT ... | DATA_SPEC] ADDR'
|
|
|
if self.proto.base_proto == 'Bitcoin' else
|
|
|
'ADDR,AMT')
|
|
|
|
|
|
+ def swaptxcreate_args(self):
|
|
|
+ return 'COIN1 [AMT CHG_ADDR] COIN2 [ADDR]'
|
|
|
+
|
|
|
def account_info_desc(self):
|
|
|
return 'unspent outputs' if self.proto.base_proto == 'Bitcoin' else 'account info'
|
|
|
|
|
@@ -40,11 +39,6 @@ class help_notes:
|
|
|
cu = self.proto.coin_amt.units
|
|
|
return ', '.join(cu[:-1]) + ('', ' and ')[len(cu)>1] + cu[-1] + ('', ',\nrespectively')[len(cu)>1]
|
|
|
|
|
|
- def coind_exec(self):
|
|
|
- from ..daemon import CoinDaemon
|
|
|
- return (
|
|
|
- CoinDaemon(self.cfg, self.proto.coin).exec_fn if self.proto.coin in CoinDaemon.coins else 'bitcoind')
|
|
|
-
|
|
|
def dfl_twname(self):
|
|
|
from ..proto.btc.rpc import BitcoinRPCClient
|
|
|
return BitcoinRPCClient.dfl_twname
|
|
@@ -128,7 +122,7 @@ as {r}, using an integer followed by '{l}', for {u}.
|
|
|
c = self.proto.coin,
|
|
|
r = BaseTX(cfg=self.cfg, proto=self.proto).rel_fee_desc,
|
|
|
l = self.fee_spec_letters(use_quotes=True),
|
|
|
- u = self.fee_spec_names() )
|
|
|
+ u = self.fee_spec_names())
|
|
|
|
|
|
def passwd(self):
|
|
|
return """
|
|
@@ -146,167 +140,4 @@ BRAINWALLET NOTE:
|
|
|
To thwart dictionary attacks, it’s recommended to use a strong hash preset
|
|
|
with brainwallets. For a brainwallet passphrase to generate the correct
|
|
|
seed, the same seed length and hash preset parameters must always be used.
|
|
|
-""".strip()
|
|
|
-
|
|
|
- def txcreate_examples(self):
|
|
|
-
|
|
|
- mmtype = 'B' if 'B' in self.proto.mmtypes else self.proto.mmtypes[0]
|
|
|
- from ..tool.coin import tool_cmd
|
|
|
- t = tool_cmd(self.cfg, mmtype=mmtype)
|
|
|
- addr = t.privhex2addr('bead' * 16)
|
|
|
- sample_addr = addr.views[addr.view_pref]
|
|
|
-
|
|
|
- return f"""
|
|
|
-EXAMPLES:
|
|
|
-
|
|
|
- Send 0.123 {self.proto.coin} to an external {self.proto.name} address, returning the change to a
|
|
|
- specific MMGen address in the tracking wallet:
|
|
|
-
|
|
|
- $ {gc.prog_name} {sample_addr},0.123 01ABCDEF:{mmtype}:7
|
|
|
-
|
|
|
- Same as above, but select the change address automatically:
|
|
|
-
|
|
|
- $ {gc.prog_name} {sample_addr},0.123 01ABCDEF:{mmtype}
|
|
|
-
|
|
|
- Same as above, but select the change address automatically by address type:
|
|
|
-
|
|
|
- $ {gc.prog_name} {sample_addr},0.123 {mmtype}
|
|
|
-
|
|
|
- Same as above, but reduce verbosity and specify fee of 20 satoshis
|
|
|
- per byte:
|
|
|
-
|
|
|
- $ {gc.prog_name} -q -f 20s {sample_addr},0.123 {mmtype}
|
|
|
-
|
|
|
- Send entire balance of selected inputs minus fee to an external {self.proto.name}
|
|
|
- address:
|
|
|
-
|
|
|
- $ {gc.prog_name} {sample_addr}
|
|
|
-
|
|
|
- Send entire balance of selected inputs minus fee to first unused wallet
|
|
|
- address of specified type:
|
|
|
-
|
|
|
- $ {gc.prog_name} {mmtype}
|
|
|
-""" if self.proto.base_proto == 'Bitcoin' else f"""
|
|
|
-EXAMPLES:
|
|
|
-
|
|
|
- Send 0.123 {self.proto.coin} to an external {self.proto.name} address:
|
|
|
-
|
|
|
- $ {gc.prog_name} {sample_addr},0.123
|
|
|
-
|
|
|
- Send 0.123 {self.proto.coin} to another account in wallet 01ABCDEF:
|
|
|
-
|
|
|
- $ {gc.prog_name} 01ABCDEF:{mmtype}:7,0.123
|
|
|
-"""
|
|
|
-
|
|
|
- def txcreate(self):
|
|
|
- outputs_info = (
|
|
|
- """
|
|
|
-Outputs are specified in the form ADDRESS,AMOUNT or ADDRESS. The first form
|
|
|
-creates an output sending the given amount to the given address. The bare
|
|
|
-address form designates the given address as either the change output or the
|
|
|
-sole output of the transaction (excluding any data output). Exactly one bare
|
|
|
-address argument is required.
|
|
|
-
|
|
|
-For convenience, the bare address argument may be given as ADDRTYPE_CODE or
|
|
|
-SEED_ID:ADDRTYPE_CODE (see ADDRESS TYPES below). In the first form, the first
|
|
|
-unused address of type ADDRTYPE_CODE for each Seed ID in the tracking wallet
|
|
|
-will be displayed in a menu, with the user prompted to select one. In the
|
|
|
-second form, the user specifies the Seed ID as well, allowing the script to
|
|
|
-select the transaction’s change output or single output without prompting.
|
|
|
-See EXAMPLES below.
|
|
|
-
|
|
|
-A single DATA_SPEC argument may also be given on the command line to create
|
|
|
-an OP_RETURN data output with a zero spend amount. This is the preferred way
|
|
|
-to embed data in the blockchain. DATA_SPEC may be of the form "data":DATA
|
|
|
-or "hexdata":DATA. In the first form, DATA is a string in your system’s native
|
|
|
-encoding, typically UTF-8. In the second, DATA is a hexadecimal string (with
|
|
|
-the leading ‘0x’ omitted) encoding the binary data to be embedded. In both
|
|
|
-cases, the resulting byte string must not exceed {bl} bytes in length.
|
|
|
-""".format(bl=self.proto.max_op_return_data_len)
|
|
|
- if self.proto.base_proto == 'Bitcoin' else """
|
|
|
-The transaction output is specified in the form ADDRESS,AMOUNT.
|
|
|
-""")
|
|
|
-
|
|
|
- return """
|
|
|
-The transaction’s outputs are listed on the command line, while its inputs
|
|
|
-are chosen from a list of the wallet’s unspent outputs via an interactive
|
|
|
-menu. Alternatively, inputs may be specified using the --inputs option.
|
|
|
-
|
|
|
-Addresses on the command line can be either native coin addresses or MMGen
|
|
|
-IDs in the form SEED_ID:ADDRTYPE_CODE:INDEX.
|
|
|
-{oinfo}
|
|
|
-If the transaction fee is not specified on the command line (see FEE
|
|
|
-SPECIFICATION below), it will be calculated dynamically using network fee
|
|
|
-estimation for the default (or user-specified) number of confirmations.
|
|
|
-If network fee estimation fails, the user will be prompted for a fee.
|
|
|
-
|
|
|
-Network-estimated fees will be multiplied by the value of --fee-adjust, if
|
|
|
-specified.
|
|
|
-""".format(oinfo=outputs_info)
|
|
|
-
|
|
|
- def txsign(self):
|
|
|
- from ..proto.btc.params import mainnet
|
|
|
- return """
|
|
|
-Transactions may contain both {pnm} or non-{pnm} input addresses.
|
|
|
-
|
|
|
-To sign non-{pnm} inputs, a {wd}flat key list is used
|
|
|
-as the key source (--keys-from-file option).
|
|
|
-
|
|
|
-To sign {pnm} inputs, key data is generated from a seed as with the
|
|
|
-{pnl}-addrgen and {pnl}-keygen commands. Alternatively, a key-address file
|
|
|
-may be used (--mmgen-keys-from-file option).
|
|
|
-
|
|
|
-Multiple wallets or other seed files can be listed on the command line in
|
|
|
-any order. If the seeds required to sign the transaction’s inputs are not
|
|
|
-found in these files (or in the default wallet), the user will be prompted
|
|
|
-for seed data interactively.
|
|
|
-
|
|
|
-To prevent an attacker from crafting transactions with bogus {pnm}-to-{pnu}
|
|
|
-address mappings, all outputs to {pnm} addresses are verified with a seed
|
|
|
-source. Therefore, seed files or a key-address file for all {pnm} outputs
|
|
|
-must also be supplied on the command line if the data can’t be found in the
|
|
|
-default wallet.
|
|
|
-""".format(
|
|
|
- wd = f'{self.coind_exec()} wallet dump or ' if isinstance(self.proto, mainnet) else '',
|
|
|
- pnm = gc.proj_name,
|
|
|
- pnu = self.proto.name,
|
|
|
- pnl = gc.proj_name.lower())
|
|
|
-
|
|
|
- def subwallet(self):
|
|
|
- from ..subseed import SubSeedIdxRange
|
|
|
- return f"""
|
|
|
-SUBWALLETS:
|
|
|
-
|
|
|
-Subwallets (subseeds) are specified by a ‘Subseed Index’ consisting of:
|
|
|
-
|
|
|
- a) an integer in the range 1-{SubSeedIdxRange.max_idx}, plus
|
|
|
- b) an optional single letter, ‘L’ or ‘S’
|
|
|
-
|
|
|
-The letter designates the length of the subseed. If omitted, ‘L’ is assumed.
|
|
|
-
|
|
|
-Long (‘L’) subseeds are the same length as their parent wallet’s seed
|
|
|
-(typically 256 bits), while short (‘S’) subseeds are always 128-bit.
|
|
|
-The long and short subseeds for a given index are derived independently,
|
|
|
-so both may be used.
|
|
|
-
|
|
|
-MMGen Wallet has no notion of ‘depth’, and to an outside observer subwallets
|
|
|
-are identical to ordinary wallets. This is a feature rather than a bug, as
|
|
|
-it denies an attacker any way of knowing whether a given wallet has a parent.
|
|
|
-
|
|
|
-Since subwallets are just wallets, they may be used to generate other
|
|
|
-subwallets, leading to hierarchies of arbitrary depth. However, this is
|
|
|
-inadvisable in practice for two reasons: Firstly, it creates accounting
|
|
|
-complexity, requiring the user to independently keep track of a derivation
|
|
|
-tree. More importantly, however, it leads to the danger of Seed ID
|
|
|
-collisions between subseeds at different levels of the hierarchy, as
|
|
|
-MMGen checks and avoids ID collisions only among sibling subseeds.
|
|
|
-
|
|
|
-An exception to this caveat would be a multi-user setup where sibling
|
|
|
-subwallets are distributed to different users as their default wallets.
|
|
|
-Since the subseeds derived from these subwallets are private to each user,
|
|
|
-Seed ID collisions among them doesn’t present a problem.
|
|
|
-
|
|
|
-A safe rule of thumb, therefore, is for *each user* to derive all of his/her
|
|
|
-subwallets from a single parent. This leaves each user with a total of two
|
|
|
-million subwallets, which should be enough for most practical purposes.
|
|
|
""".strip()
|