blockchainkit.structures#

Authenticated data, signed transactions, immutable blocks, and fork state.

Merkle trees and proofs, signed transfers, blocks, ledger state, and cumulative-work fork selection.

Every public name below is re-exported by the subpackage: import it as bk.structures.<name>. The plotting helpers are the exception: import them explicitly from blockchainkit.structures.visualizers, which loads Matplotlib.

Types and results#

Result containers for blockchainkit.structures.

class blockchainkit.structures.core.base.MerkleProof(index, leaf_count, siblings)[source]#

Bases: object

Leaf position, leaf count, and bottom-up siblings (None for promotion).

Parameters:
index: int#
leaf_count: int#
siblings: tuple[bytes | None, ...]#
class blockchainkit.structures.core.base.ProofStep(side, sibling, digest)[source]#

Bases: object

One level of Merkle-proof verification, from the leaf toward the root.

Variables:
  • side ({"left", "right", "promoted"}) – Where the sibling sits: "left" means hash(sibling || current), "right" means hash(current || sibling), and "promoted" means the node had no sibling and moved up unchanged.

  • sibling (bytes or None) – The sibling digest from the proof (None when promoted).

  • digest (bytes) – The node digest after this step.

Parameters:
side: str#
sibling: bytes | None#
digest: bytes#
class blockchainkit.structures.core.base.MerkleTrace(leaf_digest, steps, root, valid)[source]#

Bases: object

Every step of reconstructing a root from a leaf and its proof.

Variables:
Parameters:
leaf_digest: bytes#
steps: tuple[ProofStep, ...]#
root: bytes#
valid: bool#
class blockchainkit.structures.core.base.OutPoint(txid, index)[source]#

Bases: object

A reference to one coin: the creating transaction’s id and the output index.

Parameters:
txid: bytes#
index: int#
class blockchainkit.structures.core.base.Coin(owner, amount)[source]#

Bases: object

An unspent output: who owns it and how much it holds.

Parameters:
owner: str#
amount: int#
class blockchainkit.structures.core.base.SparseMerkleProof(key, value, siblings)[source]#

Bases: object

Siblings from the leaf up, and the value at the key (None if absent).

Parameters:
key: bytes#
value: bytes | None#
siblings: tuple[bytes, ...]#
class blockchainkit.structures.core.base.MMRProof(index, size, siblings, peaks)[source]#

Bases: object

Path from a leaf to its peak, plus every peak and the range size.

Parameters:
index: int#
size: int#
siblings: tuple[bytes, ...]#
peaks: tuple[bytes, ...]#

Constructions and protocols#

Domain-separated Merkle trees with explicit leaf-count commitments.

Odd nodes are promoted unchanged. Roots bind the leaf count to avoid ambiguity between differently shaped trees. This is not Bitcoin’s format.

class blockchainkit.structures.systems.merkle.MerkleTree(leaves)[source]#

Bases: object

Build a tree from an iterable of byte strings.

Parameters:

leaves (collections.abc.Iterable of bytes) – Ordered payloads, hashed as SHA256(0x00 || payload).

Examples

>>> from blockchainkit.structures import MerkleTree, verify_proof
>>> tree = MerkleTree([b"alice", b"bob", b"carol"])
>>> verify_proof(b"bob", tree.proof(1), tree.root)
True
property root: bytes#

Return the immutable 32-byte, leaf-count-bound root.

property leaf_count: int#

Return the number of leaves the root commits to.

consistency_proof(old_size)[source]#

Prove that this tree extends its first old_size leaves (RFC 6962).

Parameters:

old_size (int)

Return type:

tuple[bytes, …]

property levels: tuple[tuple[bytes, ...], ...]#

Return every level’s digests, from leaf hashes up to the top digest.

The top digest is not yet the root: the root also binds the leaf count. An empty tree has a single empty level.

proof(index)[source]#

Return a logarithmic-size inclusion proof at a zero-based position.

Parameters:

index (int)

Return type:

MerkleProof

blockchainkit.structures.systems.merkle.verify_proof(leaf, proof, root)[source]#

Verify payload, position, shape, count, and root; reject malformed proofs.

Parameters:
Return type:

bool

blockchainkit.structures.systems.merkle.trace_proof(leaf, proof, root)[source]#

Reconstruct the root step by step, recording each level.

