Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/bitcoin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
jl2012 committed Jan 19, 2016
2 parents 345f1c4 + f01ec3f commit 171c392
Show file tree
Hide file tree
Showing 12 changed files with 690 additions and 346 deletions.
24 changes: 21 additions & 3 deletions README.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ Those proposing changes should consider that ultimately consent may rest with th
| OP_CHECKLOCKTIMEVERIFY
| Peter Todd
| Standard
| Draft
| Accepted
|-
| [[bip-0066.mediawiki|66]]
| Strict DER signatures
Expand Down Expand Up @@ -302,6 +302,12 @@ Those proposing changes should consider that ultimately consent may rest with th
| Standard
| Draft
|-
| [[bip-0083.mediawiki|83]]
| Dynamic Hierarchical Deterministic Key Trees
| Eric Lombrozo
| Standard
| Draft
|-
| [[bip-0099.mediawiki|99]]
| Motivation and deployment of consensus rule changes ([soft/hard]forks)
| Jorge Timón
Expand Down Expand Up @@ -386,6 +392,12 @@ Those proposing changes should consider that ultimately consent may rest with th
| Informational
| Draft
|-
| [[bip-0124.mediawiki|124]]
| Hierarchical Deterministic Script Templates
| Eric Lombrozo, William Swanson
| Informational
| Draft
|-
| [[bip-0125.mediawiki|125]]
| Opt-in Full Replace-by-Fee Signaling
| David Harding, Peter Todd
Expand All @@ -398,6 +410,12 @@ Those proposing changes should consider that ultimately consent may rest with th
| Standard
| Draft
|-
| [[bip-0131.mediawiki|131]]
| "Coalescing Transaction" Specification (wildcard inputs)
| Chris Priest
| Standard
| Draft
|-
| [[bip-0140.mediawiki|140]]
| Normalized TXID
| Christian Decker
Expand All @@ -411,13 +429,13 @@ Those proposing changes should consider that ultimately consent may rest with th
| Draft
|-
| [[bip-0142.mediawiki|142]]
| Address Formats for Witness Program
| Address Format for Segregated Witness
| Johnson Lau
| Standard
| Draft
|-
| [[bip-0143.mediawiki|143]]
| Transaction signature verification for version 0 and version 1 witness program
| Transaction Signature Verification for Version 0 Witness Program
| Johnson Lau, Pieter Wuille
| Standard
| Draft
Expand Down
3 changes: 2 additions & 1 deletion bip-0032.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ PyCoin (https://github.com/richardkiss/pycoin) is a suite of utilities for deali

A Java implementation is available at https://github.com/bitsofproof/supernode/blob/1.1/api/src/main/java/com/bitsofproof/supernode/api/ExtendedKey.java

A C++ implementation is available at https://github.com/CodeShark/CoinClasses/tree/master/tests/hdwallets
A C++ implementation is available at https://github.com/ciphrex/mSIGNA/blob/master/deps/CoinCore/src/hdkeys.h

An Objective-C implementation is available at https://github.com/oleganza/CoreBitcoin/blob/master/CoreBitcoin/BTCKeychain.h

Expand All @@ -281,4 +281,5 @@ A Haskell implementation is available at https://github.com/haskoin/haskoin toge

* Gregory Maxwell for the original idea of type-2 deterministic wallets, and many discussions about it.
* Alan Reiner for the implementation of this scheme in Armory, and the suggestions that followed from that.
* Eric Lombrozo for reviewing and revising this BIP.
* Mike Caldwell for the version bytes to obtain human-recognizable Base58 strings.
265 changes: 143 additions & 122 deletions bip-0068.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -49,139 +49,160 @@ The block produced time is equal to the median-time-past of its previous block.

When the relative lock-time is block-based, it is interpreted as a minimum block-height constraint over the input's age. A relative block-based lock-time of zero indicates an input which can be included in any block. More generally, a relative block lock-time n can be included n blocks after the mining date of the output it is spending, or any block thereafter.

This is proposed to be accomplished by replacing IsFinalTx() and CheckFinalTx(), existing consensus and non-consensus code functions that return true if a transaction's lock-time constraints are satisfied and false otherwise, with LockTime() and CheckLockTime(), new functions that return a non-zero value if a transaction's lock-time or sequence number constraints are not satisfied and zero otherwise:
==Implementation==

A reference implementation is provided by the following pull request

https://github.com/bitcoin/bitcoin/pull/7184

<pre>
enum {
/* Interpret sequence numbers as relative lock-time constraints. */
LOCKTIME_VERIFY_SEQUENCE = (1 << 0),
};

/* Setting nSequence to this value for every input in a transaction
* disables nLockTime. */
static const uint32_t SEQUENCE_FINAL = 0xffffffff;
/* If this flag set, CTxIn::nSequence is NOT interpreted as a
* relative lock-time. Setting the most significant bit of a
* sequence number disabled relative lock-time. */
static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31);
enum {
/* Interpret sequence numbers as relative lock-time constraints. */
LOCKTIME_VERIFY_SEQUENCE = (1 << 0),
};

