-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Comments:BIP 0044
Mandatory use of public derived keys is unsafe for any software which supports private key export and will result (has resulted) in funds loss. The lack of hooks for versioning is poor for future extensibility (though this could be handled at a higher level). I normally recommend against implementing this except for hardware wallets. -- Greg Maxwell 2017-03-14
I believe that this BIP should be on the Process (or Informational) Track rather than the Standards Track as per Greg Maxwell's comment on 2017-03-14. One thing I think that Greg missed is that this BIP does not propose a "change that affects most or all Bitcoin implementations, such as a change to the network protocol, a change in block or transaction validity rules, or any change or addition that affects the interoperability of applications using Bitcoin" as stated in BIP-0002.
There are times when JBOK wallets may be preferred over HD wallets. Though, I think it is important to note that funds can be lost using JBOK software wallets, like the current BTC reference client, if they have key export functions as well. There are just more keys to export than an HD wallet.
I would also like to state that it is possible to store the master key on a hardware wallet while distributing individual account keys to their proper owners, who may or may not store it on a hardware wallet, without risking the master key. Thus it is possible to secure the master key while allowing individual accounts to use software wallets.
HD wallets, like this, can also help eliminate the blockchain bloat caused by 1-of-n multi-sig wallets by eliminating some of the need for them. The same effect can be achieved by having n+1 levels, with the keys of levels 0 through n-1 controlled by a different person. Anyone having a key for any level between 0 and n-1 can spend anything in levels n onward, so rather than 100 1-of-n multi-sig accounts being established to support n account holders, a single chain can be established with n levels each corresponding to a different account holder and 100 standard addresses established at level n.
That aside, here are the changes I would make to this BIP:
- Move the BIP to either the Process Track or the Informational Track.
- Clearly state that the master key needs to be protected and, ideally, should be stored on a hardware wallet.
- Talk about the possibility of having a different owner for each account, each of which may use their preferred wallet software or hardware.
- Swap the position of the "coin_type'" and "account'" levels so that a single account can hold any coin they want.
- Add a 6th level before the "coin_type'" and "account'" levels for "revision_number'".
- Allow for the possibility of sub-accounts specific to the organization using the wallet such that there are levels "account_0'" through "account_n-1'" where n is the number of account levels.
- Add a 7th level between "revision_number'" and "account_0'" labeled "n'" to specify the number of account levels in the tree so searching is more efficient.
- A recovery process should be clearly defined.
Based on suggestions 4-7, the path levels would for this BIP would be redefined as such:
m / purpose' / revision_number' / n' / account_0' / account_1' / ... / account_n-1' / coin_type' / change / address_index
Organization should clearly define their "n'" value and enforce its use. If the "n'" states that there should be 10 levels and a particular account at the "account_1'" level, only needs one sub-account, it should still complete the tree down to the "account_n-1'" level and generate the levels from "coin_type'" onward from their "account_n-1'" to meet with their organization's standards and make account recovery from the master key easier.
During the recovery process, the stop limit at each account level is 20 by default, meaning that if there are 20 consecutive "account_n-1'" accounts in an "account_n-2'" account, each with 20 empty reviving addresses for all of the organization's "coin_types'", then it is considered the last "account_n-2'" account and the next "account_n-3'" account is searched until the last "account_0'" account is found.
Overall, I think this is a good BIP, it just needs a different track and some revision. -- Colin M. Lacina 2018-02-07
`
BIP: 119 Layer: Consensus (soft fork) Title: CHECKTEMPLATEVERIFY Author: Jeremy Rubin [email protected] Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0119 Status: Draft Type: Standards Track Created: 2020-01-06 License: BSD-3-Clause
==Abstract==
This BIP proposes a new opcode, OP_CHECKTEMPLATEVERIFY, to be activated as a change to the semantics of OP_NOP4.
==Summary==
OP_CHECKTEMPLATEVERIFY uses opcode OP_NOP4 (0xb3) as a soft fork upgrade.
OP_CHECKTEMPLATEVERIFY does the following:
- There is at least one element on the stack, fail otherwise
- The element on the stack is 32 bytes long, NOP otherwise
- The DefaultCheckTemplateVerifyHash of the transaction at the current input index is equal to the element on the stack, fail otherwise
The DefaultCheckTemplateVerifyHash commits to the serialized version, locktime, scriptSigs hash (if any non-null scriptSigs), number of inputs, sequences hash, number of outputs, outputs hash, and currently executing input index.
The recommended standardness rules additionally:
- Reject non-32 byte as SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS.
==Motivation==
This BIP introduces a transaction template, a simple spending restriction that pattern matches a transaction against a hashed transaction specification. OP_CHECKTEMPLATEVERIFY reduces many of the trust, interactivity, and storage requirements inherent with the use of pre-signing in applications. For more details on applications, please see the references.
==Detailed Specification==
The below code is the main logic for verifying CHECKTEMPLATEVERIFY, described in pythonic pseudocode. The canonical specification for the semantics of OP_CHECKTEMPLATEVERIFY as implemented in C++ in the context of Bitcoin Core can be seen in the reference implementation.
The execution of the opcode is as follows:
# CTV always requires at least one stack argument
if len(self.stack) < 1:
return self.errors_with(errors.script_err_invalid_stack_operation)
# CTV only verifies the hash against a 32 byte argument
if len(self.stack[-1]) == 32:
# Ensure the precomputed data required for anti-DoS is available,
# or cache it on first use
if self.context.precomputed_ctv_data == None:
self.context.precomputed_ctv_data = self.context.tx.get_default_check_template_precomputed_data()
# If the hashes do not match, return error
if stack[-1] != self.context.tx.get_default_check_template_hash(self.context.nIn, self.context.precomputed_ctv_data):
return self.errors_with(errors.script_err_template_mismatch)
return self.return_as_nop()
# future upgrade can add semantics for this opcode with different length args
# so discourage use when applicable
if self.flags.script_verify_discourage_upgradable_nops:
return self.errors_with(errors.script_err_discourage_upgradable_nops)
else:
return self.return_as_nop()
The computation of this hash can be implemented as specified below (where self is the transaction type). Care must be taken that in any validation context, the precomputed data must be initialized to prevent Denial-of-Service attacks. Any implementation must cache these parts of the hash computation to avoid quadratic hashing DoS. All variable length computations must be precomputed including hashes of the scriptsigs, sequences, and outputs. See the section "Denial of Service and Validation Costs" below. This is not a performance optimization.
def ser_compact_size(l): r = b"" if l < 253: # Serialize as unsigned char r = struct.pack("B", l) elif l < 0x10000: # Serialize as unsigned char 253 followed by unsigned 2 byte integer (little endian) r = struct.pack("<BH", 253, l) elif l < 0x100000000: # Serialize as unsigned char 254 followed by unsigned 4 byte integer (little endian) r = struct.pack("<BI", 254, l) else: # Serialize as unsigned char 255 followed by unsigned 8 byte integer (little endian) r = struct.pack("<BQ", 255, l) return r
def ser_string(s): return ser_compact_size(len(s)) + s
class CTxOut: def serialize(self): r = b"" # serialize as signed 8 byte integer (little endian) r += struct.pack("<q", self.nValue) r += ser_string(self.scriptPubKey) return r
def get_default_check_template_precomputed_data(self): result = {} # If there are no s`**