Unlike verify_proof(), a well-formed proof that reconstructs the wrong root still returns its full trace (with valid=False), so an experiment can show where a tampered leaf diverges.

Raises:

ValueError – The proof is malformed: wrong shape, count, index, or sibling type.

Parameters:
Return type:

MerkleTrace

Examples

>>> from blockchainkit.structures import MerkleTree, trace_proof
>>> tree = MerkleTree([b"a", b"b", b"c"])
>>> [step.side for step in trace_proof(b"c", tree.proof(2), tree.root).steps]
['promoted', 'left']
blockchainkit.structures.systems.merkle.consistency_proof(tree, old_size)[source]#

Prove that the first old_size leaves of tree form an earlier tree.

The proof (RFC 6962, section 2.1.2) lists the subtree digests needed to rebuild both the old and the new top digest from shared parts, so a verifier can check that the log only appended. Because blockchainkit’s roots also bind the leaf count, the verifier cannot read the old top digest off the old root; when old_size is a power of two (the case where RFC 6962 omits it) the proof starts with it. Also available as MerkleTree.consistency_proof().

Parameters:
Return type:

tuple[bytes, …]

blockchainkit.structures.systems.merkle.verify_consistency(old_size, old_root, new_size, new_root, proof)[source]#

Check that the tree with old_root is a prefix of the tree with new_root.

Follows RFC 9162, section 2.1.4.2, on top digests, then checks both count-bound roots. Malformed or mismatched proofs return False.

Examples

>>> from blockchainkit.structures import MerkleTree, verify_consistency
>>> leaves = [bytes([i]) for i in range(7)]
>>> old, new = MerkleTree(leaves[:3]), MerkleTree(leaves)
>>> verify_consistency(3, old.root, 7, new.root, new.consistency_proof(3))
True
Parameters:
Return type:

bool

blockchainkit.structures.systems.merkle.bitcoin_merkle_root(leaves)[source]#

Return a root in Bitcoin’s convention: double SHA-256, odd nodes duplicated.

Shown for contrast with MerkleTree. With no domain separation and no leaf count, the lists [a, b, c] and [a, b, c, c] share a root (CVE-2012-2459), which let an attacker make nodes reject a valid block. MerkleTree promotes odd nodes and binds the count instead.

>>> from blockchainkit.structures import bitcoin_merkle_root
>>> bitcoin_merkle_root([b"a", b"b", b"c"]) == bitcoin_merkle_root([b"a", b"b", b"c", b"c"])
True
Parameters:

leaves (Iterable[bytes])

Return type:

bytes

Merkle mountain ranges (2016): an append-only log with cheap updates.

A Merkle tree over n leaves is rebuilt along a whole path when a leaf is added. A mountain range keeps a list of perfect binary trees (“peaks”) of decreasing size, one per 1-bit of n. Appending a leaf adds a peak of size one and merges equal-sized neighbours, like binary addition: on average a constant number of merges. Old peaks are never rewritten, so proofs about old leaves need only the peaks to be refreshed. The root “bags” the peaks.

class blockchainkit.structures.systems.mmr.MerkleMountainRange[source]#

Bases: object

An immutable append-only accumulator of byte strings.

Examples

>>> from blockchainkit.structures import MerkleMountainRange, verify_mmr_proof
>>> mmr = MerkleMountainRange()
>>> for leaf in (b"a", b"b", b"c"):
...     mmr = mmr.append(leaf)
>>> len(mmr.peaks), verify_mmr_proof(b"c", mmr.proof(2), mmr.root)
(2, True)
append(leaf)[source]#

Return a range with one more leaf, merging equal-sized peaks.

Only the new leaf’s hash and the merged nodes are computed: about two hashes per append on average, however long the range.

Parameters:

leaf (bytes)

Return type:

MerkleMountainRange

property peaks: tuple[bytes, ...]#

Peak digests, largest tree first; there is one per 1-bit of the size.

property root: bytes#

Bag the peaks, with the size, into one commitment.

proof(index)[source]#

Return an inclusion proof for the leaf at index.

Parameters:

index (int)

Return type:

MMRProof

blockchainkit.structures.systems.mmr.verify_mmr_proof(leaf, proof, root)[source]#

Rebuild the leaf’s peak, find it among the peaks, and check the bagged root.

Parameters:
Return type:

bool

Sparse Merkle trees (2016): a key-value map with membership and non-membership proofs.