/* If CTxIn::nSequence encodes a relative lock-time and this flag
* is set, the relative lock-time has units of 512 seconds,
* otherwise it specifies blocks with a granularity of 1. */
static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22);
/* Setting nSequence to this value for every input in a transaction
* disables nLockTime. */
static const uint32_t SEQUENCE_FINAL = 0xffffffff;

/* If CTxIn::nSequence encodes a relative lock-time, this mask is
* applied to extract that lock-time from the sequence field. */
static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
/* If this flag set, CTxIn::nSequence is NOT interpreted as a
* relative lock-time. Setting the most significant bit of a
* sequence number disabled relative lock-time. */
static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31);

/* In order to use the same number of bits to encode roughly the
* same wall-clock duration, and because blocks are naturally
* limited to occur every 600s on average, the minimum granularity
* for time-based relative lock-time is fixed at 512 seconds.
* Converting from CTxIn::nSequence to seconds is performed by
* multiplying by 512 = 2^9, or equivalently shifting up by
* 9 bits. */
static const int SEQUENCE_LOCKTIME_GRANULARITY = 9;
/* If CTxIn::nSequence encodes a relative lock-time and this flag
* is set, the relative lock-time has units of 512 seconds,
* otherwise it specifies blocks with a granularity of 1. */
static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22);

int64_t LockTime(const CTransaction &tx, int flags, const std::vector<int>* prevHeights, const CBlockIndex& block)
{
assert(prevHeights == NULL || prevHeights->size() == tx.vin.size());
int64_t nBlockTime = (flags & LOCKTIME_MEDIAN_TIME_PAST)
? block.GetAncestor(std::max(block.nHeight-1, 0))->GetMedianTimePast()
: block.GetBlockTime();
bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2
&& flags & LOCKTIME_VERIFY_SEQUENCE;
// Will be set to the equivalent height- and time-based nLockTime
// values that would be necessary to satisfy all relative lock-
// time constraints given our view of block chain history.
int nMinHeight = 0;
int64_t nMinTime = 0;
// Will remain equal to true if all inputs are finalized
// (CTxIn::SEQUENCE_FINAL).
bool fFinalized = true;
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
const CTxIn& txin = tx.vin[txinIndex];
// Set a flag if we witness an input that isn't finalized.
if (txin.nSequence == CTxIn::SEQUENCE_FINAL)
continue;
else
fFinalized = false;
/* If CTxIn::nSequence encodes a relative lock-time, this mask is
* applied to extract that lock-time from the sequence field. */
static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff;

// Do not enforce sequence numbers as a relative lock time
// unless we have been instructed to, and a view has been
// provided.
if (!fEnforceBIP68)
continue;
/* In order to use the same number of bits to encode roughly the
* same wall-clock duration, and because blocks are naturally
* limited to occur every 600s on average, the minimum granularity
* for time-based relative lock-time is fixed at 512 seconds.
* Converting from CTxIn::nSequence to seconds is performed by
* multiplying by 512 = 2^9, or equivalently shifting up by
* 9 bits. */
static const int SEQUENCE_LOCKTIME_GRANULARITY = 9;

// Sequence numbers with the most significant bit set are not
// treated as relative lock-times, nor are they given any
// consensus-enforced meaning at this point.
if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG)
continue;
if (prevHeights == NULL)
continue;
int nCoinHeight = (*prevHeights)[txinIndex];
if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast();
// Time-based relative lock-times are measured from the
// smallest allowed timestamp of the block containing the
// txout being spent, which is the median time past of the
// block prior.
nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
} else {
// We subtract 1 from relative lock-times because a lock-
// time of 0 has the semantics of "same block," so a lock-
// time of 1 should mean "next block," but nLockTime has
// the semantics of "last invalid block height."
nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
}
/**
* Calculates the block height and time which the transaction must be later than
* in order to be considered final in the context of BIP 68. It also removes
* from the vector of input heights any entries which did not correspond to sequence
* locked inputs as they do not affect the calculation.
*/
static std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
{
assert(prevHeights->size() == tx.vin.size());

// Will be set to the equivalent height- and time-based nLockTime
// values that would be necessary to satisfy all relative lock-
// time constraints given our view of block chain history.
// The semantics of nLockTime are the last invalid height/time, so
// use -1 to have the effect of any height or time being valid.
int nMinHeight = -1;
int64_t nMinTime = -1;
// tx.nVersion is signed integer so requires cast to unsigned otherwise
// we would be doing a signed comparison and half the range of nVersion
// wouldn't support BIP 68.
bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2
&& flags & LOCKTIME_VERIFY_SEQUENCE;
// Do not enforce sequence numbers as a relative lock time
// unless we have been instructed to
if (!fEnforceBIP68) {
return std::make_pair(nMinHeight, nMinTime);
}
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
const CTxIn& txin = tx.vin[txinIndex];
// Sequence numbers with the most significant bit set are not
// treated as relative lock-times, nor are they given any
// consensus-enforced meaning at this point.
if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) {
// The height of this input is not relevant for sequence locks
(*prevHeights)[txinIndex] = 0;
continue;
}
// If all sequence numbers are CTxIn::SEQUENCE_FINAL, the
// transaction is considered final and nLockTime constraints
// are not enforced.
if (fFinalized)
return 0;
if ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD)
nMinHeight = std::max(nMinHeight, (int)tx.nLockTime);
else
nMinTime = std::max(nMinTime, (int64_t)tx.nLockTime);
if (nMinHeight >= block.nHeight)
return nMinHeight;
if (nMinTime >= nBlockTime)
return nMinTime;
return 0;
}</pre>
Code conditional on the return value of IsFinalTx() / CheckLockTime() has to be updated as well, since the semantics of the return value has been inverted.

