nockchain 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 nockchain-go contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ include README.md SECURITY.md requirements-dev.txt
2
+ recursive-include testdata *.json
3
+ recursive-include tests *.py
@@ -0,0 +1,227 @@
1
+ Metadata-Version: 2.4
2
+ Name: nockchain
3
+ Version: 0.1.0
4
+ Summary: Native Python Nockchain V1 wallets, transactions, multisig and timelocks
5
+ Author: SWPSCO
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://github.com/SWPSCO/nockchain-py
8
+ Keywords: nockchain,nock,wallet,multisig
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Typing :: Typed
11
+ Requires-Python: >=3.11
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ License-File: THIRD_PARTY_LICENSES
15
+ Dynamic: license-file
16
+
17
+ # nockchain
18
+
19
+ Native Python tools for Nockchain V1 wallets and transactions. Derive receiving
20
+ addresses, inspect payments, select coins, and sign single-key or multisig spends.
21
+ Python 3.11+; the package uses the standard library and has no runtime dependencies.
22
+
23
+ ```sh
24
+ pip install nockchain
25
+ ```
26
+
27
+ ## Receive from a public branch
28
+
29
+ ```python
30
+ from nockchain import derive_receive_address, parse_public_key
31
+
32
+ branch = parse_public_key(zpub) # rejects private extended keys
33
+ receive = derive_receive_address(branch.zpub(), 42)
34
+ print(receive.address, receive.lock_root)
35
+ ```
36
+
37
+ Reserve each receiving index durably before giving its address to a payer. Use a
38
+ dedicated non-hardened receiving branch and retain the path and allocated-index
39
+ range for recovery. `address` is the sending wallet's destination; `lock_root` is
40
+ its output lock commitment. A zpub is privacy-sensitive.
41
+
42
+ ## Wallets and recovery
43
+
44
+ ```python
45
+ from nockchain import generate_wallet, restore_wallet
46
+
47
+ key, recovery = generate_wallet("") # optional BIP39 passphrase
48
+ # Back up recovery.words() privately before receiving funds. Never log it.
49
+ restored = restore_wallet(recovery.words(), "")
50
+ public_branch = key.derive("m/44'/0'/0'/9000").public().zpub()
51
+ ```
52
+
53
+ `generate_mnemonic()` creates a 24-word English BIP39 phrase. Recovery accepts
54
+ 12–24 words, validates checksums, and normalizes Unicode with NFKD. A wrong
55
+ passphrase produces a different valid wallet. `generate_seed()` creates a raw
56
+ 64-byte seed; `master(seed_bytes)` accepts one. Raw seeds have no mnemonic.
57
+ `zprv()`, `words()`, and `Seed.to_bytes()` explicitly export spending authority.
58
+ Diagnostic string and repr output redact secret-bearing objects.
59
+
60
+ Paths start with `m` and are relative to the supplied key. Apostrophes mark
61
+ hardened indices, which require private parents. `public()` removes the private
62
+ scalar. Key parsing validates canonical coordinates and the Cheetah prime-order
63
+ subgroup.
64
+
65
+ ## Exact amounts and coin selection
66
+
67
+ ```python
68
+ from nockchain import Payment, parse_nocks, select_transfer
69
+
70
+ nicks = parse_nocks("1.25") # 81920
71
+ plan = select_transfer(sender.public(), verified_unspent_notes, [
72
+ Payment(destination, "1.25"),
73
+ ])
74
+ review = plan.summary()
75
+ # Present the review and obtain the wallet user's authorization before signing.
76
+ signed = plan.sign(sender)
77
+ wire = signed.jam()
78
+ ```
79
+
80
+ Amounts, heights, digest limbs, and atoms are Python integers. Floats and booleans
81
+ are rejected at numeric protocol boundaries. `1 NOCK = 65,536 nicks`;
82
+ `parse_nocks()` rejects sub-nick decimal precision, and `format_nocks()` is exact.
83
+
84
+ `select_transfer()` chooses sufficient notes largest-first with deterministic
85
+ note-name ties. `prepare_transfer()` consumes every supplied record. Both merge
86
+ repeated recipients, estimate fees, and send change to the sender unless
87
+ `TransferOptions(change_address=...)` is set. A nonzero `fee_nicks` supplies an
88
+ explicit fee. With automatic fees, a remainder too small to pay for change
89
+ metadata becomes part of the fee; the review shows the exact amount.
90
+ These helpers support plain 1-of-1 PKH inputs. `sign_transfer_v1()` accepts explicit
91
+ per-input output and fee allocations.
92
+
93
+ An `UnspentNote` holds the complete note and its verified lock root:
94
+
95
+ ```python
96
+ from nockchain import NoteV1, NoteName, UnspentNote, cue, parse_digest
97
+
98
+ note = NoteV1(
99
+ origin_page=100,
100
+ name=NoteName(parse_digest(first), parse_digest(last)),
101
+ note_data=cue(stored_metadata_jam),
102
+ nicks=10_000_000,
103
+ )
104
+ unspent = UnspentNote(note, parse_digest(input_lock_root))
105
+ ```
106
+
107
+ Parent commitments include version, origin, name, **all stored metadata**, and
108
+ value. Empty metadata is `0` only when the stored record actually has none.
109
+ The application authenticates input existence, unspent status, and confirmations.
110
+
111
+ ## Multisig, timelocks, and independent signing
112
+
113
+ ```python
114
+ from nockchain import (
115
+ HeightRange, TimelockV1, LockV1, LockedPaymentV1, LockedSpendPlanV1,
116
+ minimum_transaction_fee_v1, prepare_transaction_v1,
117
+ )
118
+
119
+ lock = LockV1(2, (alice_pkh, bob_pkh, carol_pkh), TimelockV1(
120
+ relative=HeightRange(min=10),
121
+ absolute=HeightRange(max=500_000),
122
+ ))
123
+ fee = minimum_transaction_fee_v1([lock], [recipient_lock])
124
+ unsigned = prepare_transaction_v1([LockedSpendPlanV1(
125
+ note=verified_note, lock=lock, fee=fee,
126
+ outputs=(LockedPaymentV1(recipient_lock, verified_note.nicks - fee),),
127
+ )])
128
+ # Each signer independently reviews the same unsigned plan.
129
+ alice = unsigned.sign(alice_key)
130
+ bob = unsigned.sign(bob_key)
131
+ signed = alice.merge_signatures(bob)
132
+ signed.verify_signatures()
133
+ signed.validate_inputs([verified_note], chain_height)
134
+ ```
135
+
136
+ A lock requires **exactly m signatures**, with up to 32 distinct keys. Extra
137
+ signatures are rejected. Timelock endpoints are inclusive; `None` is unbounded.
138
+ Relative heights measure age since the note's origin page. Signing does not
139
+ assert that a timelock is satisfied. Each signature changes the transaction ID.
140
+ Partial transactions travel as jam bytes; merging rejects altered plans and
141
+ conflicting signatures. Plans, notes, policies, and reviews are immutable.
142
+
143
+ ## Inspect and validate
144
+
145
+ ```python
146
+ from nockchain import parse_transaction_v1
147
+
148
+ tx = parse_transaction_v1(wire)
149
+ review = tx.summary()
150
+ tx.verify_signatures()
151
+ tx.validate_inputs(verified_notes, chain_height)
152
+ print(str(tx.id))
153
+ ```
154
+
155
+ | Operation | What it establishes |
156
+ | --- | --- |
157
+ | `parse_transaction_v1()` | Supported structure, canonical trees, proof roots, key encoding, and embedded ID |
158
+ | `summary()` | Committed outputs, fees, signature hashes, and present signers |
159
+ | `OutputV1.lock()` | Metadata authenticates the committed output policy |
160
+ | `verify_signatures()` | Every signature, authorization, exact threshold, and minimum fee |
161
+ | `validate_inputs()` | Complete supplied records, parent hashes, balances, origin heights, and timelocks |
162
+
163
+ Validation methods raise `NockchainError` on protocol failures and return `None`
164
+ on success. `verify_digest()` returns a boolean. Successful parsing is not proof
165
+ of valid signatures or chain state. The package does not fetch chain data,
166
+ broadcast transactions, or implement confirmation policy.
167
+
168
+ ## Protocol primitives and limits
169
+
170
+ `Digest` is an immutable tuple of five field elements. `str(digest)` encodes its
171
+ Base58 form and `parse_digest()` validates it. `Noun` is an integer atom or an
172
+ immutable `Cell`. Use `atom()`, `Cell(head, tail)`, `noun_tuple()`, and `noun_list()`
173
+ for construction; `hash_words()`, `hash_noun()`, `jam()`, and `cue()` implement the
174
+ hashing and codec primitives. Atom values must be below the Goldilocks prime;
175
+ these are based nouns, not arbitrary-size Nock atom containers.
176
+
177
+ Noun hashing and jam/cue traversal are iterative. Shared subtrees count toward
178
+ logical expansion limits even when backreferences make the wire encoding small.
179
+ Equality memoizes visited cell pairs. General noun operations allow 1,048,576
180
+ logical nodes and at most 16 MiB of jam bytes.
181
+
182
+ Transactions support full axis-1 PKH proofs, optional conjunctive timelocks, and
183
+ ordinary output seeds. Other Merkle proofs, hashlocks, burn locks,
184
+ source-constrained outputs, and bridge construction are outside this API.
185
+ Limits are 64 inputs, 256 output seeds, 32 keys per lock, 64 metadata entries,
186
+ 2,048 flattened metadata words per output lock, 65,536 transaction nodes, and
187
+ depth 256. Every input retains at least one nonzero output seed.
188
+
189
+ Fees follow the pinned mainnet V1 schedule, merging metadata per output lock and
190
+ rejecting conflicting values. Applications must track network rule changes.
191
+ Private-key arithmetic is **variable-time**; use trusted offline signing tools.
192
+ See [SECURITY.md](SECURITY.md).
193
+
194
+ ## Develop and verify
195
+
196
+ ```sh
197
+ python -m venv .venv
198
+ . .venv/bin/activate
199
+ pip install -r requirements-dev.txt
200
+ pip install -e .
201
+ python -m unittest discover -s tests -v
202
+ ruff check src tests
203
+ ruff format --check src tests
204
+ python -m build
205
+ python -m twine check dist/*
206
+ ```
207
+
208
+ The public corpus checks 35 wallet vectors, 105 signatures, 24 BIP39 vectors,
209
+ 13 TIP5 vectors, seven noun encodings, four single-key transactions, and two
210
+ multisig transactions. Tests compare exact partial and signed bytes and the
211
+ canonical Hoon oracle's IDs, complete note commitments, and minimum fees.
212
+ Additional tests cover malformed input, immutable reviews, timelock boundaries,
213
+ metadata, fees, and selection. CI tests Python 3.11 and 3.13, then builds and
214
+ installs the wheel. Normal tests are offline and require no Go, Rust, or Hoon.
215
+
216
+ The protocol source of truth is
217
+ [zorp-corp/nockchain at `1eac020`](https://github.com/zorp-corp/nockchain/tree/1eac02083a053c104b6a1299e80a8a51447017dc).
218
+ The port follows
219
+ [nockchain-go v0.1.0](https://github.com/yapishu/nockchain-go/tree/v0.1.0).
220
+ Public interoperability fixtures come from
221
+ [tx-types at `5f9ab2b`](https://github.com/SWPSCO/tx-types/tree/5f9ab2b38f1685a908f19a0e8f18e7845b3e7f35),
222
+ [nockster at `d621105`](https://github.com/SWPSCO/nockster/tree/d62110560dd005827ae8a46126c9841c86db0d6a),
223
+ and [Trezor BIP39 vectors](https://github.com/trezor/python-mnemonic/blob/master/vectors.json).
224
+ Fixture generators are in the Go repository.
225
+ **Never send funds to public test-vector addresses.**
226
+
227
+ MIT licensed. See [THIRD_PARTY_LICENSES](THIRD_PARTY_LICENSES) for wordlist attribution.
@@ -0,0 +1,211 @@
1
+ # nockchain
2
+
3
+ Native Python tools for Nockchain V1 wallets and transactions. Derive receiving
4
+ addresses, inspect payments, select coins, and sign single-key or multisig spends.
5
+ Python 3.11+; the package uses the standard library and has no runtime dependencies.
6
+
7
+ ```sh
8
+ pip install nockchain
9
+ ```
10
+
11
+ ## Receive from a public branch
12
+
13
+ ```python
14
+ from nockchain import derive_receive_address, parse_public_key
15
+
16
+ branch = parse_public_key(zpub) # rejects private extended keys
17
+ receive = derive_receive_address(branch.zpub(), 42)
18
+ print(receive.address, receive.lock_root)
19
+ ```
20
+
21
+ Reserve each receiving index durably before giving its address to a payer. Use a
22
+ dedicated non-hardened receiving branch and retain the path and allocated-index
23
+ range for recovery. `address` is the sending wallet's destination; `lock_root` is
24
+ its output lock commitment. A zpub is privacy-sensitive.
25
+
26
+ ## Wallets and recovery
27
+
28
+ ```python
29
+ from nockchain import generate_wallet, restore_wallet
30
+
31
+ key, recovery = generate_wallet("") # optional BIP39 passphrase
32
+ # Back up recovery.words() privately before receiving funds. Never log it.
33
+ restored = restore_wallet(recovery.words(), "")
34
+ public_branch = key.derive("m/44'/0'/0'/9000").public().zpub()
35
+ ```
36
+
37
+ `generate_mnemonic()` creates a 24-word English BIP39 phrase. Recovery accepts
38
+ 12–24 words, validates checksums, and normalizes Unicode with NFKD. A wrong
39
+ passphrase produces a different valid wallet. `generate_seed()` creates a raw
40
+ 64-byte seed; `master(seed_bytes)` accepts one. Raw seeds have no mnemonic.
41
+ `zprv()`, `words()`, and `Seed.to_bytes()` explicitly export spending authority.
42
+ Diagnostic string and repr output redact secret-bearing objects.
43
+
44
+ Paths start with `m` and are relative to the supplied key. Apostrophes mark
45
+ hardened indices, which require private parents. `public()` removes the private
46
+ scalar. Key parsing validates canonical coordinates and the Cheetah prime-order
47
+ subgroup.
48
+
49
+ ## Exact amounts and coin selection
50
+
51
+ ```python
52
+ from nockchain import Payment, parse_nocks, select_transfer
53
+
54
+ nicks = parse_nocks("1.25") # 81920
55
+ plan = select_transfer(sender.public(), verified_unspent_notes, [
56
+ Payment(destination, "1.25"),
57
+ ])
58
+ review = plan.summary()
59
+ # Present the review and obtain the wallet user's authorization before signing.
60
+ signed = plan.sign(sender)
61
+ wire = signed.jam()
62
+ ```
63
+
64
+ Amounts, heights, digest limbs, and atoms are Python integers. Floats and booleans
65
+ are rejected at numeric protocol boundaries. `1 NOCK = 65,536 nicks`;
66
+ `parse_nocks()` rejects sub-nick decimal precision, and `format_nocks()` is exact.
67
+
68
+ `select_transfer()` chooses sufficient notes largest-first with deterministic
69
+ note-name ties. `prepare_transfer()` consumes every supplied record. Both merge
70
+ repeated recipients, estimate fees, and send change to the sender unless
71
+ `TransferOptions(change_address=...)` is set. A nonzero `fee_nicks` supplies an
72
+ explicit fee. With automatic fees, a remainder too small to pay for change
73
+ metadata becomes part of the fee; the review shows the exact amount.
74
+ These helpers support plain 1-of-1 PKH inputs. `sign_transfer_v1()` accepts explicit
75
+ per-input output and fee allocations.
76
+
77
+ An `UnspentNote` holds the complete note and its verified lock root:
78
+
79
+ ```python
80
+ from nockchain import NoteV1, NoteName, UnspentNote, cue, parse_digest
81
+
82
+ note = NoteV1(
83
+ origin_page=100,
84
+ name=NoteName(parse_digest(first), parse_digest(last)),
85
+ note_data=cue(stored_metadata_jam),
86
+ nicks=10_000_000,
87
+ )
88
+ unspent = UnspentNote(note, parse_digest(input_lock_root))
89
+ ```
90
+
91
+ Parent commitments include version, origin, name, **all stored metadata**, and
92
+ value. Empty metadata is `0` only when the stored record actually has none.
93
+ The application authenticates input existence, unspent status, and confirmations.
94
+
95
+ ## Multisig, timelocks, and independent signing
96
+
97
+ ```python
98
+ from nockchain import (
99
+ HeightRange, TimelockV1, LockV1, LockedPaymentV1, LockedSpendPlanV1,
100
+ minimum_transaction_fee_v1, prepare_transaction_v1,
101
+ )
102
+
103
+ lock = LockV1(2, (alice_pkh, bob_pkh, carol_pkh), TimelockV1(
104
+ relative=HeightRange(min=10),
105
+ absolute=HeightRange(max=500_000),
106
+ ))
107
+ fee = minimum_transaction_fee_v1([lock], [recipient_lock])
108
+ unsigned = prepare_transaction_v1([LockedSpendPlanV1(
109
+ note=verified_note, lock=lock, fee=fee,
110
+ outputs=(LockedPaymentV1(recipient_lock, verified_note.nicks - fee),),
111
+ )])
112
+ # Each signer independently reviews the same unsigned plan.
113
+ alice = unsigned.sign(alice_key)
114
+ bob = unsigned.sign(bob_key)
115
+ signed = alice.merge_signatures(bob)
116
+ signed.verify_signatures()
117
+ signed.validate_inputs([verified_note], chain_height)
118
+ ```
119
+
120
+ A lock requires **exactly m signatures**, with up to 32 distinct keys. Extra
121
+ signatures are rejected. Timelock endpoints are inclusive; `None` is unbounded.
122
+ Relative heights measure age since the note's origin page. Signing does not
123
+ assert that a timelock is satisfied. Each signature changes the transaction ID.
124
+ Partial transactions travel as jam bytes; merging rejects altered plans and
125
+ conflicting signatures. Plans, notes, policies, and reviews are immutable.
126
+
127
+ ## Inspect and validate
128
+
129
+ ```python
130
+ from nockchain import parse_transaction_v1
131
+
132
+ tx = parse_transaction_v1(wire)
133
+ review = tx.summary()
134
+ tx.verify_signatures()
135
+ tx.validate_inputs(verified_notes, chain_height)
136
+ print(str(tx.id))
137
+ ```
138
+
139
+ | Operation | What it establishes |
140
+ | --- | --- |
141
+ | `parse_transaction_v1()` | Supported structure, canonical trees, proof roots, key encoding, and embedded ID |
142
+ | `summary()` | Committed outputs, fees, signature hashes, and present signers |
143
+ | `OutputV1.lock()` | Metadata authenticates the committed output policy |
144
+ | `verify_signatures()` | Every signature, authorization, exact threshold, and minimum fee |
145
+ | `validate_inputs()` | Complete supplied records, parent hashes, balances, origin heights, and timelocks |
146
+
147
+ Validation methods raise `NockchainError` on protocol failures and return `None`
148
+ on success. `verify_digest()` returns a boolean. Successful parsing is not proof
149
+ of valid signatures or chain state. The package does not fetch chain data,
150
+ broadcast transactions, or implement confirmation policy.
151
+
152
+ ## Protocol primitives and limits
153
+
154
+ `Digest` is an immutable tuple of five field elements. `str(digest)` encodes its
155
+ Base58 form and `parse_digest()` validates it. `Noun` is an integer atom or an
156
+ immutable `Cell`. Use `atom()`, `Cell(head, tail)`, `noun_tuple()`, and `noun_list()`
157
+ for construction; `hash_words()`, `hash_noun()`, `jam()`, and `cue()` implement the
158
+ hashing and codec primitives. Atom values must be below the Goldilocks prime;
159
+ these are based nouns, not arbitrary-size Nock atom containers.
160
+
161
+ Noun hashing and jam/cue traversal are iterative. Shared subtrees count toward
162
+ logical expansion limits even when backreferences make the wire encoding small.
163
+ Equality memoizes visited cell pairs. General noun operations allow 1,048,576
164
+ logical nodes and at most 16 MiB of jam bytes.
165
+
166
+ Transactions support full axis-1 PKH proofs, optional conjunctive timelocks, and
167
+ ordinary output seeds. Other Merkle proofs, hashlocks, burn locks,
168
+ source-constrained outputs, and bridge construction are outside this API.
169
+ Limits are 64 inputs, 256 output seeds, 32 keys per lock, 64 metadata entries,
170
+ 2,048 flattened metadata words per output lock, 65,536 transaction nodes, and
171
+ depth 256. Every input retains at least one nonzero output seed.
172
+
173
+ Fees follow the pinned mainnet V1 schedule, merging metadata per output lock and
174
+ rejecting conflicting values. Applications must track network rule changes.
175
+ Private-key arithmetic is **variable-time**; use trusted offline signing tools.
176
+ See [SECURITY.md](SECURITY.md).
177
+
178
+ ## Develop and verify
179
+
180
+ ```sh
181
+ python -m venv .venv
182
+ . .venv/bin/activate
183
+ pip install -r requirements-dev.txt
184
+ pip install -e .
185
+ python -m unittest discover -s tests -v
186
+ ruff check src tests
187
+ ruff format --check src tests
188
+ python -m build
189
+ python -m twine check dist/*
190
+ ```
191
+
192
+ The public corpus checks 35 wallet vectors, 105 signatures, 24 BIP39 vectors,
193
+ 13 TIP5 vectors, seven noun encodings, four single-key transactions, and two
194
+ multisig transactions. Tests compare exact partial and signed bytes and the
195
+ canonical Hoon oracle's IDs, complete note commitments, and minimum fees.
196
+ Additional tests cover malformed input, immutable reviews, timelock boundaries,
197
+ metadata, fees, and selection. CI tests Python 3.11 and 3.13, then builds and
198
+ installs the wheel. Normal tests are offline and require no Go, Rust, or Hoon.
199
+
200
+ The protocol source of truth is
201
+ [zorp-corp/nockchain at `1eac020`](https://github.com/zorp-corp/nockchain/tree/1eac02083a053c104b6a1299e80a8a51447017dc).
202
+ The port follows
203
+ [nockchain-go v0.1.0](https://github.com/yapishu/nockchain-go/tree/v0.1.0).
204
+ Public interoperability fixtures come from
205
+ [tx-types at `5f9ab2b`](https://github.com/SWPSCO/tx-types/tree/5f9ab2b38f1685a908f19a0e8f18e7845b3e7f35),
206
+ [nockster at `d621105`](https://github.com/SWPSCO/nockster/tree/d62110560dd005827ae8a46126c9841c86db0d6a),
207
+ and [Trezor BIP39 vectors](https://github.com/trezor/python-mnemonic/blob/master/vectors.json).
208
+ Fixture generators are in the Go repository.
209
+ **Never send funds to public test-vector addresses.**
210
+
211
+ MIT licensed. See [THIRD_PARTY_LICENSES](THIRD_PARTY_LICENSES) for wordlist attribution.
@@ -0,0 +1,30 @@
1
+ # Security
2
+
3
+ Online services use a dedicated public receiving branch. Public extended keys
4
+ are privacy-sensitive. A non-hardened child private key together with its parent
5
+ zpub can expose the parent's private key.
6
+
7
+ Cheetah arithmetic uses variable-time Python integer operations. Private
8
+ operations belong in trusted offline wallet tools, not remote signing or key
9
+ services. Python's allocator and garbage collector do not guarantee erasure of
10
+ secret copies. `zprv()`, `words()`, and `Seed.to_bytes()` explicitly export spending
11
+ authority. Diagnostic string/repr output is redacted; generic object serializers
12
+ and private attributes are not secret-storage boundaries. Callers own logging,
13
+ backups, storage, and access control.
14
+
15
+ Nouns, locks, notes and transaction reviews are immutable. Decoding has byte,
16
+ logical-node and depth limits. Parsing does not establish signature or chain
17
+ validity. Call `verify_signatures()` and `validate_inputs()` explicitly; obtain
18
+ complete input records, canonical height, unspent status, and confirmations from
19
+ a trusted chain-state source.
20
+
21
+ The supported V1 subset uses full PKH proofs with optional conjunctive timelocks.
22
+ This package is not a complete consensus validator, chain client, or broadcaster.
23
+ Fee rules are pinned to the referenced source; applications must track changes.
24
+ Native NOCK uses nicks (2^16 per NOCK), distinct from Base ERC-20 units.
25
+
26
+ Tests use public Hoon, Rust and BIP39 fixtures. No independent cryptographic audit
27
+ is claimed. Report vulnerabilities privately through GitHub private reporting
28
+ when available or another established private channel to the maintainers. Never
29
+ include real seeds, private extended keys, API credentials, or identifying wallet
30
+ data in issues or reproductions.
@@ -0,0 +1,23 @@
1
+ English BIP39 wordlist from github.com/tyler-smith/go-bip39
2
+
3
+ The MIT License (MIT)
4
+
5
+ Copyright (c) 2014-2018 Tyler Smith and contributors
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
@@ -0,0 +1,30 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "nockchain"
7
+ version = "0.1.0"
8
+ description = "Native Python Nockchain V1 wallets, transactions, multisig and timelocks"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+ license-files = ["LICENSE", "THIRD_PARTY_LICENSES"]
13
+ authors = [{name = "SWPSCO"}]
14
+ keywords = ["nockchain", "nock", "wallet", "multisig"]
15
+ classifiers = ["Programming Language :: Python :: 3", "Typing :: Typed"]
16
+
17
+ [project.urls]
18
+ Repository = "https://github.com/SWPSCO/nockchain-py"
19
+
20
+ [tool.setuptools.packages.find]
21
+ where = ["src"]
22
+
23
+ [tool.setuptools.package-data]
24
+ nockchain = ["py.typed"]
25
+
26
+ [tool.ruff]
27
+ line-length = 100
28
+
29
+ [tool.ruff.lint]
30
+ select = ["E4", "E7", "E9", "F"]
@@ -0,0 +1,3 @@
1
+ build==1.6.1
2
+ twine==7.0.0
3
+ ruff==0.17.0
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+