Picture a Merkle tree with one leaf for every possible 256-bit key, almost all empty. Each key’s position is fixed by its hash, so the root is independent of insertion order, and absence is provable: show that the leaf at the key’s position is empty. Empty subtrees have precomputed default digests, so only paths to non-empty leaves are ever hashed.

class blockchainkit.structures.systems.sparse_merkle.SparseMerkleTree(depth=256, items=None)[source]#

Bases: object

An immutable map from byte keys to byte values with a Merkle root.

Parameters:
  • depth (int) – Number of key-hash bits used for the position, 1 to 256. A small depth makes collisions between keys possible; it exists only to make small experiments easy to draw.

  • items (dict[bytes, bytes] | None)

Examples

>>> from blockchainkit.structures import SparseMerkleTree, verify_sparse_proof
>>> tree = SparseMerkleTree().set(b"alice", b"100")
>>> verify_sparse_proof(tree.prove(b"bob"), tree.root)  # Proof that bob is absent.
True
get(key)[source]#

Return the value stored at a key, or None.

Parameters:

key (bytes)

Return type:

bytes | None

set(key, value)[source]#

Return a new tree with key mapped to value.

Parameters:
Return type:

SparseMerkleTree

delete(key)[source]#

Return a new tree without key.

Parameters:

key (bytes)

Return type:

SparseMerkleTree

property root: bytes#

Return the root digest; equal maps give equal roots, in any order.

prove(key)[source]#

Return a proof of the key’s value, or of its absence.

Parameters:

key (bytes)

Return type:

SparseMerkleProof

blockchainkit.structures.systems.sparse_merkle.verify_sparse_proof(proof, root)[source]#

Recompute the root from a key, its claimed value (or absence), and siblings.

The number of siblings is the tree depth. Leaf and node digests carry different prefixes, so a shorter proof cannot pass for a longer one.

Parameters:
Return type:

bool

Bloom filters (1970): compact set membership with false positives but no false negatives.

Bitcoin’s lightweight clients (BIP 37, 2012) sent full nodes a Bloom filter of their addresses, so nodes could forward matching transactions without the client listing its addresses outright. The false positives were meant to give privacy; in practice they leaked much of it.

class blockchainkit.structures.systems.bloom.BloomFilter(size, hashes)[source]#

Bases: object

An array of size bits, set at hashes positions per added item.

An item is reported present if all its positions are set. Items that were added are always found; others are wrongly found with probability about (1 - exp(-k n / m))**k.

Parameters:
  • size (int) – Number of bits m.

  • hashes (int) – Number of positions k per item.

Examples

>>> from blockchainkit.structures import BloomFilter
>>> bloom = BloomFilter(256, 3)
>>> bloom.add(b"alice")
>>> b"alice" in bloom
True
add(item)[source]#

Set the item’s bit positions.

Parameters:

item (bytes)

Return type:

None

property fill_ratio: float#

Fraction of bits set.

static false_positive_rate(size, hashes, items)[source]#

Return Bloom’s estimate (1 - exp(-k n / m))**k.

Parameters:
Return type:

float

static optimal_hash_count(size, items)[source]#

Return the k minimizing false positives, round((m / n) ln 2).

Parameters:
Return type:

int

Lamport’s hash chains (1981): one-time passwords from repeated hashing.

Hash a secret seed n times. The server stores only the last link. To log in, the user reveals the link before it; the server hashes it once, compares, and stores the revealed link as the new anchor. An eavesdropper who captures a password learns a value the server will never accept again, and cannot compute the next one without inverting the hash. This became S/KEY (1995).

blockchainkit.structures.systems.hash_chain.hash_chain(seed, length)[source]#

Return (H(seed), H(H(seed)), ..., H^length(seed)).

>>> from blockchainkit.structures import hash_chain
>>> len(hash_chain(b"seed", 3))
3
Parameters:
Return type:

tuple[bytes, …]

blockchainkit.structures.systems.hash_chain.verify_one_time_password(password, anchor)[source]#

Return whether H(password) equals the stored anchor (constant-time).

Parameters:
Return type:

bool

Immutable signed account transfers and deterministic teaching encodings.

blockchainkit.structures.systems.transaction.address(public)[source]#

Return SHA-256(uncompressed public key) as a 64-character account ID.

Parameters:

public (tuple[int, int])

Return type:

str