==Example: Bidirectional payment channel==
A bidirectional payment channel can be established by two parties funding a single output in the following way: Alice funds a 1 BTC output which is the 2-of-2 multisig of Alice AND Bob, or Alice's key only after a sufficiently long timeout, e.g. 30 days or 4320 blocks. The channel-generating transaction is signed by Alice and broadcast to the network.

Alice desires to send Bob a payment of 0.1 BTC. She does so by constructing a transaction spending the 1 BTC output and sending 0.1 BTC to Bob and 0.9 BTC back to herself. She provides her signature for the 2-of-2 multisig constraint, and sets a relative lock-time using the sequence number field such that the transaction will become valid 24-hours or 144 blocks before the refund timeout. Two more times Alice sends Bob a payment of 0.1 BTC, each time generating and signing her half of a transaction spending the 1btc output and sending 0.2 BTC, then 0.3 BTC to Bob with a relative lock-time of 29 days from creation of the channel.

Bob now desires to send Alice a refund of 0.25 BTC. He does so by constructing a transaction spending the 1btc output and sending 0.95 BTC (= 0.7 BTC + 0.25 BTC) to Alice and 0.05 BTC to himself. Since Bob will still have in his logs the transaction giving him 0.7 BTC 29 days after the creation of the channel, Alice demands that this new transaction have a relative lock-time of 28 days so she has a full day to broadcast it before the next transaction matures.

Alice and Bob continue to make payments to each other, decrementing the relative lock-time by one day each time the channel switches direction, until the present time is reached or either party desires to close out the channel. A close-out is performed by finalizing the input (nSequence = MAX_INT) and both parties signing.

==Implementation==

A reference implementation is provided by the following pull request
int nCoinHeight = (*prevHeights)[txinIndex];
if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast();
// Time-based relative lock-times are measured from the
// smallest allowed timestamp of the block containing the
// txout being spent, which is the median time past of the
// block prior.
nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
} else {
// We subtract 1 from relative lock-times because a lock-
// time of 0 has the semantics of "same block," so a lock-
// time of 1 should mean "next block," but nLockTime has
// the semantics of "last invalid block height."
nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
}
}
return std::make_pair(nMinHeight, nMinTime);
}

static bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair)
{
int64_t nBlockTime = block.pprev ? block.pprev->GetMedianTimePast() : 0;
if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime)
return false;

return true;
}

bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
{
return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
}

bool CheckSequenceLocks(const CTransaction &tx, int flags)
{
AssertLockHeld(cs_main);

CBlockIndex* tip = chainActive.Tip();
CBlockIndex index;
index.pprev = tip;
// CheckSequenceLocks() uses chainActive.Height()+1 to evaluate
// height based locks because when SequenceLocks() is called within
// CBlock::AcceptBlock(), the height of the block *being*
// evaluated is what is used. Thus if we want to know if a
// transaction can be part of the *next* block, we need to call
// SequenceLocks() with one more than chainActive.Height().
index.nHeight = tip->nHeight + 1;
// pcoinsTip contains the UTXO set for chainActive.Tip()
CCoinsViewMemPool viewMemPool(pcoinsTip, mempool);
std::vector<int> prevheights;
prevheights.resize(tx.vin.size());
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
const CTxIn& txin = tx.vin[txinIndex];
CCoins coins;
if (!viewMemPool.GetCoins(txin.prevout.hash, coins)) {
return error("%s: Missing input", __func__);
}
if (coins.nHeight == MEMPOOL_HEIGHT) {
// Assume all mempool transaction confirm in the next block
prevheights[txinIndex] = tip->nHeight + 1;
} else {
prevheights[txinIndex] = coins.nHeight;
}
}
https://github.com/bitcoin/bitcoin/pull/6312
std::pair<int, int64_t> lockPair = CalculateSequenceLocks(tx, flags, &prevheights, index);
return EvaluateSequenceLocks(index, lockPair);
}
</pre>

==Acknowledgments==

Expand Down
Loading

1 comment on commit 171c392

@SpencerLobree
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jl2012 hi ,i couldn’t find another way to reach you...
I'm looking for a dev with your stack/advisor/consultant to work on our platform , Metify[.]tech, as a freelancer or full-time . some projects start soon and others begin in 6-12 months ,so if you're busy now ,we can discuss it in advance . are you up ? contact me on telegram @SpencerLobree or via email at [email protected]

Please sign in to comment.