btclib.block package¶
Submodules¶
btclib.block.block module¶
The Block dataclass and its rules; the class docstring has the contract.
- class btclib.block.block.Block(header: BlockHeader, transactions: Sequence[Tx] | None = None, *, check_validity: bool = True)[source]¶
Bases:
objectA block: its header and the transactions the header commits to.
assert_valid is Core’s CheckBlock – what the bytes answer for themselves, proof-of-work included; the rules that need a height or a clock are assert_valid_contextual, taking a BlockContext.
- assert_valid(pow_limit_bits: bytes | str | bytearray | memoryview = b'\x1d\x00\xff\xff') None[source]¶
Refuse what Core’s CheckBlock refuses, in Core’s order.
The header and its proof-of-work, the size bounds, exactly one coinbase and it first, every transaction on its own, the sigop bound, the merkle root, the witness commitment, the weight. Height and clock rules are assert_valid_contextual’s.
pow_limit_bits is forwarded to assert_valid_pow, whose docstring says why the network’s easiest target is the caller’s to state and why mainnet’s is the default. It is a parameter here and not of __init__, parse or serialize: those three call this to answer whether the bytes are a block, and a block of another network is built with check_validity=False and then asked, which is the same two steps a caller already takes to build a header being mined.
- assert_valid_coinbase_height(height: int) None[source]¶
Assert that the coinbase commits to a height (BIP34, bad-cb-height).
A byte comparison, as Core’s is: the coinbase script_sig must start with CScript() << nHeight, so a height pushed any other way than the shortest is refused although it decodes to the right number. Block.height is the decoder, and comparing what it returns would accept a commitment no other node does – bip34_commitment is what the comparison is against.
Which height, and whether BIP34 is in force at all, are the caller’s to say: the second is BlockContext.is_bip34_active, and assert_valid_contextual is what applies it. Nothing is skipped here, so a caller that knows the rule binds can ask for it directly – which is the only way to ask it of a block whose height is all that is known about its place in a chain.
- assert_valid_contextual(context: BlockContext) None[source]¶
Assert the rules a block cannot be checked against on its own.
Bitcoin Core’s ContextualCheckBlockHeader and ContextualCheckBlock, as far as a height and a clock reach: bad-diffbits and time-too-old wherever the caller has walked the chain for them, time-too-new always, and bad-cb-height wherever BIP34 is in force. In that order, which is Core’s – the header is checked before the block it heads, and within the header proof-of-work before the clock.
Separate from assert_valid, which is CheckBlock: what the bytes answer for themselves, and therefore what Block.parse can ask. Both are asked of a block being accepted, and by whoever has the context; neither implies the other.
bad-diffbits and time-too-old are the two rules BlockContext.median_time_past and .required_bits answer for, and each is skipped where the field is None – a caller that has not walked the chain for it, most of them until now. The rest of Core’s two functions still needs more than a context: bad-version the activation heights of BIP34, BIP66 and BIP65, bad-txns-nonfinal every transaction’s lock time against the same median time past. Each becomes a field of BlockContext once the chain state it reads is there to put in one.
- assert_valid_length() None[source]¶
Assert the size limits of Core’s CheckBlock (bad-blk-length).
Two comparisons against MAX_BLOCK_WEIGHT, and neither of them is the weight: the transaction count times WITNESS_SCALE_FACTOR – no transaction serializes to less than a byte, and a byte outside the witness weighs four, so a block holds at most a quarter of the cap in transactions – and the stripped size times WITNESS_SCALE_FACTOR. The second is what real blocks sit against: 3,954,076 of 4,000,000 for block 481,824, 98.9% of the cap. The weight itself is bounded by assert_valid_weight, where Core bounds it.
The count is compared first, as in Core’s single condition, and that is what keeps this cheap: a list too long to be a block is refused without serializing it.
- assert_valid_merkle_root() None[source]¶
Refuse a header whose merkle root is not the transactions’.
The CVE-2012-2459 mutation flag is refused too, as Core’s bad-txns-duplicate; the comment below carries the reasoning.
- assert_valid_sig_op_count() None[source]¶
Assert the sigop bound of Core’s CheckBlock (bad-blk-sigops).
The legacy count of every script in the block, times WITNESS_SCALE_FACTOR, against MAX_BLOCK_SIGOPS_COST – i.e. 20,000 legacy signature checks. It is the only sigop rule reachable from the bytes: what Core adds in ConnectBlock is counted over the outputs being spent, which are in other blocks.
The largest answer this library has a block for is block 481,824’s 3,409, so a block that breaks this rule has to be built for the purpose. That is what makes the arithmetic the thing worth testing, and script.sig_ops is where it happens.
- assert_valid_structure() None[source]¶
Refuse what Core’s CheckBlock refuses, proof-of-work excepted.
The size bounds, exactly one coinbase and it first, every transaction on its own, the sigop bound, the merkle root, the witness commitment, the weight – everything assert_valid asks except BlockHeader.assert_valid and assert_valid_pow, which it calls immediately before this and which a pre-mining candidate cannot pass. block.build.build_block is the other caller: a header mining.candidate_block_header has already validated structurally, over a block that has no proof-of-work yet and cannot be asked for one, and everything below still has to hold of it – the two coinbases, the over-weight block and the over-the-sigop-bound block this refuses are exactly what a builder must not hand back silently.
- assert_valid_weight() None[source]¶
Assert the weight bound of BIP141 (bad-blk-weight).
Core asks this in ContextualCheckBlock and not in CheckBlock, though the weight is read off the bytes like everything else, and the reason is the order rather than the context: the coinbase witness is not covered by the block hash, so a block whose weight is over the cap only because that witness was stuffed must not be marked permanently invalid before the commitment to it has been checked. Hence the position here, right after assert_valid_witness_commitment, and hence the same rule twice at different strengths – assert_valid_length bounds what a legacy node relays, this bounds the block segwit nodes see.
- assert_valid_witness_commitment() None[source]¶
Assert that the coinbase commits to the witness data (BIP141).
The merkle root of the header is computed over txids, which by segwit’s design leave every witness out: without this check the witnesses of a block can be replaced wholesale, header and root untouched, and the signatures they carry are worth nothing.
- classmethod from_dict(dict_: Mapping[str, Any], *, check_validity: bool = True) Block[source]¶
Build a Block from the dict shape to_dict writes.
- property height: int | None¶
Return the height committed into a BIP34 coinbase script_sig.
Version 2 blocks commit block height into the coinbase script_sig.
https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki Block 227,835 (2013-03-24 15 :49: 13 GMT) was the last version 1 block.
This is the reader and not the check: it decodes whatever the coinbase pushed, where consensus compares bytes. assert_valid_coinbase_height is the check.
- classmethod parse(data: BytesIO | bytes | str | bytearray | memoryview, *, check_validity: bool = True) Block[source]¶
Return a Block by parsing binary data.
- serialize(include_witness: bool = True, *, check_validity: bool = True) bytes[source]¶
Return the wire serialization: header, count, transactions.
include_witness False gives the block as a legacy node relays it, every witness stripped – a bool and nothing else, for the reason Tx.serialize states.
- property sig_op_count: int¶
Return the legacy sigop count, summed over the transactions.
What CheckBlock sums to enforce MAX_BLOCK_SIGOPS_COST; see script.sig_ops.sig_op_count for what “legacy” leaves out and why nothing here can add it.
- property stripped_size: int¶
Return the size of the block as a legacy node sees it.
Core’s GetSerializeSize(TX_NO_WITNESS(block)), and the quantity assert_valid_length bounds: the whole block with every witness left out, which is the serialization the witness discount is expressed against and what getblock reports under this name.
- to_dict(*, check_validity: bool = True) dict[str, Any][source]¶
Return the block as a dict of json-friendly values.
The header and each transaction as their own to_dict render them; from_dict reads the same shape back.
- property weight: int¶
Return the block weight, as Core’s GetBlockWeight computes it.
Three times the stripped size plus the size, i.e. four times what a legacy node relays plus the witness bytes, over the block: the eighty bytes of the header and the var_int of the transaction count are part of it, so this is not the sum of the transactions’ weights – 332 more than that sum for block 481,824, 324 for a block holding one transaction. The sum is the number no rule reads; MAX_BLOCK_WEIGHT bounds this one.
- property witness_commitment: bytes | None¶
Return the BIP141 witness commitment, if the coinbase has one.
It is the 32 bytes following the 6a24aa21a9ed prefix in the last coinbase output carrying it, as Core’s GetWitnessCommitmentIndex does: were the first one to win, an output appended to the coinbase could not be told from one the miner meant, and the rule has to be the same one everybody else applies anyway.
- btclib.block.block.bip34_commitment(height: int) bytes[source]¶
Return the height as a coinbase script_sig must commit to it (BIP34).
Bitcoin Core’s CScript() << nHeight, which is where the bytes Block.assert_valid_coinbase_height compares against come from: the shortest encoding of the number, so OP_0 for zero and OP_1 to OP_16 for one to sixteen – one byte, no push at all – and a minimal data push of the script number from seventeen up.
Those first seventeen are not what script.serialize([height]) writes. It pushes the number as data – 0100, 0101 to 0110 – and warns that an op code says the same, which is a defensible encoding of a number and the wrong answer here: a regtest chain has BIP34 in force from height 1, so those seventeen are where the rule binds first and every node on such a chain compares against the op code.
- btclib.block.block.coinbase_witness_commitment(transactions: Sequence[Tx], nonce: bytes | str | bytearray | memoryview) bytes[source]¶
Return the coinbase’s BIP141 commitment over every witness.
Bitcoin Core’s GenerateCoinbaseCommitment (src/validation.cpp, at bitcoin/bitcoin@9be056a8a7): hash256 of the witness merkle root, concatenated with nonce – the other half of the preimage, which a real block carries in the coinbase’s own witness stack rather than here.
The witness tree is built the way merkle_root_and_mutated_from_transactions builds the txid one, over wtxids instead of txids, with one difference: transactions[0]’s own leaf is BIP141’s all-zero placeholder rather than its wtxid, which is unknowable here – it would have to commit to the very output this function’s own result ends up inside. The mutation flag merkle_root_and_mutated_from_hashes also returns is not read: the witness tree has the shape of the txid one, and two equal wtxids mean two equal transactions, hence two equal txids that assert_valid_merkle_root already rejects.
One implementation, shared between assert_valid_witness_commitment and witness_commitment_output below, for the same reason merkle_root_and_mutated_from_transactions is shared between a header being validated and one being mined: the validator and the builder must not disagree about what a set of transactions hashes to.
- btclib.block.block.merkle_root_and_mutated_from_transactions(transactions: Sequence[Tx]) tuple[bytes, bool][source]¶
Return a header’s merkle root over a list of transactions.
The leaves are the transactions serialized without witness data, i.e. their txids, and the root is reversed into the byte order a header carries. See merkle_root_and_mutated_from_hashes for the second returned value, the CVE-2012-2459 flag.
One implementation, because the block builder and the block validator must agree by construction: assert_valid_merkle_root compares this against the header at hand, and mining.py’s candidate header is built from it.
- btclib.block.block.witness_commitment_output(transactions: Sequence[Tx], nonce: bytes | str | bytearray | memoryview) TxOut[source]¶
Return the zero-valued coinbase output committing to every witness.
Nothing spends this output – it exists for Block.witness_commitment to read back, the way a real miner’s coinbase carries one. BIP141’s own aa21a9ed header goes in front of coinbase_witness_commitment’s 32 bytes, inside an OP_RETURN push, which is _COMMITMENT_PREFIX’s own shape: this is the one place that constant is written to rather than compared against.
btclib.block.block_context module¶
BlockContext dataclass.
What a block cannot be validated against from its own bytes: the height it is being accepted at, the instant it is being accepted at, and the height BIP34 takes effect at on the chain in question. Bitcoin Core reads all three off pindexPrev and the chain parameters, which is what ContextualCheckBlockHeader and ContextualCheckBlock are given and CheckBlock is not – and Block.assert_valid is CheckBlock, called by Block.parse with nothing to give it.
One carrier rather than a parameter per rule, because the list grows and each addition is chain state: time-too-old is the median time past of eleven ancestors, bad-diffbits is the target the retarget arithmetic of proof_of_work.py computes from a whole period, bad-version needs two more activation heights. Each becomes a field here when the chain state it takes arrives, and none of them changes the signature of Block.assert_valid_contextual.
median_time_past and required_bits are the first two, arrived: values rather than a callable, because a context stays what it always was, a photograph of a moment rather than an object with a chain behind it that the two rules reading it could disagree about. Computing them is btclib.block.header_context’s median_time_past and next_bits_required, which walk the chain through a ParentOf callable the caller supplies and BlockContext never sees; both default to None, which is how a caller that has not walked the chain – most of the existing callers of this class, checking only bad-cb-height and time-too-new – still builds one, and how the two rules below stay skipped rather than fed a value nobody computed.
The rules underneath take the datum they read and not the whole context – BlockHeader.assert_valid_time(now), Block.assert_valid_coinbase_height(height) – so a caller holding one half of a context asks the half it can answer, and nothing is skipped for want of the other.
- class btclib.block.block_context.BlockContext(height: int, now: datetime, bip34_height: int = 227931, median_time_past: int | None = None, required_bits: bytes | None = None, *, check_validity: bool = True)[source]¶
Bases:
objectWhat Block.assert_valid_contextual reads: a height and a clock.
The facts a block cannot answer for itself, supplied by the caller; bip34_height is the chain’s activation height, defaulting to mainnet’s, and median_time_past and required_bits default to None, which skips the rule each answers for.
- assert_valid() None[source]¶
Refuse a negative or non-int height, or a now that is no datetime.
Naive-datetime refusal is assert_valid_time’s, the reader of the clock being where the comparison happens. median_time_past and required_bits are refused only when given – None is what leaves the rule each answers for unchecked, not a value to validate – and _assert_valid_chain_state is where that happens.
- property is_bip34_active: bool¶
Whether the coinbase must commit to the height (BIP34).
Core’s DeploymentActiveAfter(pindexPrev, DEPLOYMENT_HEIGHTINCB), which is this comparison: the rule binds from the activation height on, and not from the block version. A version 1 block at or above it is refused too, by bad-version, which needs the chain and is out of scope here.
btclib.block.block_filter module¶
BIP158 compact block filters; the class docstring has the contract.
A filter is a Golomb-coded set: every script the block touches is mapped into [0, N * M) by SipHash-2-4 keyed on the block hash, the values are sorted, and the differences between them are Golomb-Rice coded. A light client that holds the filter can ask whether a script it cares about may be in the block, and fetch the block only then – which is BIP157’s getcfilters, and the reason the false positive rate 1 / M is a parameter rather than an accident.
Only the basic filter type, 0x00, is defined by BIP158, and it is what this module builds. BIP157’s peer-to-peer messages and Core’s filter index are not here: what a node stores and how it announces it are questions about a node, where this is the arithmetic over one block.
- class btclib.block.block_filter.BasicBlockFilter(block_hash: bytes | str | bytearray | memoryview = b'', element_count: int = 0, encoded_set: bytes | str | bytearray | memoryview = b'', *, check_validity: bool = True)[source]¶
Bases:
objectThe BIP158 basic filter of one block.
The block hash the filter is keyed by, the number of elements it holds, and the Golomb-Rice coded set of their hashes. The hash is in the display order BlockHeader.hash gives, and is a field rather than something read back out of the bytes: BIP157 sends a filter and the hash of its block as two things, the serialization below being the count and the set alone.
match answers “may this block touch that script”, never “does it”: a Golomb-coded set is a probabilistic structure, and one query in BASIC_FILTER_M is a false positive by construction.
- assert_valid() None[source]¶
Refuse a filter the serialized bytes could not hold.
The block hash width, the element count, and then the set itself: decoding it is the only way to know that it holds the number of elements it declares, that the bits end where the octets do, and that nothing follows them.
- property element_hashes: list[int]¶
Return the element hashes the set holds, sorted.
What the elements were is not recoverable – a filter holds their SipHash images and not the scripts – so this is what a caller comparing two filters, or counting how full one is, has to work with. match is the question about a script.
- classmethod from_block(block: Block, prevout_scripts: Sequence[bytes | str | bytearray | memoryview], *, check_validity: bool = True) BasicBlockFilter[source]¶
Return the basic filter of a block whose prevouts are resolved.
BIP158’s contents rule: the script of every output that is not an OP_RETURN one, and the previous output script of every input of every transaction but the coinbase. An empty script is a “nil” item the BIP excludes on both sides, and the elements are a set, so a script the block repeats weighs once.
prevout_scripts is one script per non-coinbase input, in the order the block spends them, and it is the caller’s: a block does not carry the outputs it spends. The count is checked against the block, which is what turns a caller passing the wrong list into an error rather than into a filter that is quietly not the one the network computed. prevout_scripts_from_utxos builds the list from a mapping for a caller that holds one.
- property hash: bytes¶
Return the hash of the serialized filter, in display order.
Core’s BlockFilter::GetHash, a double SHA256 over the octets serialize writes; reversed, as every other hash this library hands out is.
- header(previous_header: bytes | str | bytearray | memoryview) bytes[source]¶
Return the filter header that chains this filter to the previous.
filter_header over this filter’s own hash: the module function is the general form, taking the hash a cfheaders message carries where the filter itself was never sent.
- match(element: bytes | str | bytearray | memoryview) bool[source]¶
Answer whether the filter may hold the element.
- match_any(elements: Iterable[bytes | str | bytearray | memoryview]) bool[source]¶
Answer whether the filter may hold any of the elements.
Both sides are sorted and walked once, which is Core’s MatchInternal: the queries are hashed into the same range and compared against the values as they decode, so a filter is read once however many elements are asked about.
False for an empty set of elements, and false for an element the filter cannot hold – an empty script, or the script of an OP_RETURN output, neither of which is ever put in one.
- classmethod parse(data: BytesIO | bytes | str | bytearray | memoryview, block_hash: bytes | str | bytearray | memoryview = b'', *, check_validity: bool = True) BasicBlockFilter[source]¶
Return the filter these octets encode, for that block hash.
The whole of the octets: a Golomb-coded set carries no length of its own, only the count of the values coded in it, so the filter is however many octets it takes to hold them and there is no assert_no_trailing to run. What would have been trailing data is caught a level down, _decode refusing an octet the deltas never reached.
block_hash is the caller’s because the serialization does not carry it – BIP157’s cfilter message names the block beside the filter – and without it nothing could be matched: the key of the SipHash is derived from it. The default is the empty default of the constructor and not a filter keyed on nothing: assert_valid refuses it for its width, so a caller that omits the hash is told which argument it left out.
- btclib.block.block_filter.filter_header(filter_hash: bytes | str | bytearray | memoryview, previous_header: bytes | str | bytearray | memoryview) bytes[source]¶
Return the filter header chaining a filter hash onto the previous one.
Core’s BlockFilter::ComputeHeader, and BIP157’s definition: “the double-SHA256 of the concatenation of the filter hash with the previous filter header”, both in the internal order – so a header commits to every filter down to genesis, which is what lets a light client be told one hash and check the chain of filters against it. The previous header of the genesis block’s filter is thirty-two zero octets.
Both arguments and the answer are in the display order every hash this library hands out is in.
A function over a hash rather than a method on a filter, because that is the general case: BIP157’s cfheaders message carries the hashes of filters its receiver has not got, and deriving the headers is the whole of what it is for. BasicBlockFilter.header is this over a filter that is at hand.
- btclib.block.block_filter.prevout_scripts_from_utxos(block: Block, utxos: Mapping[OutPoint, TxOut]) list[bytes][source]¶
Return the previous output scripts from_block asks for.
The typed adapter over a utxo set: one script per non-coinbase input, in the order the block spends them. OutPoint is frozen and hashable so that it can key such a mapping, and an input the mapping does not answer for is refused by name – a filter built from a silently missing prevout is a filter that omits an element, which no later check would catch.
btclib.block.block_header module¶
The BlockHeader dataclass; the class docstring has the contract.
- class btclib.block.block_header.BlockHeader(version: int = 1, previous_block_hash: bytes | str | bytearray | memoryview = b'', merkle_root: bytes | str | bytearray | memoryview = b'', time: datetime = datetime.datetime(1970, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), bits: bytes | str | bytearray | memoryview = b'', nonce: int = 0, *, check_validity: bool = True)[source]¶
Bases:
objectThe eighty bytes a block is identified and mined by.
Version, previous block hash, merkle root, time, bits, nonce; the hashes and bits are held in display order and reversed on the wire, the time as an aware datetime. assert_valid answers for the eighty bytes alone – proof-of-work and clock checks are the explicit assert_valid_pow and assert_valid_time, a header being mined having neither yet.
- assert_valid() None[source]¶
Refuse a header the eighty bytes could not hold.
Field types, the version and nonce ranges, the timestamp between genesis and the last four-byte instant, the field sizes. Nothing here reads a clock or checks the work: those are assert_valid_time and assert_valid_pow, whose docstrings say why they are separate.
- assert_valid_pow(pow_limit_bits: bytes | str | bytearray | memoryview = b'\x1d\x00\xff\xff') None[source]¶
Assert whether the BlockHeader provides a valid proof-of-work.
Bitcoin Core’s CheckProofOfWork: the target the bits denote must be one the network allows, and the hash must not exceed it. The range of the target is checked first and is four questions, which are Core’s DeriveTarget – a negative bits value, a zero target, a target 32 bytes cannot hold, a target above the network’s limit. Each is refused by name, where DeriveTarget returns a bare nullopt for all four: a caller of this library is told which rule it broke, and the four are as many different mistakes.
pow_limit_bits is the network’s easiest target, mainnet’s by default as next_bits takes it, and it is the caller’s to state: a header carries no claim about which network it belongs to, so nothing here can read one. Passing REGTEST_POW_LIMIT_BITS is what makes a regtest header acceptable – and what keeps a regtest one from passing for mainnet, which is the hole this closes.
Not called by assert_valid, which answers the other question: whether the eighty bytes are a well-formed header. A header being mined is structurally valid and has no proof-of-work yet, so a candidate could not otherwise be built, serialized, or hashed through the ordinary API – and hashing it is what mining is.
Block.assert_valid does call this, as Bitcoin Core’s CheckBlock calls CheckProofOfWork by default: a Block is a block, and the proof-of-work is what its transactions are committed by.
- assert_valid_time(now: datetime) None[source]¶
Assert that the timestamp is not too far ahead of a clock.
Bitcoin Core’s time-too-new, from ContextualCheckBlockHeader: a header more than MAX_FUTURE_BLOCK_TIME ahead of the current time is refused, which is what bounds how far a miner can push a timestamp forward – and the reason it is a bound rather than an equality is that the network has no clock of its own to check against.
now is the caller’s, and never datetime.now() read here: a consensus rule taking the wall clock would have one machine accept the block another refuses, and no test of it could be written that did not depend on the day it ran on. Which is also why this is not called by assert_valid, and why Block.assert_valid does not reach it: those two answer for the eighty bytes and for the block, and a clock is neither.
time-too-old is the other half of the pair Core checks beside this one, and it is not asked here: it is the median time past of eleven ancestors, which needs the chain rather than a datum this method takes. btclib.block.header_context.median_time_past is where the walk lives, and Block.assert_valid_contextual is where the comparison is made, off BlockContext.median_time_past rather than off a callable this method could take instead.
- property difficulty: float¶
Return the BlockHeader difficulty.
Difficulty is the ratio of the genesis block target over the BlockHeader target.
It represents the average number of hash function evaluations required to satisfy the BlockHeader target, expressed as multiple of the genesis block difficulty used as unit.
The difficulty of the genesis block is 2^32 (4*2^30), i.e. 4 GigaHash function evaluations.
- classmethod from_dict(dict_: Mapping[str, Any], *, check_validity: bool = True) BlockHeader[source]¶
Build a BlockHeader from the dict shape to_dict writes.
- classmethod parse(data: BytesIO | bytes | str | bytearray | memoryview, *, check_validity: bool = True) BlockHeader[source]¶
Return a BlockHeader by parsing 80 bytes from binary data.
btclib.block.build module¶
Build a coinbase and a block; mining.py keeps the header search.
block/mining.py already builds a candidate header and searches its nonce; what it does not build is what that header commits to – a coinbase paying the chain’s own subsidy, and a block over a list of transactions with a witness commitment where one is owed. That asymmetry, and not a preference for one file over two, is why this is a module of its own beside mining.py rather than an addition to it: a builder is the first code in block/ that decides what a block is, where every other function there reads one somebody else built.
build_coinbase validates what it returns by default, check_validity False the escape – the rule every constructor of this library already has, Block, Tx and BlockHeader among them. build_block carries no such parameter, and still validates everything a pre-mining candidate can be asked for: Block.assert_valid_structure is every rule Block.assert_valid asks except the header’s own two – which a candidate cannot pass, and which mining.candidate_block_header has already asked of the header the same way BlockHeader always does. build_block’s own docstring has why the two remaining rules are left to the caller. A caller wanting a block that is invalid on purpose, the way Bitcoin Core’s own test_framework.blocktools.create_block is meant to be driven into invalid states, builds a Tx or a Block by hand with check_validity=False and mutates the result, exactly as a caller already does for a regtest block whose proof-of-work mainnet’s own default limit would refuse.
- btclib.block.build.build_block(previous_block_hash: bytes | str | bytearray | memoryview, transactions: Sequence[Tx], time: datetime, bits: bytes | str | bytearray | memoryview, *, version: int = 536870912) Block[source]¶
Return the unsolved block over transactions, ready for mining.mine.
transactions[0] is the coinbase – build_coinbase’s own shape, or a caller’s – and the rest are what it is paid to include. Where any of them carries a witness, the coinbase this returns is not the caller’s own: it is a copy carrying the BIP141 commitment Bitcoin Core’s GenerateCoinbaseCommitment writes into every block it assembles, _coinbase_with_commitment’s docstring has the pair this is built from. A block with no witness among its transactions gets neither the output nor the coinbase’s own witness stack, the way a legacy block never carried one.
mining.candidate_block_header is what builds the header, over the transactions actually carried rather than the caller’s own copies of them: the merkle root it commits to and the one Block.assert_valid_merkle_root checks are the same computation, which is the whole of what makes a built block a block.
No check_validity, unlike build_coinbase: what this returns has no proof-of-work, nonce zero rather than one that satisfies bits, and Block.assert_valid always asks for one, so there is no state in which the complete check could pass. That is not every check, though, and this still runs the rest: Block.assert_valid_structure is assert_valid minus the header’s own two rules – candidate_block_header has already asked those of the header, the same way BlockHeader always does – so a caller handing this two coinbases, an over-weight block or a malformed transaction is refused here rather than handed back a Block nothing has looked at. mining.mine is this function’s own next step, and Block.assert_valid(pow_limit_bits) is the caller’s once it returns a solved header – the one check this cannot itself perform.
- btclib.block.build.build_coinbase(height: int, script_pub_key: bytes | str | bytearray | memoryview, *, fees: int = 0, halving_interval: int = 210000, extra_nonce: bytes | str | bytearray | memoryview = b'', version: int = 1, lock_time: int = 0, check_validity: bool = True) Tx[source]¶
Return a coinbase transaction paying the subsidy at height, plus fees.
Bitcoin Core’s create_coinbase (test/functional/test_framework/blocktools.py, at bitcoin/bitcoin@9be056a8a7): a null-outpoint input committing to height (BIP34, bip34_commitment) and one output paying consensus.subsidy(height, halving_interval) + fees to script_pub_key. halving_interval defaults to mainnet’s own; a caller building for another network passes that network’s own row – CONSENSUS_PARAMS[name].subsidy_halving_interval, regtest’s 150 among them – rather than this function asserting a chain’s schedule for it.
extra_nonce is pushed onto the script_sig after the height commitment, empty by default and padding a height of sixteen or below’s one-byte commitment out to the two bytes a coinbase script_sig must carry: var_bytes.serialize(b””) is one more byte on its own, an empty push rather than nothing pushed at all. A caller mining several candidates from one height rolls this the way a real miner does once the header’s own four nonce bytes are exhausted – mining.mine’s own docstring has the reason – a different extra_nonce being a different script_sig and hence a different merkle root to search under.
btclib.block.genesis module¶
Build the genesis block of a network, on demand rather than at import.
Network.genesis_block is 32 bytes – the hash a header’s previous_block_hash is checked against – not a Block. It cannot be one: block.block already reaches btclib.network transitively, through btclib.tx’s TxOut.script_pub_key importing btclib.script’s script_pub_key module for the address tables, so a Network field holding a Block would close the cycle issue #147 is about. This module is where a caller who wants the actual block gets one instead – built here, on request, rather than carried as a field of Network or of NETWORKS.
build.build_block does the header assembly and every structural check a pre-mining candidate can pass; what this adds is the one coinbase shape it cannot build. build.build_coinbase always commits to a height (BIP34), and every network’s genesis predates that rule: its script_sig is the literal timestamp message Bitcoin Core’s CreateGenesisBlock hardcodes (kernel/chainparams.cpp, at bitcoin/bitcoin@9be056a8a7), not a general-purpose builder’s output. mainnet, testnet, regtest and signet share that message, the same public key, and OP_CHECKSIG – tests/block/build_test.py’s own mainnet vector already builds that shape – and differ only in the header’s own time, bits, nonce and version, plus the reward consensus.subsidy already gives at height zero regardless of a chain’s halving interval. testnet4 does not: Core gives it its own timestamp text and an output script that pays to thirty-three zero bytes and OP_CHECKSIG rather than to that key, and _GENESIS_PARAMS below carries both shapes rather than assuming the one mainnet uses is universal.
Every result is checked against the network’s own bits before it is returned – Block.assert_valid, at that network’s pow_limit_bits rather than mainnet’s default, which a regtest or signet genesis would fail. tests/block/genesis_test.py is the check this module exists for: every network’s built genesis hashes to the value NETWORKS already ships for it.
- btclib.block.genesis.genesis_block(network: str = 'mainnet') Block[source]¶
Return the genesis block of network, built rather than looked up.
A caller wanting only the hash already has it, cheaply, at network_from_name(network).genesis_block; this is for a caller that needs the block itself – a datadir seeding a fresh node, a test fixture – and is willing to pay for one coinbase transaction and one header assembly to get it, in place of a field this library cannot carry without closing issue #147’s cycle.
The block is checked against the network’s own easiest target before it is returned (Block.assert_valid, at that network’s pow_limit_bits), and reproduces the hash Network.genesis_block already carries for the same network – verified for all five in tests/block/genesis_test.py.
btclib.block.header_context module¶
What a header owes the chain before it: median time, target, ancestor.
Bitcoin Core’s CBlockIndex::GetMedianTimePast, GetNextWorkRequired / CalculateNextWorkRequired, and CBlockIndex::GetAncestor, over a header, its height, and a callable that steps back one header at a time rather than over an index: a batch of headers off the wire is checked before any of it is indexed, so its own members are what the header after them is checked against, and btclib does not learn what a block index is.
ConsensusParams is what tells next_bits_required which network it is answering for – pow_limit_bits, pow_allow_min_difficulty_blocks, pow_no_retargeting, enforce_bip94, and the retarget window pow_target_spacing/pow_target_timespan – and btclib.block.proof_of_work is where the arithmetic of a single retarget lives; this module is the walk that feeds it a period’s first header and the two chain-wide readings that do not need the whole retarget.
Bitcoin Core v31.1 (bitcoin/bitcoin@9be056a8a7) is the reference for every rule, src/chain.h, src/pow.cpp and src/validation.cpp’s ContextualCheckBlockHeader, cited beside the code that transcribes it.
- btclib.block.header_context.header_at_height(header: BlockHeader, height: int, target_height: int, parent_of: Callable[[BlockHeader], BlockHeader]) BlockHeader[source]¶
Walk back from header, at height, to its ancestor at target_height.
Core’s CBlockIndex::GetAncestor, over a skip list there; this walks parent_of one header at a time, which is the same cost median_time_past already pays to reach its own eleventh ancestor – unbounded here rather than capped at ten, since a caller asking for a BIP68 time-locked input’s own coin height can name any past height, not only one within the last eleven blocks.
- btclib.block.header_context.median_time_past(header: BlockHeader, height: int, parent_of: Callable[[BlockHeader], BlockHeader]) int[source]¶
Return the median timestamp of a header and its ten ancestors.
Core’s CBlockIndex::GetMedianTimePast, whose window is however many of the eleven exist: nearer the genesis than that it is the whole chain, and the median of an even number of times is the later of the two middle ones – sort and take the middle index, as Core’s own pointer arithmetic does.
- btclib.block.header_context.next_bits_required(header: BlockHeader, parent: BlockHeader, parent_height: int, parent_of: Callable[[BlockHeader], BlockHeader], consensus: ConsensusParams) bytes[source]¶
Return the compact target header, on this parent, has to carry.
Core’s GetNextWorkRequired and CalculateNextWorkRequired combined, the min-difficulty walk included: the target moves once every consensus.difficulty_adjustment_interval blocks and is the parent’s the rest of the time, unless the network allows min-difficulty blocks, in which case _min_difficulty_bits answers instead.
Where the network enforces BIP94 (consensus.enforce_bip94) and header opens a new difficulty period, this also asks Core’s own time-timewarp-attack question – whether header is timestamped more than MAX_TIMEWARP seconds behind its own parent – and raises rather than returning a target for it: Core asks it in ContextualCheckBlockHeader, apart from GetNextWorkRequired, but it reads exactly the data this function already holds at exactly the height this function already singles out, so it is answered here instead of asking every caller to open a period boundary a second time.
Core checks bad-diffbits first and unconditionally, ahead of time-too-old, the timewarp bound and time-too-new (ContextualCheckBlockHeader, src/validation.cpp at bitcoin/bitcoin@9be056a8a7). Folding the timewarp question in here does not preserve that order: a header failing both bad-diffbits and the timewarp bound never gets a required_bits out of this function at all, so the comparison Block.assert_valid_contextual would make against it never runs, and no caller-side reordering recovers it – what such a header is reported as failing is the timewarp bound, not the wrong target. It is refused either way, by Core and by this library; only the reported reason can differ, for a header that fails both.
At a period boundary and consensus.enforce_bip94, the retarget scales the period’s own first target rather than the parent’s, which is what keeps a period’s real difficulty from being overwritten by a min-difficulty block mined at its very end.
btclib.block.limits module¶
The consensus limits on a block, with Bitcoin Core’s names.
Core declares all but MAX_FUTURE_BLOCK_TIME in consensus/consensus.h, and that one in chain.h, beside the wider window the wallet compares its own timestamps against; it is a consensus bound all the same, and ContextualCheckBlockHeader rejects time-too-new with it.
A module of its own, as script/limits.py is and for the same reason: block.py is the dataclass and its serialization, while each name here is a rule about a block being accepted. WITNESS_SCALE_FACTOR is not a limit but the unit the other two are expressed in – a byte outside the witness weighs four, and so does one legacy signature check – which is why it is here rather than beside the arithmetic that reads it.
It and MAX_BLOCK_WEIGHT are defined in btclib.consensus and re-exported here, which is a layering fact and not a second home for them: what a transaction and a witness may declare is arithmetic on the block that has to hold them, and neither btclib.tx nor btclib.script can import this package. btclib.consensus says why; a caller reading a block’s rules still names this module, which is where the rest of Core’s header is.
Some of consensus.h’s constants are deliberately absent. MAX_BLOCK_SERIALIZED_SIZE is marked in Core’s own comment as a buffer bound and not a network rule, the weight being what consensus caps. COINBASE_MATURITY is a rule about spending an output, so it needs the chain the output was created on: btclib.tx.coin.Coin carries that height, and the constant is btclib.tx.limits’s, beside btclib.tx.tx_context.assert_coinbase_maturity, which reads it.
MAX_TIMEWARP is here and not among those: it is BIP94’s bound on the first block of a new retarget period, checked against that block’s own parent – the last block of the period before it – so it needs one header rather than the whole chain, which is what makes it a bound rather than a rule of its own. btclib.block.header_context.next_bits_required is where it is read, behind ConsensusParams.enforce_bip94.
MIN_SERIALIZABLE_TRANSACTION_WEIGHT is here, where its neighbour MIN_TRANSACTION_WEIGHT is not, and the pair is what says why: the second is the smallest a valid transaction can be and is fee estimation’s, the first the smallest one that deserializes – so it is the one a parser divides MAX_BLOCK_WEIGHT by to bound how many transactions a block may declare before it allocates for them (issue #569). btclib.tx.limits derives the same kind of bound for a transaction’s own inputs and outputs.
btclib.block.merkle_proof module¶
Verification of a merkle branch against a block header’s merkle root.
The verifier’s side of the tree btclib.block.Block builds: given a txid, the siblings on its way up and its position among the block’s transactions, recompute the root and compare it with the header’s. That is what Core’s verifytxoutproof answers and what gettxoutproof produces the input for, and it is the arithmetic every light client runs.
The arithmetic itself is hashes.merkle_root_from_branch, next to the functions that build a root; what lives here is the half of the hardening that has to know what a transaction is, CVE-2017-12842, plus the byte-order convention. A txid and a header’s merkle_root are handled here the way Tx.id and BlockHeader.merkle_root give them – reversed for display, which is also how an explorer or an RPC prints them – and so is every sibling of the branch.
A proof is evidence only together with the header that carries the root: this module answers “the tree with this root contained this leaf”, and nothing about whether that root is on the most-work chain.
- btclib.block.merkle_proof.assert_as_valid(txid: bytes | str | bytearray | memoryview, branch: Sequence[bytes | str | bytearray | memoryview], index: int, merkle_root: bytes | str | bytearray | memoryview) None[source]¶
Raise unless the branch proves that txid is in the tree of merkle_root.
index is the transaction’s position in the block, counted from zero; branch is one sibling per level, bottom-up. txid, the siblings and merkle_root are all in the reversed order they are displayed in, which is what Tx.id and BlockHeader.merkle_root hold.
- btclib.block.merkle_proof.verify(txid: bytes | str | bytearray | memoryview, branch: Sequence[bytes | str | bytearray | memoryview], index: int, merkle_root: bytes | str | bytearray | memoryview) bool[source]¶
Return True if the branch proves that txid is in the tree of merkle_root.
See assert_as_valid, which this wraps and which says why a branch was refused.
btclib.block.mining module¶
Candidate block headers, and a toy search for the nonce that solves one.
A toy, and the word is meant: mine hashes one nonce at a time in Python, in one process, over a header it re-serializes on every evaluation. That is some five orders of magnitude short of what a single mainnet block needs, so what this is for is a regtest-grade target, a test, or watching the search work.
What it is not a toy about is the header it produces. The merkle root comes from the same function Block.assert_valid_merkle_root checks against, and the solved header satisfies assert_valid_pow for a network whose pow limit the bits are within – REGTEST_POW_LIMIT_BITS for a target of that grade, since mainnet’s is the default there and refuses one. So the result is a block every other implementation accepts, at a difficulty nobody has to be convinced by.
- btclib.block.mining.candidate_block_header(previous_block_hash: bytes | str | bytearray | memoryview, transactions: Sequence[Tx], time: datetime, bits: bytes | str | bytearray | memoryview, *, version: int = 536870912) BlockHeader[source]¶
Return the unsolved header committing to a list of transactions.
Everything the header needs except the work: the merkle root is computed here, and the nonce starts at zero for mine to search from. The result is structurally valid – assert_valid passes, serialize and hash work – and has no proof-of-work, which is the state a header is in while it is being mined.
A transaction list whose merkle tree is the CVE-2012-2459 mutation of a shorter one is refused: the header would commit to both lists, so it is not a candidate for the one at hand.
- btclib.block.mining.mine(header: BlockHeader, max_tries: int = 1048576) BlockHeader | None[source]¶
Return the header solved by a nonce, or None if none was found.
The search runs from the nonce the candidate carries and stops at max_tries evaluations or at the end of the four-byte field, whichever comes first, so it always terminates. None is the honest answer to a bounded search: the target may still be satisfiable by a nonce past the bound.
Exhausting the field is not the end of mining, which is why this is a toy rather than a miner. A real one then changes what it is hashing – the extranonce in the coinbase script_sig, the timestamp, the transaction set – and searches the four bytes again over the new merkle root. Building that header again is candidate_block_header.
The caller’s header is left alone: what comes back is a copy.
btclib.block.proof_of_work module¶
Proof-of-work arithmetic: compact targets, retargeting, work, hash rate.
Pure functions over the four bits bytes a header carries and the times two headers carry, deliberately: which chain is best, what the next target is and how fast the network hashes are three questions asked of several competing chains at once, and a function taking a chain object could answer them for one. BlockHeader supplies the inputs and this module does the arithmetic; nothing here reads or builds a header.
Bitcoin Core’s pow.cpp and arith_uint256.cpp are the reference for every value returned. The functions are named after what they answer rather than after Core’s spelling – bits_from_target is GetCompact, target_from_bits is SetCompact, next_bits is CalculateNextWorkRequired, block_work is GetBlockProof – and each docstring names its counterpart.
SetCompact answers three things at once, the number and two out-parameters, so it is two functions here: target_from_bits is the number and raises where fOverflow is set, is_negative_bits is fNegative. Refusing a header on either takes both, which is what BlockHeader.assert_valid_pow asks.
- btclib.block.proof_of_work.bits_from_target(target: bytes | str | bytearray | memoryview) bytes[source]¶
Return the compact bits denoting a target, rounded down.
The inverse of target_from_bits, i.e. Bitcoin Core’s GetCompact, and lossy in the direction that keeps the target harder: the significand holds three bytes, so everything below them is dropped. A target that came from bits is recovered exactly.
The sign bit of the significand is what makes this more than a change of base. The compact form reads 0x00800000 as “negative”, so a significand whose high bit is set is divided by 256 and the exponent raised – 0x800000 is written 0x04008000, four bytes rather than three, and never 0x03800000, where that bit is the sign and SetCompact masks it off, leaving four bytes that denote zero. is_negative_bits is the flag itself, for the other direction.
- btclib.block.proof_of_work.block_work(bits: bytes | str | bytearray | memoryview) int[source]¶
Return the expected number of hashes a block of this target costs.
A hash satisfies the target with probability (target + 1) / 2^256, so 2^256 / (target + 1) evaluations are expected before one does. This is the block’s contribution to the chain work, and Bitcoin Core spells it GetBlockProof.
Core answers 0 for a zero target, and for the two SetCompact flags besides, because GetBlockProof doubles as the gate that keeps an invalid header from being credited with work. Here both are exceptions instead: target_from_bits raises on the overflow, and a zero target – which no hash can ever satisfy, so no block can ever carry it – raises here rather than being reported as free.
- btclib.block.proof_of_work.chain_work(bits_sequence: Sequence[bytes | str | bytearray | memoryview]) int[source]¶
Return the cumulative work of the blocks carrying these bits.
Which of two chains is best is this number’s comparison, not a height comparison: a longer chain of easier blocks is not the one with the most work behind it, and only the second is expensive to replace. Bitcoin Core accumulates the same sum as nChainWork.
- btclib.block.proof_of_work.hash_rate(difficulty: float, timespan: float, block_count: int = 1) float[source]¶
Return the hashes per second a window of blocks implies.
A block of difficulty d costs d * 2^32 hash evaluations on average, so block_count of them found over timespan seconds put the network at that many hashes per second. BlockHeader.difficulty supplies the first argument, and the timestamps of the window’s ends the second.
This is an estimate of a quantity nobody can measure, and a noisy one: hashing is a Poisson process, so the timespan of n blocks is a sum of n exponential intervals and its relative standard deviation is 1/sqrt(n) – 100% over a single block, 8% over a day’s 144, and still 2% over a whole 2016-block window. A number that has moved by less than that has not moved.
Two things also make the inputs less solid than they look. The timestamps are the miners’ own, constrained only by the median of the last eleven blocks below and two hours ahead of the node’s clock above, so a short window’s timespan can be negative in the middle of it; Core’s getnetworkhashps takes the minimum and the maximum time over the window rather than its ends for exactly that reason. And a window spanning a retarget has no single difficulty to be given here: sum the block_work of the blocks in it and divide by the timespan instead, which is what Core does, and which this agrees with to within the 1/65536 by which the genesis target falls short of 2^224.
- btclib.block.proof_of_work.is_negative_bits(bits: bytes | str | bytearray | memoryview) bool[source]¶
Return whether the compact bits denote a negative number.
Bitcoin Core’s fNegative, the flag SetCompact reports beside the value: 0x00800000 of the significand is a sign and not magnitude, so bits carrying it denote a number below zero, which no target is and no header may claim. CheckProofOfWork refuses such a header, and BlockHeader.assert_valid_pow is where btclib does. target_from_bits masks the bit off and answers the magnitude alone, which is what makes the flag a question of its own.
A significand of zero has no sign, which is Core’s nWord != 0 &&: 0x03800000 denotes zero rather than negative zero, the sign bit being all there is of it. The magnitude asked about is the one the exponent has already been applied to, as it is in Core, so 0x018000ff is zero as well – the only byte its masked significand holds is shifted out by an exponent of 1. And it is the sign of the number the four bytes denote, not the sign of the target, which is unsigned and cannot carry the answer – hence a predicate, where Core has an out-parameter.
- btclib.block.proof_of_work.next_bits(bits: bytes | str | bytearray | memoryview, first_block_time: datetime, last_block_time: datetime, *, pow_limit_bits: bytes | str | bytearray | memoryview = b'\x1d\x00\xff\xff') bytes[source]¶
Return the compact target of the difficulty period that follows.
bits is what the last block of the ending period carries, last_block_time its timestamp and first_block_time the timestamp of the block retarget_first_height names – 2015 blocks earlier, which is the off-by-one documented there.
The new target is the old one scaled by the measured timespan over the two weeks aimed at, so a period mined too fast tightens it. The timespan itself is clamped to a quarter and to four times two weeks before the scaling, which is what bounds a single retarget to a factor of four either way; the result is then clamped to the network’s easiest target and re-encoded, and the rounding of that re-encoding is part of the answer.
Bitcoin Core spells this CalculateNextWorkRequired.
- btclib.block.proof_of_work.retarget_first_height(last_height: int) int[source]¶
Return the height the retarget window is measured from.
The window ends at last_height, the last block of a difficulty period, and this is the first block of that same period: 2015 blocks back, not 2016.
That is the off-by-one Bitcoin Core keeps for compatibility. The period holds 2016 blocks but only 2015 intervals between their timestamps, and the retarget divides the measured timespan by two weeks all the same, so the difficulty is set as if 2016 intervals had been observed and blocks come out roughly 0.05% faster than the ten minutes aimed at. Fixing it would be a hard fork over a rounding error, so GetNextWorkRequired still reads nHeight - (DifficultyAdjustmentInterval() - 1).
- btclib.block.proof_of_work.target_from_bits(bits: bytes | str | bytearray | memoryview) bytes[source]¶
Return the 32-byte target the compact bits denote.
The target yyzzww * 256^(xx-3) is represented by the 4 bytes ‘bits’ xxyyzzww. Bitcoin Core spells this SetCompact.
The high bit of yy is the sign of that number and not part of it, so it is masked off here and answered by is_negative_bits: a target is what a hash is compared against, and 0x1d80ffff denotes the genesis target with a sign, not one 2^7 easier.
Module contents¶
Blocks: header and block, their rules, proof of work, merkle proofs.
- class btclib.block.BasicBlockFilter(block_hash: bytes | str | bytearray | memoryview = b'', element_count: int = 0, encoded_set: bytes | str | bytearray | memoryview = b'', *, check_validity: bool = True)[source]¶
Bases:
objectThe BIP158 basic filter of one block.
The block hash the filter is keyed by, the number of elements it holds, and the Golomb-Rice coded set of their hashes. The hash is in the display order BlockHeader.hash gives, and is a field rather than something read back out of the bytes: BIP157 sends a filter and the hash of its block as two things, the serialization below being the count and the set alone.
match answers “may this block touch that script”, never “does it”: a Golomb-coded set is a probabilistic structure, and one query in BASIC_FILTER_M is a false positive by construction.
- assert_valid() None[source]¶
Refuse a filter the serialized bytes could not hold.
The block hash width, the element count, and then the set itself: decoding it is the only way to know that it holds the number of elements it declares, that the bits end where the octets do, and that nothing follows them.
- property element_hashes: list[int]¶
Return the element hashes the set holds, sorted.
What the elements were is not recoverable – a filter holds their SipHash images and not the scripts – so this is what a caller comparing two filters, or counting how full one is, has to work with. match is the question about a script.
- classmethod from_block(block: Block, prevout_scripts: Sequence[bytes | str | bytearray | memoryview], *, check_validity: bool = True) BasicBlockFilter[source]¶
Return the basic filter of a block whose prevouts are resolved.
BIP158’s contents rule: the script of every output that is not an OP_RETURN one, and the previous output script of every input of every transaction but the coinbase. An empty script is a “nil” item the BIP excludes on both sides, and the elements are a set, so a script the block repeats weighs once.
prevout_scripts is one script per non-coinbase input, in the order the block spends them, and it is the caller’s: a block does not carry the outputs it spends. The count is checked against the block, which is what turns a caller passing the wrong list into an error rather than into a filter that is quietly not the one the network computed. prevout_scripts_from_utxos builds the list from a mapping for a caller that holds one.
- property hash: bytes¶
Return the hash of the serialized filter, in display order.
Core’s BlockFilter::GetHash, a double SHA256 over the octets serialize writes; reversed, as every other hash this library hands out is.
- header(previous_header: bytes | str | bytearray | memoryview) bytes[source]¶
Return the filter header that chains this filter to the previous.
filter_header over this filter’s own hash: the module function is the general form, taking the hash a cfheaders message carries where the filter itself was never sent.
- match(element: bytes | str | bytearray | memoryview) bool[source]¶
Answer whether the filter may hold the element.
- match_any(elements: Iterable[bytes | str | bytearray | memoryview]) bool[source]¶
Answer whether the filter may hold any of the elements.
Both sides are sorted and walked once, which is Core’s MatchInternal: the queries are hashed into the same range and compared against the values as they decode, so a filter is read once however many elements are asked about.
False for an empty set of elements, and false for an element the filter cannot hold – an empty script, or the script of an OP_RETURN output, neither of which is ever put in one.
- classmethod parse(data: BytesIO | bytes | str | bytearray | memoryview, block_hash: bytes | str | bytearray | memoryview = b'', *, check_validity: bool = True) BasicBlockFilter[source]¶
Return the filter these octets encode, for that block hash.
The whole of the octets: a Golomb-coded set carries no length of its own, only the count of the values coded in it, so the filter is however many octets it takes to hold them and there is no assert_no_trailing to run. What would have been trailing data is caught a level down, _decode refusing an octet the deltas never reached.
block_hash is the caller’s because the serialization does not carry it – BIP157’s cfilter message names the block beside the filter – and without it nothing could be matched: the key of the SipHash is derived from it. The default is the empty default of the constructor and not a filter keyed on nothing: assert_valid refuses it for its width, so a caller that omits the hash is told which argument it left out.
- class btclib.block.Block(header: BlockHeader, transactions: Sequence[Tx] | None = None, *, check_validity: bool = True)[source]¶
Bases:
objectA block: its header and the transactions the header commits to.
assert_valid is Core’s CheckBlock – what the bytes answer for themselves, proof-of-work included; the rules that need a height or a clock are assert_valid_contextual, taking a BlockContext.
- assert_valid(pow_limit_bits: bytes | str | bytearray | memoryview = b'\x1d\x00\xff\xff') None[source]¶
Refuse what Core’s CheckBlock refuses, in Core’s order.
The header and its proof-of-work, the size bounds, exactly one coinbase and it first, every transaction on its own, the sigop bound, the merkle root, the witness commitment, the weight. Height and clock rules are assert_valid_contextual’s.
pow_limit_bits is forwarded to assert_valid_pow, whose docstring says why the network’s easiest target is the caller’s to state and why mainnet’s is the default. It is a parameter here and not of __init__, parse or serialize: those three call this to answer whether the bytes are a block, and a block of another network is built with check_validity=False and then asked, which is the same two steps a caller already takes to build a header being mined.
- assert_valid_coinbase_height(height: int) None[source]¶
Assert that the coinbase commits to a height (BIP34, bad-cb-height).
A byte comparison, as Core’s is: the coinbase script_sig must start with CScript() << nHeight, so a height pushed any other way than the shortest is refused although it decodes to the right number. Block.height is the decoder, and comparing what it returns would accept a commitment no other node does – bip34_commitment is what the comparison is against.
Which height, and whether BIP34 is in force at all, are the caller’s to say: the second is BlockContext.is_bip34_active, and assert_valid_contextual is what applies it. Nothing is skipped here, so a caller that knows the rule binds can ask for it directly – which is the only way to ask it of a block whose height is all that is known about its place in a chain.
- assert_valid_contextual(context: BlockContext) None[source]¶
Assert the rules a block cannot be checked against on its own.
Bitcoin Core’s ContextualCheckBlockHeader and ContextualCheckBlock, as far as a height and a clock reach: bad-diffbits and time-too-old wherever the caller has walked the chain for them, time-too-new always, and bad-cb-height wherever BIP34 is in force. In that order, which is Core’s – the header is checked before the block it heads, and within the header proof-of-work before the clock.
Separate from assert_valid, which is CheckBlock: what the bytes answer for themselves, and therefore what Block.parse can ask. Both are asked of a block being accepted, and by whoever has the context; neither implies the other.
bad-diffbits and time-too-old are the two rules BlockContext.median_time_past and .required_bits answer for, and each is skipped where the field is None – a caller that has not walked the chain for it, most of them until now. The rest of Core’s two functions still needs more than a context: bad-version the activation heights of BIP34, BIP66 and BIP65, bad-txns-nonfinal every transaction’s lock time against the same median time past. Each becomes a field of BlockContext once the chain state it reads is there to put in one.
- assert_valid_length() None[source]¶
Assert the size limits of Core’s CheckBlock (bad-blk-length).
Two comparisons against MAX_BLOCK_WEIGHT, and neither of them is the weight: the transaction count times WITNESS_SCALE_FACTOR – no transaction serializes to less than a byte, and a byte outside the witness weighs four, so a block holds at most a quarter of the cap in transactions – and the stripped size times WITNESS_SCALE_FACTOR. The second is what real blocks sit against: 3,954,076 of 4,000,000 for block 481,824, 98.9% of the cap. The weight itself is bounded by assert_valid_weight, where Core bounds it.
The count is compared first, as in Core’s single condition, and that is what keeps this cheap: a list too long to be a block is refused without serializing it.
- assert_valid_merkle_root() None[source]¶
Refuse a header whose merkle root is not the transactions’.
The CVE-2012-2459 mutation flag is refused too, as Core’s bad-txns-duplicate; the comment below carries the reasoning.
- assert_valid_sig_op_count() None[source]¶
Assert the sigop bound of Core’s CheckBlock (bad-blk-sigops).
The legacy count of every script in the block, times WITNESS_SCALE_FACTOR, against MAX_BLOCK_SIGOPS_COST – i.e. 20,000 legacy signature checks. It is the only sigop rule reachable from the bytes: what Core adds in ConnectBlock is counted over the outputs being spent, which are in other blocks.
The largest answer this library has a block for is block 481,824’s 3,409, so a block that breaks this rule has to be built for the purpose. That is what makes the arithmetic the thing worth testing, and script.sig_ops is where it happens.
- assert_valid_structure() None[source]¶
Refuse what Core’s CheckBlock refuses, proof-of-work excepted.
The size bounds, exactly one coinbase and it first, every transaction on its own, the sigop bound, the merkle root, the witness commitment, the weight – everything assert_valid asks except BlockHeader.assert_valid and assert_valid_pow, which it calls immediately before this and which a pre-mining candidate cannot pass. block.build.build_block is the other caller: a header mining.candidate_block_header has already validated structurally, over a block that has no proof-of-work yet and cannot be asked for one, and everything below still has to hold of it – the two coinbases, the over-weight block and the over-the-sigop-bound block this refuses are exactly what a builder must not hand back silently.
- assert_valid_weight() None[source]¶
Assert the weight bound of BIP141 (bad-blk-weight).
Core asks this in ContextualCheckBlock and not in CheckBlock, though the weight is read off the bytes like everything else, and the reason is the order rather than the context: the coinbase witness is not covered by the block hash, so a block whose weight is over the cap only because that witness was stuffed must not be marked permanently invalid before the commitment to it has been checked. Hence the position here, right after assert_valid_witness_commitment, and hence the same rule twice at different strengths – assert_valid_length bounds what a legacy node relays, this bounds the block segwit nodes see.
- assert_valid_witness_commitment() None[source]¶
Assert that the coinbase commits to the witness data (BIP141).
The merkle root of the header is computed over txids, which by segwit’s design leave every witness out: without this check the witnesses of a block can be replaced wholesale, header and root untouched, and the signatures they carry are worth nothing.
- classmethod from_dict(dict_: Mapping[str, Any], *, check_validity: bool = True) Block[source]¶
Build a Block from the dict shape to_dict writes.
- property height: int | None¶
Return the height committed into a BIP34 coinbase script_sig.
Version 2 blocks commit block height into the coinbase script_sig.
https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki Block 227,835 (2013-03-24 15 :49: 13 GMT) was the last version 1 block.
This is the reader and not the check: it decodes whatever the coinbase pushed, where consensus compares bytes. assert_valid_coinbase_height is the check.
- classmethod parse(data: BytesIO | bytes | str | bytearray | memoryview, *, check_validity: bool = True) Block[source]¶
Return a Block by parsing binary data.
- serialize(include_witness: bool = True, *, check_validity: bool = True) bytes[source]¶
Return the wire serialization: header, count, transactions.
include_witness False gives the block as a legacy node relays it, every witness stripped – a bool and nothing else, for the reason Tx.serialize states.
- property sig_op_count: int¶
Return the legacy sigop count, summed over the transactions.
What CheckBlock sums to enforce MAX_BLOCK_SIGOPS_COST; see script.sig_ops.sig_op_count for what “legacy” leaves out and why nothing here can add it.
- property stripped_size: int¶
Return the size of the block as a legacy node sees it.
Core’s GetSerializeSize(TX_NO_WITNESS(block)), and the quantity assert_valid_length bounds: the whole block with every witness left out, which is the serialization the witness discount is expressed against and what getblock reports under this name.
- to_dict(*, check_validity: bool = True) dict[str, Any][source]¶
Return the block as a dict of json-friendly values.
The header and each transaction as their own to_dict render them; from_dict reads the same shape back.
- property weight: int¶
Return the block weight, as Core’s GetBlockWeight computes it.
Three times the stripped size plus the size, i.e. four times what a legacy node relays plus the witness bytes, over the block: the eighty bytes of the header and the var_int of the transaction count are part of it, so this is not the sum of the transactions’ weights – 332 more than that sum for block 481,824, 324 for a block holding one transaction. The sum is the number no rule reads; MAX_BLOCK_WEIGHT bounds this one.
- property witness_commitment: bytes | None¶
Return the BIP141 witness commitment, if the coinbase has one.
It is the 32 bytes following the 6a24aa21a9ed prefix in the last coinbase output carrying it, as Core’s GetWitnessCommitmentIndex does: were the first one to win, an output appended to the coinbase could not be told from one the miner meant, and the rule has to be the same one everybody else applies anyway.
- class btclib.block.BlockContext(height: int, now: datetime, bip34_height: int = 227931, median_time_past: int | None = None, required_bits: bytes | None = None, *, check_validity: bool = True)[source]¶
Bases:
objectWhat Block.assert_valid_contextual reads: a height and a clock.
The facts a block cannot answer for itself, supplied by the caller; bip34_height is the chain’s activation height, defaulting to mainnet’s, and median_time_past and required_bits default to None, which skips the rule each answers for.
- assert_valid() None[source]¶
Refuse a negative or non-int height, or a now that is no datetime.
Naive-datetime refusal is assert_valid_time’s, the reader of the clock being where the comparison happens. median_time_past and required_bits are refused only when given – None is what leaves the rule each answers for unchecked, not a value to validate – and _assert_valid_chain_state is where that happens.
- property is_bip34_active: bool¶
Whether the coinbase must commit to the height (BIP34).
Core’s DeploymentActiveAfter(pindexPrev, DEPLOYMENT_HEIGHTINCB), which is this comparison: the rule binds from the activation height on, and not from the block version. A version 1 block at or above it is refused too, by bad-version, which needs the chain and is out of scope here.
- class btclib.block.BlockHeader(version: int = 1, previous_block_hash: bytes | str | bytearray | memoryview = b'', merkle_root: bytes | str | bytearray | memoryview = b'', time: datetime = datetime.datetime(1970, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), bits: bytes | str | bytearray | memoryview = b'', nonce: int = 0, *, check_validity: bool = True)[source]¶
Bases:
objectThe eighty bytes a block is identified and mined by.
Version, previous block hash, merkle root, time, bits, nonce; the hashes and bits are held in display order and reversed on the wire, the time as an aware datetime. assert_valid answers for the eighty bytes alone – proof-of-work and clock checks are the explicit assert_valid_pow and assert_valid_time, a header being mined having neither yet.
- assert_valid() None[source]¶
Refuse a header the eighty bytes could not hold.
Field types, the version and nonce ranges, the timestamp between genesis and the last four-byte instant, the field sizes. Nothing here reads a clock or checks the work: those are assert_valid_time and assert_valid_pow, whose docstrings say why they are separate.
- assert_valid_pow(pow_limit_bits: bytes | str | bytearray | memoryview = b'\x1d\x00\xff\xff') None[source]¶
Assert whether the BlockHeader provides a valid proof-of-work.
Bitcoin Core’s CheckProofOfWork: the target the bits denote must be one the network allows, and the hash must not exceed it. The range of the target is checked first and is four questions, which are Core’s DeriveTarget – a negative bits value, a zero target, a target 32 bytes cannot hold, a target above the network’s limit. Each is refused by name, where DeriveTarget returns a bare nullopt for all four: a caller of this library is told which rule it broke, and the four are as many different mistakes.
pow_limit_bits is the network’s easiest target, mainnet’s by default as next_bits takes it, and it is the caller’s to state: a header carries no claim about which network it belongs to, so nothing here can read one. Passing REGTEST_POW_LIMIT_BITS is what makes a regtest header acceptable – and what keeps a regtest one from passing for mainnet, which is the hole this closes.
Not called by assert_valid, which answers the other question: whether the eighty bytes are a well-formed header. A header being mined is structurally valid and has no proof-of-work yet, so a candidate could not otherwise be built, serialized, or hashed through the ordinary API – and hashing it is what mining is.
Block.assert_valid does call this, as Bitcoin Core’s CheckBlock calls CheckProofOfWork by default: a Block is a block, and the proof-of-work is what its transactions are committed by.
- assert_valid_time(now: datetime) None[source]¶
Assert that the timestamp is not too far ahead of a clock.
Bitcoin Core’s time-too-new, from ContextualCheckBlockHeader: a header more than MAX_FUTURE_BLOCK_TIME ahead of the current time is refused, which is what bounds how far a miner can push a timestamp forward – and the reason it is a bound rather than an equality is that the network has no clock of its own to check against.
now is the caller’s, and never datetime.now() read here: a consensus rule taking the wall clock would have one machine accept the block another refuses, and no test of it could be written that did not depend on the day it ran on. Which is also why this is not called by assert_valid, and why Block.assert_valid does not reach it: those two answer for the eighty bytes and for the block, and a clock is neither.
time-too-old is the other half of the pair Core checks beside this one, and it is not asked here: it is the median time past of eleven ancestors, which needs the chain rather than a datum this method takes. btclib.block.header_context.median_time_past is where the walk lives, and Block.assert_valid_contextual is where the comparison is made, off BlockContext.median_time_past rather than off a callable this method could take instead.
- property difficulty: float¶
Return the BlockHeader difficulty.
Difficulty is the ratio of the genesis block target over the BlockHeader target.
It represents the average number of hash function evaluations required to satisfy the BlockHeader target, expressed as multiple of the genesis block difficulty used as unit.
The difficulty of the genesis block is 2^32 (4*2^30), i.e. 4 GigaHash function evaluations.
- classmethod from_dict(dict_: Mapping[str, Any], *, check_validity: bool = True) BlockHeader[source]¶
Build a BlockHeader from the dict shape to_dict writes.
- classmethod parse(data: BytesIO | bytes | str | bytearray | memoryview, *, check_validity: bool = True) BlockHeader[source]¶
Return a BlockHeader by parsing 80 bytes from binary data.
- btclib.block.bip34_commitment(height: int) bytes[source]¶
Return the height as a coinbase script_sig must commit to it (BIP34).
Bitcoin Core’s CScript() << nHeight, which is where the bytes Block.assert_valid_coinbase_height compares against come from: the shortest encoding of the number, so OP_0 for zero and OP_1 to OP_16 for one to sixteen – one byte, no push at all – and a minimal data push of the script number from seventeen up.
Those first seventeen are not what script.serialize([height]) writes. It pushes the number as data – 0100, 0101 to 0110 – and warns that an op code says the same, which is a defensible encoding of a number and the wrong answer here: a regtest chain has BIP34 in force from height 1, so those seventeen are where the rule binds first and every node on such a chain compares against the op code.
- btclib.block.coinbase_witness_commitment(transactions: Sequence[Tx], nonce: bytes | str | bytearray | memoryview) bytes[source]¶
Return the coinbase’s BIP141 commitment over every witness.
Bitcoin Core’s GenerateCoinbaseCommitment (src/validation.cpp, at bitcoin/bitcoin@9be056a8a7): hash256 of the witness merkle root, concatenated with nonce – the other half of the preimage, which a real block carries in the coinbase’s own witness stack rather than here.
The witness tree is built the way merkle_root_and_mutated_from_transactions builds the txid one, over wtxids instead of txids, with one difference: transactions[0]’s own leaf is BIP141’s all-zero placeholder rather than its wtxid, which is unknowable here – it would have to commit to the very output this function’s own result ends up inside. The mutation flag merkle_root_and_mutated_from_hashes also returns is not read: the witness tree has the shape of the txid one, and two equal wtxids mean two equal transactions, hence two equal txids that assert_valid_merkle_root already rejects.
One implementation, shared between assert_valid_witness_commitment and witness_commitment_output below, for the same reason merkle_root_and_mutated_from_transactions is shared between a header being validated and one being mined: the validator and the builder must not disagree about what a set of transactions hashes to.
- btclib.block.genesis_block(network: str = 'mainnet') Block[source]¶
Return the genesis block of network, built rather than looked up.
A caller wanting only the hash already has it, cheaply, at network_from_name(network).genesis_block; this is for a caller that needs the block itself – a datadir seeding a fresh node, a test fixture – and is willing to pay for one coinbase transaction and one header assembly to get it, in place of a field this library cannot carry without closing issue #147’s cycle.
The block is checked against the network’s own easiest target before it is returned (Block.assert_valid, at that network’s pow_limit_bits), and reproduces the hash Network.genesis_block already carries for the same network – verified for all five in tests/block/genesis_test.py.
- btclib.block.header_at_height(header: BlockHeader, height: int, target_height: int, parent_of: Callable[[BlockHeader], BlockHeader]) BlockHeader[source]¶
Walk back from header, at height, to its ancestor at target_height.
Core’s CBlockIndex::GetAncestor, over a skip list there; this walks parent_of one header at a time, which is the same cost median_time_past already pays to reach its own eleventh ancestor – unbounded here rather than capped at ten, since a caller asking for a BIP68 time-locked input’s own coin height can name any past height, not only one within the last eleven blocks.
- btclib.block.median_time_past(header: BlockHeader, height: int, parent_of: Callable[[BlockHeader], BlockHeader]) int[source]¶
Return the median timestamp of a header and its ten ancestors.
Core’s CBlockIndex::GetMedianTimePast, whose window is however many of the eleven exist: nearer the genesis than that it is the whole chain, and the median of an even number of times is the later of the two middle ones – sort and take the middle index, as Core’s own pointer arithmetic does.
- btclib.block.merkle_root_and_mutated_from_transactions(transactions: Sequence[Tx]) tuple[bytes, bool][source]¶
Return a header’s merkle root over a list of transactions.
The leaves are the transactions serialized without witness data, i.e. their txids, and the root is reversed into the byte order a header carries. See merkle_root_and_mutated_from_hashes for the second returned value, the CVE-2012-2459 flag.
One implementation, because the block builder and the block validator must agree by construction: assert_valid_merkle_root compares this against the header at hand, and mining.py’s candidate header is built from it.
- btclib.block.next_bits_required(header: BlockHeader, parent: BlockHeader, parent_height: int, parent_of: Callable[[BlockHeader], BlockHeader], consensus: ConsensusParams) bytes[source]¶
Return the compact target header, on this parent, has to carry.
Core’s GetNextWorkRequired and CalculateNextWorkRequired combined, the min-difficulty walk included: the target moves once every consensus.difficulty_adjustment_interval blocks and is the parent’s the rest of the time, unless the network allows min-difficulty blocks, in which case _min_difficulty_bits answers instead.
Where the network enforces BIP94 (consensus.enforce_bip94) and header opens a new difficulty period, this also asks Core’s own time-timewarp-attack question – whether header is timestamped more than MAX_TIMEWARP seconds behind its own parent – and raises rather than returning a target for it: Core asks it in ContextualCheckBlockHeader, apart from GetNextWorkRequired, but it reads exactly the data this function already holds at exactly the height this function already singles out, so it is answered here instead of asking every caller to open a period boundary a second time.
Core checks bad-diffbits first and unconditionally, ahead of time-too-old, the timewarp bound and time-too-new (ContextualCheckBlockHeader, src/validation.cpp at bitcoin/bitcoin@9be056a8a7). Folding the timewarp question in here does not preserve that order: a header failing both bad-diffbits and the timewarp bound never gets a required_bits out of this function at all, so the comparison Block.assert_valid_contextual would make against it never runs, and no caller-side reordering recovers it – what such a header is reported as failing is the timewarp bound, not the wrong target. It is refused either way, by Core and by this library; only the reported reason can differ, for a header that fails both.
At a period boundary and consensus.enforce_bip94, the retarget scales the period’s own first target rather than the parent’s, which is what keeps a period’s real difficulty from being overwritten by a min-difficulty block mined at its very end.
- btclib.block.prevout_scripts_from_utxos(block: Block, utxos: Mapping[OutPoint, TxOut]) list[bytes][source]¶
Return the previous output scripts from_block asks for.
The typed adapter over a utxo set: one script per non-coinbase input, in the order the block spends them. OutPoint is frozen and hashable so that it can key such a mapping, and an input the mapping does not answer for is refused by name – a filter built from a silently missing prevout is a filter that omits an element, which no later check would catch.
- btclib.block.witness_commitment_output(transactions: Sequence[Tx], nonce: bytes | str | bytearray | memoryview) TxOut[source]¶
Return the zero-valued coinbase output committing to every witness.
Nothing spends this output – it exists for Block.witness_commitment to read back, the way a real miner’s coinbase carries one. BIP141’s own aa21a9ed header goes in front of coinbase_witness_commitment’s 32 bytes, inside an OP_RETURN push, which is _COMMITMENT_PREFIX’s own shape: this is the one place that constant is written to rather than compared against.