class blockchainkit.structures.systems.transaction.Transaction(sender, recipient, amount, nonce, chain_id='blockchainkit-demo', signature=None)[source]#

Bases: object

An integer-valued transfer, signed over network ID and account nonce.

Parameters:
  • sender (tuple of int) – secp256k1 public point.

  • recipient (str) – Lowercase 64-character hexadecimal account identifier.

  • amount (int) – Positive integer units (no floating-point currency amounts).

  • nonce (int) – Sender sequence number, starting at zero.

  • chain_id (str) – Domain that prevents replay onto a different teaching network.

  • signature (blockchainkit.crypto.core.base.SchnorrSignature, optional) – Signature over the canonical unsigned payload.

sender: tuple[int, int]#
recipient: str#
amount: int#
nonce: int#
chain_id: str = 'blockchainkit-demo'#
signature: SchnorrSignature | None = None#
property sender_address: str#

Return the account identifier derived from the sender’s public key.

payload()[source]#

Return the exact bytes signed, including domain and format version.

Return type:

bytes

to_bytes()[source]#

Serialize the unsigned payload and signature without ambiguity.

Return type:

bytes

property txid: bytes#

Return a digest of the signed transaction encoding.

Because it covers the signature, re-signing the same payment changes it: the malleability that segregated witness removed from Bitcoin’s transaction ids. Compare unsigned_id.

property unsigned_id: bytes#

Return a digest of the unsigned payload only, as SegWit’s txid does.

Any valid signature over the same payment gives the same value, so a later transaction can refer to this one before it is confirmed.

is_valid()[source]#

Check the signature; account balance and nonce are checked by Ledger.

Return type:

bool

signed(private, *, signing_nonce=None)[source]#

Return a signed copy, checking that the key matches this sender.

Parameters:
  • private (int)

  • signing_nonce (int | None)

Return type:

Transaction

The unspent-transaction-output (UTXO) model of Bitcoin (2008).

There are no accounts. Value lives in coins, outputs of earlier transactions, each owned by an address. A transaction consumes whole coins as inputs and creates new ones as outputs; any value not assigned to an output is the miner’s fee. A coin can be spent once: double spending is the attempt to use one input twice.

class blockchainkit.structures.systems.utxo.UTXOTransaction(inputs, outputs, witnesses=())[source]#

Bases: object

Spend whole coins and create new ones.

Parameters:
inputs: tuple[OutPoint, ...]#
outputs: tuple[tuple[str, int], ...]#
witnesses: tuple[tuple[tuple[int, int], SchnorrSignature], ...] = ()#
payload()[source]#

Return the bytes each input’s owner signs.

Return type:

bytes

property txid: bytes#

Return the hash of the unsigned payload; outputs are named by it.

signed(privates)[source]#

Return a copy with one signature per input, keys given in input order.

Each witness is the signer’s public key and a Schnorr signature over payload() with an RFC 6979 nonce. Whether the key owns the coin is checked by UTXOSet.apply().

Parameters:

privates (Sequence[int])

Return type:

UTXOTransaction

fee(utxos)[source]#

Return inputs minus outputs: what the miner may claim.

Parameters:

utxos (UTXOSet)

Return type:

int

class blockchainkit.structures.systems.utxo.UTXOSet(coins)[source]#

Bases: object

An immutable set of unspent coins; applying a transaction returns a new set.

Examples

>>> import blockchainkit as bk
>>> alice = bk.structures.address(bk.crypto.public_key(7))
>>> bk.structures.UTXOSet.genesis({alice: 50}).balance(alice)
50
Parameters:

coins (Mapping[OutPoint, Coin])

classmethod genesis(allocations)[source]#

Create one coin per address from an initial allocation.

Parameters:

allocations (Mapping[str, int])

Return type:

UTXOSet

coins_of(owner)[source]#

Return the outpoints of every coin an address owns, sorted.

Parameters:

owner (str)

Return type:

tuple[OutPoint, …]

balance(owner)[source]#

Return the total value of an address’s coins (a wallet’s view).

Parameters:

owner (str)

Return type:

int

apply(tx)[source]#

Validate a transaction and return the set after it.

Raises:

ValueError – An input is spent or unknown, a witness is missing or does not match the coin’s owner, or outputs exceed inputs.

Parameters:

tx (UTXOTransaction)

Return type:

UTXOSet

Immutable blocks with canonical headers and transaction commitments.

class blockchainkit.structures.systems.block.BlockHeader(previous_hash=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', merkle_root=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', height=0, timestamp=0, difficulty=8, nonce=0)[source]#

Bases: object

The 80-byte-style summary a light client downloads instead of a block.

It commits to the block’s transactions through merkle_root alone, so its hash, and therefore its proof of work, can be checked without them. Block.to_header().hash == Block.hash.

Parameters:
  • previous_hash (bytes) – 32-byte digests.

  • merkle_root (bytes) – 32-byte digests.

  • height (int) – As for Block.

  • timestamp (int) – As for Block.

  • difficulty (int) – As for Block.

  • nonce (int) – As for Block.

previous_hash: bytes = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'#
merkle_root: bytes = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'#
height: int = 0#
timestamp: int = 0#
difficulty: int = 8#
nonce: int = 0#
encode()[source]#

Return the canonical bytes that are hashed.

Return type:

bytes

property hash: bytes#

Return SHA-256 of the canonical header.

class blockchainkit.structures.systems.block.Block(previous_hash=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', transactions=(), height=0, timestamp=0, difficulty=8, nonce=0)[source]#

Bases: object

A teaching block, not a Bitcoin/Ethereum wire-format block.

Parameters:
  • previous_hash (bytes) – Parent digest, or 32 zero bytes for genesis.

  • transactions (tuple of blockchainkit.structures.systems.transaction.Transaction) – Ordered signed transfers; copied into an immutable tuple.

  • height (int) – Nonnegative 64-bit integers; timestamps use simulation units.

  • timestamp (int) – Nonnegative 64-bit integers; timestamps use simulation units.

  • nonce (int) – Nonnegative 64-bit integers; timestamps use simulation units.

  • difficulty (int) – Number of required leading zero hash bits, between 0 and 256.

Notes

The Merkle root and the block hash are computed once and cached. A miner never rebuilds the transaction tree: it calls header(nonce=...) with candidate nonces, as real miners vary only the header.

previous_hash: bytes = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'#
transactions: tuple[Transaction, ...] = ()#
height: int = 0#
timestamp: int = 0#
difficulty: int = 8#
nonce: int = 0#
property merkle_root: bytes#

Return the count-bound commitment to ordered signed transactions.

header(nonce=None)[source]#

Return canonical bytes committing to all consensus-relevant fields.

Parameters:

nonce (int, optional) – A candidate nonce to place in the header instead of self.nonce. block.header(nonce=n) equals replace(block, nonce=n).header() without rebuilding the Merkle tree.

Return type:

bytes

to_header(nonce=None)[source]#

Return this block’s header, optionally with a candidate nonce.

Parameters:

nonce (int | None)

Return type:

BlockHeader

property hash: bytes#

Return SHA-256 of the canonical header.

Simplified payment verification: checking a chain of headers without blocks.

Nakamoto’s whitepaper (section 8) observed that a client can verify a payment without downloading the blockchain: keep only the block headers, check that they link and carry proof of work, and ask for a Merkle proof that the transaction is in one of them. Trust shifts to an assumption: the heaviest header chain is the one honest miners extended.

blockchainkit.structures.systems.headers.verify_header_chain(headers)[source]#

Check that headers link by hash and carry their proof of work.

Parameters:

headers (collections.abc.Sequence of blockchainkit.structures.systems.block.BlockHeader) – Consecutive headers, oldest first (not necessarily from genesis).

Returns:

The expected work they represent, the sum of 2**difficulty.

Return type:

int

Raises:

ValueError – The list is empty, a header does not link to its predecessor, or a hash misses its target.

Examples

>>> import blockchainkit as bk
>>> genesis = bk.consensus.mine(bk.structures.Block(difficulty=4)).block
>>> bk.structures.verify_header_chain([genesis.to_header()])
16

Immutable account balances and nonces, updated atomically by signed transfers.

class blockchainkit.structures.systems.ledger.Ledger(balances=None, nonces=None, *, chain_id='blockchainkit-demo')[source]#

Bases: object

An immutable view of account balances and next expected nonces.

Initial balances are a shared simulation configuration, not a minting transaction. All peers must start with the same allocation and chain ID. Applying a batch returns a new state; failures leave the old state intact.

Parameters:
property total_supply: int#

Return the sum of all balances, which transfers never change.

Every transfer debits one account and credits another by the same amount: Pacioli’s double-entry rule. A change in total supply would mean money was created or destroyed.

property balances: Mapping[str, int]#

Read-only account balances in integer units.

property nonces: Mapping[str, int]#

Read-only next expected sequence numbers (missing accounts start at 0).

property chain_id: str#

Return the signature domain accepted by this ledger.

apply(transactions)[source]#

Validate and atomically apply transfers in order, returning a new ledger.

Rejects invalid signatures, wrong chain IDs, replayed/out-of-order nonces, and insufficient funds. Self-transfers still consume a nonce.

Parameters:

transactions (Iterable[Transaction])

Return type:

Ledger

Cumulative-work fork selection for a fixed-difficulty chain.

class blockchainkit.structures.systems.chain.Blockchain(genesis, initial_state=None)[source]#

Bases: object

Store valid forks and select the tip with greatest cumulative work.

Parameters:

Notes

Difficulty is fixed by genesis; a child cannot lower its own target. Equal-work ties select the lexicographically smaller hash, so peers with the same block set converge independent of arrival order. This teaching tie-break is not Bitcoin’s first-seen behavior. Each fork retains its own ledger snapshot, so reorganizations restore balances and nonces.

Keeping a full snapshot per block makes reorganizations easy to inspect, at a memory cost proportional to blocks times accounts. Real nodes keep one state and undo data instead.

property tip: Block#

Return the selected canonical tip.

property state: Ledger#

Return the selected tip’s validated ledger snapshot.

property cumulative_work: int#

Return total expected hash trials represented by the canonical chain.

property blocks: Mapping[bytes, Block]#

Read-only view of every stored block by hash, including side forks.

tips()[source]#

Return the blocks that have no child: the tip of every fork.

Ordered as fork choice ranks them: most cumulative work first, ties broken by the smaller hash. The first tip is always tip.

Return type:

tuple[Block, …]

work_at(block_hash)[source]#

Return the cumulative expected work of the chain ending at a stored block.

Raises KeyError for an unknown hash.

Parameters:

block_hash (bytes)

Return type:

int

state_at(block_hash)[source]#

Return the ledger snapshot after a stored block, on whichever fork it lies.

Raises KeyError for an unknown hash.

Parameters:

block_hash (bytes)

Return type:

Ledger

contains(block_hash)[source]#

Return whether this node already knows a block, including side forks.

Parameters:

block_hash (bytes)

Return type:

bool

add(block)[source]#

Validate and store a child; return whether the preferred tip changed.

Unknown parents raise ValueError. Networking experiments can buffer such blocks until their parents arrive. Duplicate blocks are ignored.

Parameters:

block (Block)

Return type:

bool

canonical_blocks()[source]#

Return the selected chain from genesis through tip.

Return type:

tuple[Block, …]

Helpers#

Deterministic byte encodings for hashing and signing records.

blockchainkit.structures.utils.encoding.canonical_json(value)[source]#

Encode internal integer/string records as sorted compact UTF-8 JSON.

This is a package-specific encoding, not a general canonical-JSON standard.

Parameters:

value (object)

Return type:

bytes

Account identifiers: 64 lowercase hex characters, the SHA-256 of a public key.

blockchainkit.structures.utils.accounts.is_account_id(value)[source]#

Return whether value has the shape of an account identifier.

>>> from blockchainkit.structures.utils import is_account_id
>>> is_account_id("ab" * 32), is_account_id("AB" * 32)
(True, False)
Parameters:

value (object)

Return type:

bool

Plotting#

Plotting helpers for blockchainkit.structures: Merkle trees, proof traces, block trees.

blockchainkit.structures.visualizers.plots.plot_merkle_tree(tree, *, highlight=None, ax=None)[source]#

Draw every level of a Merkle tree, optionally highlighting one proof.

Parameters:
Return type:

matplotlib.axes.Axes

blockchainkit.structures.visualizers.plots.plot_proof_trace(trace, ax=None)[source]#

Tabulate each step of reconstructing a root from a leaf and its proof.

Parameters:
Return type:

matplotlib.axes.Axes

blockchainkit.structures.visualizers.plots.plot_block_tree(chain, ax=None)[source]#

Draw every stored block by height, one lane per fork, canonical chain highlighted.

Parameters:
Return type:

matplotlib.axes.Axes