create-sia-app 0.1.7 → 0.1.9

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.
Files changed (114) hide show
  1. package/package.json +2 -6
  2. package/template/AGENTS.md +143 -0
  3. package/template/CLAUDE.md +25 -46
  4. package/template/README.md +6 -12
  5. package/template/_gitignore +0 -1
  6. package/template/dist/assets/index-BEylY2j7.css +1 -0
  7. package/template/dist/assets/index-CnYqArKN.js +8741 -0
  8. package/template/dist/assets/sia_bg-BTOHUC1A.wasm +0 -0
  9. package/template/dist/assets/slab-download-worker-DhW6ZBJs.js +2 -0
  10. package/template/dist/assets/slab-upload-worker-B2uSB2iY.js +2 -0
  11. package/template/dist/index.html +13 -0
  12. package/template/e2e/smoke.spec.ts +20 -0
  13. package/template/index.html +0 -1
  14. package/template/package.json +2 -2
  15. package/template/playwright.config.ts +13 -0
  16. package/template/src/components/Navbar.tsx +3 -3
  17. package/template/src/components/auth/ApproveScreen.tsx +10 -13
  18. package/template/src/components/auth/AuthFlow.tsx +13 -10
  19. package/template/src/components/auth/ConnectScreen.tsx +2 -3
  20. package/template/src/components/auth/RecoveryScreen.tsx +7 -7
  21. package/template/src/components/upload/UploadZone.tsx +192 -74
  22. package/template/src/index.css +14 -4
  23. package/template/src/stores/auth.ts +6 -12
  24. package/template/test-results/.last-run.json +4 -0
  25. package/template/tsconfig.app.json +1 -1
  26. package/template/tsconfig.node.json +0 -1
  27. package/template/vite.config.ts +2 -3
  28. package/template/rust/README.md +0 -16
  29. package/template/rust/sia-sdk-rs/.changeset/added_cancel_function_to_cancel_inflight_packed_uploads.md +0 -6
  30. package/template/rust/sia-sdk-rs/.changeset/check_if_we_have_enough_hosts_prior_to_encoding_in_upload_slabs.md +0 -16
  31. package/template/rust/sia-sdk-rs/.changeset/fix_slab_length_in_packed_object.md +0 -5
  32. package/template/rust/sia-sdk-rs/.changeset/fix_upload_racing_race_conditon.md +0 -13
  33. package/template/rust/sia-sdk-rs/.changeset/improved_parallelism_of_packed_uploads.md +0 -5
  34. package/template/rust/sia-sdk-rs/.changeset/progress_callback_will_now_be_called_as_expected_for_packed_uploads.md +0 -5
  35. package/template/rust/sia-sdk-rs/.github/dependabot.yml +0 -10
  36. package/template/rust/sia-sdk-rs/.github/workflows/main.yml +0 -36
  37. package/template/rust/sia-sdk-rs/.github/workflows/prepare-release.yml +0 -34
  38. package/template/rust/sia-sdk-rs/.github/workflows/release.yml +0 -30
  39. package/template/rust/sia-sdk-rs/.rustfmt.toml +0 -4
  40. package/template/rust/sia-sdk-rs/Cargo.lock +0 -4127
  41. package/template/rust/sia-sdk-rs/Cargo.toml +0 -3
  42. package/template/rust/sia-sdk-rs/LICENSE +0 -21
  43. package/template/rust/sia-sdk-rs/README.md +0 -30
  44. package/template/rust/sia-sdk-rs/indexd/CHANGELOG.md +0 -79
  45. package/template/rust/sia-sdk-rs/indexd/Cargo.toml +0 -79
  46. package/template/rust/sia-sdk-rs/indexd/benches/upload.rs +0 -258
  47. package/template/rust/sia-sdk-rs/indexd/src/app_client.rs +0 -1710
  48. package/template/rust/sia-sdk-rs/indexd/src/builder.rs +0 -354
  49. package/template/rust/sia-sdk-rs/indexd/src/download.rs +0 -379
  50. package/template/rust/sia-sdk-rs/indexd/src/hosts.rs +0 -659
  51. package/template/rust/sia-sdk-rs/indexd/src/lib.rs +0 -827
  52. package/template/rust/sia-sdk-rs/indexd/src/mock.rs +0 -162
  53. package/template/rust/sia-sdk-rs/indexd/src/object_encryption.rs +0 -125
  54. package/template/rust/sia-sdk-rs/indexd/src/quic.rs +0 -575
  55. package/template/rust/sia-sdk-rs/indexd/src/rhp4.rs +0 -52
  56. package/template/rust/sia-sdk-rs/indexd/src/slabs.rs +0 -497
  57. package/template/rust/sia-sdk-rs/indexd/src/upload.rs +0 -629
  58. package/template/rust/sia-sdk-rs/indexd/src/wasm_time.rs +0 -41
  59. package/template/rust/sia-sdk-rs/indexd/src/web_transport.rs +0 -398
  60. package/template/rust/sia-sdk-rs/indexd_ffi/CHANGELOG.md +0 -76
  61. package/template/rust/sia-sdk-rs/indexd_ffi/Cargo.toml +0 -47
  62. package/template/rust/sia-sdk-rs/indexd_ffi/examples/python/README.md +0 -10
  63. package/template/rust/sia-sdk-rs/indexd_ffi/examples/python/example.py +0 -130
  64. package/template/rust/sia-sdk-rs/indexd_ffi/src/bin/uniffi-bindgen.rs +0 -3
  65. package/template/rust/sia-sdk-rs/indexd_ffi/src/builder.rs +0 -377
  66. package/template/rust/sia-sdk-rs/indexd_ffi/src/io.rs +0 -155
  67. package/template/rust/sia-sdk-rs/indexd_ffi/src/lib.rs +0 -1039
  68. package/template/rust/sia-sdk-rs/indexd_ffi/src/logging.rs +0 -58
  69. package/template/rust/sia-sdk-rs/indexd_ffi/src/tls.rs +0 -23
  70. package/template/rust/sia-sdk-rs/indexd_wasm/Cargo.toml +0 -33
  71. package/template/rust/sia-sdk-rs/indexd_wasm/src/lib.rs +0 -818
  72. package/template/rust/sia-sdk-rs/knope.toml +0 -54
  73. package/template/rust/sia-sdk-rs/sia_derive/CHANGELOG.md +0 -38
  74. package/template/rust/sia-sdk-rs/sia_derive/Cargo.toml +0 -19
  75. package/template/rust/sia-sdk-rs/sia_derive/src/lib.rs +0 -278
  76. package/template/rust/sia-sdk-rs/sia_sdk/CHANGELOG.md +0 -91
  77. package/template/rust/sia-sdk-rs/sia_sdk/Cargo.toml +0 -59
  78. package/template/rust/sia-sdk-rs/sia_sdk/benches/merkle_root.rs +0 -12
  79. package/template/rust/sia-sdk-rs/sia_sdk/src/blake2.rs +0 -22
  80. package/template/rust/sia-sdk-rs/sia_sdk/src/consensus.rs +0 -767
  81. package/template/rust/sia-sdk-rs/sia_sdk/src/encoding/v1.rs +0 -257
  82. package/template/rust/sia-sdk-rs/sia_sdk/src/encoding/v2.rs +0 -291
  83. package/template/rust/sia-sdk-rs/sia_sdk/src/encoding.rs +0 -26
  84. package/template/rust/sia-sdk-rs/sia_sdk/src/encoding_async/v2.rs +0 -367
  85. package/template/rust/sia-sdk-rs/sia_sdk/src/encoding_async.rs +0 -6
  86. package/template/rust/sia-sdk-rs/sia_sdk/src/encryption.rs +0 -303
  87. package/template/rust/sia-sdk-rs/sia_sdk/src/erasure_coding.rs +0 -347
  88. package/template/rust/sia-sdk-rs/sia_sdk/src/lib.rs +0 -15
  89. package/template/rust/sia-sdk-rs/sia_sdk/src/macros.rs +0 -435
  90. package/template/rust/sia-sdk-rs/sia_sdk/src/merkle.rs +0 -112
  91. package/template/rust/sia-sdk-rs/sia_sdk/src/rhp/merkle.rs +0 -357
  92. package/template/rust/sia-sdk-rs/sia_sdk/src/rhp/rpc.rs +0 -1507
  93. package/template/rust/sia-sdk-rs/sia_sdk/src/rhp/types.rs +0 -146
  94. package/template/rust/sia-sdk-rs/sia_sdk/src/rhp.rs +0 -7
  95. package/template/rust/sia-sdk-rs/sia_sdk/src/seed.rs +0 -278
  96. package/template/rust/sia-sdk-rs/sia_sdk/src/signing.rs +0 -236
  97. package/template/rust/sia-sdk-rs/sia_sdk/src/types/common.rs +0 -677
  98. package/template/rust/sia-sdk-rs/sia_sdk/src/types/currency.rs +0 -450
  99. package/template/rust/sia-sdk-rs/sia_sdk/src/types/specifier.rs +0 -110
  100. package/template/rust/sia-sdk-rs/sia_sdk/src/types/spendpolicy.rs +0 -778
  101. package/template/rust/sia-sdk-rs/sia_sdk/src/types/utils.rs +0 -117
  102. package/template/rust/sia-sdk-rs/sia_sdk/src/types/v1.rs +0 -1737
  103. package/template/rust/sia-sdk-rs/sia_sdk/src/types/v2.rs +0 -1726
  104. package/template/rust/sia-sdk-rs/sia_sdk/src/types/work.rs +0 -59
  105. package/template/rust/sia-sdk-rs/sia_sdk/src/types.rs +0 -16
  106. package/template/scripts/setup-rust.js +0 -29
  107. package/template/src/lib/format.ts +0 -35
  108. package/template/src/lib/hex.ts +0 -13
  109. package/template/src/lib/sdk.ts +0 -25
  110. package/template/src/lib/wasm-env.ts +0 -5
  111. package/template/wasm/indexd_wasm/indexd_wasm.d.ts +0 -309
  112. package/template/wasm/indexd_wasm/indexd_wasm.js +0 -1507
  113. package/template/wasm/indexd_wasm/indexd_wasm_bg.wasm +0 -0
  114. package/template/wasm/indexd_wasm/package.json +0 -31
@@ -1,1737 +0,0 @@
1
- use core::fmt;
2
- use std::ops::Deref;
3
-
4
- use blake2b_simd::Params;
5
- use num_bigint::BigInt;
6
- use num_rational::Ratio;
7
- use num_traits::{FromPrimitive, ToPrimitive};
8
- use serde::de::Error;
9
- use serde::{Deserialize, Serialize};
10
-
11
- use crate::consensus::ChainState;
12
- use crate::encoding::{
13
- self, SiaDecodable, SiaDecode, SiaEncodable, SiaEncode, V1SiaDecodable, V1SiaDecode,
14
- V1SiaEncodable, V1SiaEncode,
15
- };
16
- use crate::encoding_async::{AsyncSiaDecodable, AsyncSiaDecode, AsyncSiaEncodable, AsyncSiaEncode};
17
- use crate::merkle::{Accumulator, LEAF_HASH_PREFIX};
18
- use crate::signing::PublicKey;
19
- use crate::types::{Specifier, specifier};
20
-
21
- use super::currency::Currency;
22
- use super::{
23
- Address, FileContractID, Hash256, HexParseError, Leaf, SiacoinOutput, SiacoinOutputID,
24
- SiafundOutput, SiafundOutputID, StateElement, TransactionID,
25
- };
26
-
27
- pub const ALGORITHM_ED25519: Specifier = specifier!["ed25519"];
28
-
29
- /// A generic public key that can be used to spend a utxo or revise a file
30
- /// contract
31
- ///
32
- /// Currently only supports ed25519 keys
33
- #[derive(
34
- Debug,
35
- PartialEq,
36
- Clone,
37
- AsyncSiaDecode,
38
- AsyncSiaEncode,
39
- SiaEncode,
40
- V1SiaEncode,
41
- SiaDecode,
42
- V1SiaDecode,
43
- )]
44
- pub struct UnlockKey {
45
- pub algorithm: Specifier,
46
- pub key: Vec<u8>,
47
- }
48
-
49
- impl Serialize for UnlockKey {
50
- fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
51
- String::serialize(&self.to_string(), serializer)
52
- }
53
- }
54
-
55
- impl<'de> Deserialize<'de> for UnlockKey {
56
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
57
- where
58
- D: serde::Deserializer<'de>,
59
- {
60
- if deserializer.is_human_readable() {
61
- let s = String::deserialize(deserializer)?;
62
- s.parse().map_err(|e| Error::custom(format!("{e:?}")))
63
- } else {
64
- let (algorithm, key) = <(Specifier, Vec<u8>)>::deserialize(deserializer)?;
65
- Ok(Self { algorithm, key })
66
- }
67
- }
68
- }
69
-
70
- impl fmt::Display for UnlockKey {
71
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72
- write!(f, "{}:{}", self.algorithm, hex::encode(self.key.as_slice()))
73
- }
74
- }
75
-
76
- impl std::str::FromStr for UnlockKey {
77
- type Err = crate::types::HexParseError;
78
-
79
- fn from_str(s: &str) -> Result<Self, Self::Err> {
80
- let (prefix, key_str) = s.split_once(':').ok_or(HexParseError::MissingPrefix)?;
81
- Ok(UnlockKey {
82
- algorithm: Specifier::from(prefix),
83
- key: hex::decode(key_str).map_err(HexParseError::HexError)?,
84
- })
85
- }
86
- }
87
-
88
- impl From<PublicKey> for UnlockKey {
89
- fn from(val: PublicKey) -> Self {
90
- UnlockKey {
91
- algorithm: ALGORITHM_ED25519,
92
- key: val.as_ref().to_vec(),
93
- }
94
- }
95
- }
96
-
97
- /// A FileContractElement is a record of a FileContract within the state accumulator.
98
- pub struct FileContractElement {
99
- pub state_element: StateElement,
100
- pub id: FileContractID,
101
- pub file_contract: FileContract,
102
- }
103
-
104
- // specifies the conditions for spending an output or revising a file contract.
105
- #[derive(
106
- Debug,
107
- PartialEq,
108
- Clone,
109
- Serialize,
110
- Deserialize,
111
- AsyncSiaDecode,
112
- AsyncSiaEncode,
113
- SiaEncode,
114
- SiaDecode,
115
- V1SiaEncode,
116
- V1SiaDecode,
117
- )]
118
- #[serde(rename_all = "camelCase")]
119
- pub struct UnlockConditions {
120
- pub timelock: u64,
121
- pub public_keys: Vec<UnlockKey>,
122
- pub signatures_required: u64,
123
- }
124
-
125
- impl UnlockConditions {
126
- pub fn new(
127
- timelock: u64,
128
- public_keys: Vec<UnlockKey>,
129
- required_signatures: u64,
130
- ) -> UnlockConditions {
131
- UnlockConditions {
132
- timelock,
133
- public_keys,
134
- signatures_required: required_signatures,
135
- }
136
- }
137
-
138
- pub fn standard_unlock_conditions(public_key: PublicKey) -> UnlockConditions {
139
- UnlockConditions {
140
- timelock: 0,
141
- public_keys: vec![public_key.into()],
142
- signatures_required: 1,
143
- }
144
- }
145
-
146
- pub fn address(&self) -> Address {
147
- let mut acc = Accumulator::new();
148
- let mut p = Params::new();
149
- p.hash_length(32);
150
-
151
- let h = p
152
- .to_state()
153
- .update(LEAF_HASH_PREFIX)
154
- .update(&self.timelock.to_le_bytes())
155
- .finalize();
156
-
157
- acc.add_leaf(h.into());
158
-
159
- for key in self.public_keys.iter() {
160
- let mut state = p.to_state();
161
- state.update(LEAF_HASH_PREFIX);
162
- key.encode(&mut state).unwrap();
163
-
164
- let h = state.finalize();
165
- acc.add_leaf(h.into());
166
- }
167
-
168
- let h = p
169
- .to_state()
170
- .update(LEAF_HASH_PREFIX)
171
- .update(&self.signatures_required.to_le_bytes())
172
- .finalize();
173
-
174
- acc.add_leaf(h.into());
175
-
176
- Address::new(acc.root().into())
177
- }
178
- }
179
-
180
- #[derive(Debug, PartialEq, Serialize, Deserialize, V1SiaEncode, V1SiaDecode)]
181
- #[serde(rename_all = "camelCase")]
182
- pub struct SiacoinInput {
183
- #[serde(rename = "parentID")]
184
- pub parent_id: SiacoinOutputID,
185
- pub unlock_conditions: UnlockConditions,
186
- }
187
-
188
- #[derive(Debug, PartialEq, Serialize, Deserialize, V1SiaEncode, V1SiaDecode)]
189
- #[serde(rename_all = "camelCase")]
190
- pub struct SiafundInput {
191
- #[serde(rename = "parentID")]
192
- pub parent_id: SiafundOutputID,
193
- pub unlock_conditions: UnlockConditions,
194
- pub claim_address: Address,
195
- }
196
-
197
- #[derive(Debug, PartialEq, Serialize, Deserialize, V1SiaEncode, V1SiaDecode)]
198
- #[serde(rename_all = "camelCase")]
199
- pub struct FileContract {
200
- #[serde(rename = "filesize")]
201
- pub file_size: u64,
202
- pub file_merkle_root: Hash256,
203
- pub window_start: u64,
204
- pub window_end: u64,
205
- pub payout: Currency,
206
- pub valid_proof_outputs: Vec<SiacoinOutput>,
207
- pub missed_proof_outputs: Vec<SiacoinOutput>,
208
- pub unlock_hash: Address,
209
- pub revision_number: u64,
210
- }
211
-
212
- impl FileContract {
213
- pub fn tax(&self, cs: &ChainState) -> Currency {
214
- let payout = BigInt::from_u128(*self.payout.deref()).unwrap();
215
- let tax = if cs.child_height() < cs.network.hardfork_tax.height {
216
- let tax = Ratio::from(payout) * Ratio::from_float(0.039).unwrap();
217
- tax.numer() / tax.denom()
218
- } else {
219
- payout * 39 / 1000
220
- };
221
- Currency::new((&tax - &tax % cs.siafund_count()).to_u128().unwrap())
222
- }
223
- }
224
-
225
- #[derive(Debug, PartialEq, Serialize, Deserialize, V1SiaEncode, V1SiaDecode)]
226
- #[serde(rename_all = "camelCase")]
227
- pub struct FileContractRevision {
228
- #[serde(rename = "parentID")]
229
- pub parent_id: FileContractID,
230
- pub unlock_conditions: UnlockConditions,
231
- pub revision_number: u64,
232
- #[serde(rename = "filesize")]
233
- pub file_size: u64,
234
- pub file_merkle_root: Hash256,
235
- pub window_start: u64,
236
- pub window_end: u64,
237
- pub valid_proof_outputs: Vec<SiacoinOutput>,
238
- pub missed_proof_outputs: Vec<SiacoinOutput>,
239
- pub unlock_hash: Address,
240
- }
241
-
242
- #[derive(Debug, PartialEq, Serialize, Deserialize, V1SiaEncode, V1SiaDecode)]
243
- #[serde(rename_all = "camelCase")]
244
- pub struct StorageProof {
245
- #[serde(rename = "parentID")]
246
- pub parent_id: FileContractID,
247
- pub leaf: Leaf,
248
- pub proof: Vec<Hash256>,
249
- }
250
-
251
- #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize, V1SiaEncode, V1SiaDecode)]
252
- #[serde(rename_all = "camelCase")]
253
- pub struct CoveredFields {
254
- pub whole_transaction: bool,
255
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
256
- pub siacoin_inputs: Vec<usize>,
257
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
258
- pub siacoin_outputs: Vec<usize>,
259
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
260
- pub file_contracts: Vec<usize>,
261
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
262
- pub file_contract_revisions: Vec<usize>,
263
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
264
- pub storage_proofs: Vec<usize>,
265
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
266
- pub siafund_inputs: Vec<usize>,
267
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
268
- pub siafund_outputs: Vec<usize>,
269
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
270
- pub miner_fees: Vec<usize>,
271
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
272
- pub arbitrary_data: Vec<usize>,
273
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
274
- pub signatures: Vec<usize>,
275
- }
276
-
277
- impl CoveredFields {
278
- pub fn whole_transaction() -> Self {
279
- CoveredFields {
280
- whole_transaction: true,
281
- ..Default::default()
282
- }
283
- }
284
- }
285
-
286
- #[derive(Debug, PartialEq, Serialize, Deserialize, V1SiaEncode, V1SiaDecode)]
287
- #[serde(rename_all = "camelCase")]
288
- pub struct TransactionSignature {
289
- #[serde(rename = "parentID")]
290
- pub parent_id: Hash256,
291
- pub public_key_index: u64,
292
- pub timelock: u64,
293
- pub covered_fields: CoveredFields,
294
- #[serde(with = "crate::types::utils::base64")]
295
- pub signature: Vec<u8>,
296
- }
297
-
298
- #[derive(Default, Debug, PartialEq, Serialize, Deserialize, V1SiaEncode, V1SiaDecode)]
299
- #[serde(rename_all = "camelCase")]
300
- pub struct Transaction {
301
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
302
- pub siacoin_inputs: Vec<SiacoinInput>,
303
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
304
- pub siacoin_outputs: Vec<SiacoinOutput>,
305
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
306
- pub file_contracts: Vec<FileContract>,
307
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
308
- pub file_contract_revisions: Vec<FileContractRevision>,
309
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
310
- pub storage_proofs: Vec<StorageProof>,
311
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
312
- pub siafund_inputs: Vec<SiafundInput>,
313
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
314
- pub siafund_outputs: Vec<SiafundOutput>,
315
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
316
- pub miner_fees: Vec<Currency>,
317
- #[serde(
318
- default,
319
- skip_serializing_if = "Vec::is_empty",
320
- with = "crate::types::utils::vec_base64"
321
- )]
322
- pub arbitrary_data: Vec<Vec<u8>>,
323
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
324
- pub signatures: Vec<TransactionSignature>,
325
- }
326
-
327
- impl Transaction {
328
- pub fn encode_no_sigs<W: std::io::Write>(&self, w: &mut W) -> Result<(), encoding::Error> {
329
- self.siacoin_inputs.encode_v1(w)?;
330
- self.siacoin_outputs.encode_v1(w)?;
331
- self.file_contracts.encode_v1(w)?;
332
- self.file_contract_revisions.encode_v1(w)?;
333
- self.storage_proofs.encode_v1(w)?;
334
- self.siafund_inputs.encode_v1(w)?;
335
- self.siafund_outputs.encode_v1(w)?;
336
- self.miner_fees.encode_v1(w)?;
337
- self.arbitrary_data.encode_v1(w)
338
- }
339
-
340
- pub fn whole_sig_hash<T: AsRef<[u8; 32]>>(
341
- &self,
342
- cs: &ChainState,
343
- parent_id: &T,
344
- public_key_index: u64,
345
- timelock: u64,
346
- ) -> Result<Hash256, encoding::Error> {
347
- let mut state = Params::new().hash_length(32).to_state();
348
-
349
- state.update(&(self.siacoin_inputs.len() as u64).to_le_bytes());
350
- for input in self.siacoin_inputs.iter() {
351
- state.update(cs.replay_prefix());
352
- input.encode_v1(&mut state)?;
353
- }
354
-
355
- self.siacoin_outputs.encode_v1(&mut state)?;
356
- self.file_contracts.encode_v1(&mut state)?;
357
- self.file_contract_revisions.encode_v1(&mut state)?;
358
- self.storage_proofs.encode_v1(&mut state)?;
359
-
360
- state.update(&(self.siafund_inputs.len() as u64).to_le_bytes());
361
- for input in self.siafund_inputs.iter() {
362
- state.update(cs.replay_prefix());
363
- input.encode_v1(&mut state)?;
364
- }
365
-
366
- self.siafund_outputs.encode_v1(&mut state)?;
367
- self.miner_fees.encode_v1(&mut state)?;
368
- self.arbitrary_data.encode_v1(&mut state)?;
369
-
370
- state.update(parent_id.as_ref());
371
- public_key_index.encode_v1(&mut state)?;
372
- timelock.encode_v1(&mut state)?;
373
-
374
- Ok(state.finalize().into())
375
- }
376
-
377
- pub fn partial_sig_hash(
378
- &self,
379
- cs: &ChainState,
380
- covered_fields: &CoveredFields,
381
- ) -> Result<Hash256, encoding::Error> {
382
- let mut state = Params::new().hash_length(32).to_state();
383
-
384
- for &i in covered_fields.siacoin_inputs.iter() {
385
- if i >= self.siacoin_inputs.len() {
386
- return Err(encoding::Error::Custom(
387
- "siacoin_inputs index out of bounds".to_string(),
388
- ));
389
- }
390
- state.update(cs.replay_prefix());
391
- self.siacoin_inputs[i].encode_v1(&mut state)?;
392
- }
393
-
394
- for &i in covered_fields.siacoin_outputs.iter() {
395
- if i >= self.siacoin_outputs.len() {
396
- return Err(encoding::Error::Custom(
397
- "siacoin_outputs index out of bounds".to_string(),
398
- ));
399
- }
400
- self.siacoin_outputs[i].encode_v1(&mut state)?;
401
- }
402
-
403
- for &i in covered_fields.file_contracts.iter() {
404
- if i >= self.file_contracts.len() {
405
- return Err(encoding::Error::Custom(
406
- "file_contracts index out of bounds".to_string(),
407
- ));
408
- }
409
- self.file_contracts[i].encode_v1(&mut state)?;
410
- }
411
-
412
- for &i in covered_fields.file_contract_revisions.iter() {
413
- if i >= self.file_contract_revisions.len() {
414
- return Err(encoding::Error::Custom(
415
- "file_contract_revisions index out of bounds".to_string(),
416
- ));
417
- }
418
- self.file_contract_revisions[i].encode_v1(&mut state)?;
419
- }
420
-
421
- for &i in covered_fields.storage_proofs.iter() {
422
- if i >= self.storage_proofs.len() {
423
- return Err(encoding::Error::Custom(
424
- "storage_proofs index out of bounds".to_string(),
425
- ));
426
- }
427
- self.storage_proofs[i].encode_v1(&mut state)?;
428
- }
429
-
430
- for &i in covered_fields.siafund_inputs.iter() {
431
- if i >= self.siafund_inputs.len() {
432
- return Err(encoding::Error::Custom(
433
- "siafund_inputs index out of bounds".to_string(),
434
- ));
435
- }
436
- state.update(cs.replay_prefix());
437
- self.siafund_inputs[i].encode_v1(&mut state)?;
438
- }
439
-
440
- for &i in covered_fields.siafund_outputs.iter() {
441
- if i >= self.siafund_outputs.len() {
442
- return Err(encoding::Error::Custom(
443
- "siafund_outputs index out of bounds".to_string(),
444
- ));
445
- }
446
- self.siafund_outputs[i].encode_v1(&mut state)?;
447
- }
448
-
449
- for &i in covered_fields.miner_fees.iter() {
450
- if i >= self.miner_fees.len() {
451
- return Err(encoding::Error::Custom(
452
- "miner_fees index out of bounds".to_string(),
453
- ));
454
- }
455
- self.miner_fees[i].encode_v1(&mut state)?;
456
- }
457
-
458
- for &i in covered_fields.arbitrary_data.iter() {
459
- if i >= self.arbitrary_data.len() {
460
- return Err(encoding::Error::Custom(
461
- "arbitrary_data index out of bounds".to_string(),
462
- ));
463
- }
464
- self.arbitrary_data[i].encode_v1(&mut state)?;
465
- }
466
-
467
- for &i in covered_fields.signatures.iter() {
468
- if i >= self.signatures.len() {
469
- return Err(encoding::Error::Custom(
470
- "signatures index out of bounds".to_string(),
471
- ));
472
- }
473
- self.signatures[i].encode_v1(&mut state)?;
474
- }
475
- Ok(state.finalize().into())
476
- }
477
-
478
- pub fn id(&self) -> TransactionID {
479
- let mut state = Params::new().hash_length(32).to_state();
480
- self.encode_no_sigs(&mut state).unwrap();
481
-
482
- state.finalize().into()
483
- }
484
-
485
- fn derive_child_id<T: From<blake2b_simd::Hash>>(&self, prefix: &Specifier, i: usize) -> T {
486
- let mut state = Params::new().hash_length(32).to_state();
487
- state.update(prefix.as_ref());
488
- self.encode_no_sigs(&mut state).unwrap();
489
- state.update(&(i as u64).to_le_bytes());
490
- state.finalize().into()
491
- }
492
-
493
- /// siacoin_output_id returns the SiacoinOutputID for the i-th siacoin output of the transaction
494
- pub fn siacoin_output_id(&self, i: usize) -> SiacoinOutputID {
495
- const SIACOIN_OUTPUT_ID_PREFIX: Specifier = specifier!("siacoin output");
496
-
497
- self.derive_child_id(&SIACOIN_OUTPUT_ID_PREFIX, i)
498
- }
499
-
500
- /// siafund_output_id returns the SiafundOutputID for the i-th siafund output of the transaction
501
- pub fn siafund_output_id(&self, i: usize) -> SiafundOutputID {
502
- const SIAFUND_OUTPUT_ID_PREFIX: Specifier = specifier!("siafund output");
503
-
504
- self.derive_child_id(&SIAFUND_OUTPUT_ID_PREFIX, i)
505
- }
506
-
507
- /// file_contract_id returns the FileContractID for the i-th file contract of the transaction
508
- pub fn file_contract_id(&self, i: usize) -> FileContractID {
509
- const FILE_CONTRACT_ID_PREFIX: Specifier = specifier!("file contract");
510
-
511
- self.derive_child_id(&FILE_CONTRACT_ID_PREFIX, i)
512
- }
513
- }
514
-
515
- #[cfg(test)]
516
- mod tests {
517
- use super::*;
518
- use crate::consensus::{
519
- ElementAccumulator, HardforkASIC, HardforkDevAddr, HardforkFoundation, HardforkOak,
520
- HardforkStorageProof, HardforkTax, HardforkV2, Network, State,
521
- };
522
- use crate::seed::Seed;
523
- use crate::signing::{PrivateKey, PublicKey, Signature};
524
- use crate::types::{BlockID, ChainIndex, Work};
525
- use crate::{address, contract_id, hash_256, siacoin_id, siafund_id};
526
- use chrono::{DateTime, Duration};
527
- use serde::de::DeserializeOwned;
528
- use std::fmt::Debug;
529
- use std::vec;
530
-
531
- /// test_serialize_json is a helper to test serialization and deserialization of a struct to and from JSON.
532
- fn test_serialize_json<S: Serialize + DeserializeOwned + Debug + PartialEq>(
533
- obj: &S,
534
- json_str: &str,
535
- ) {
536
- let serialized = serde_json::to_string(&obj).unwrap();
537
- assert_eq!(serialized, json_str);
538
- let deserialized: S = serde_json::from_str(&serialized).unwrap();
539
- assert_eq!(deserialized, *obj);
540
- }
541
-
542
- /// test_serialize_v1 is a helper to test serialization and deserialization of a struct to and from Sia's
543
- /// custom binary encoding.
544
- fn test_serialize_v1<S: V1SiaEncodable + V1SiaDecodable + Debug + PartialEq>(
545
- obj: &S,
546
- hex_binary: &str,
547
- ) {
548
- let mut serialized = Vec::new();
549
- obj.encode_v1(&mut serialized).unwrap();
550
- assert_eq!(hex::encode(serialized.clone()), hex_binary);
551
- let deserialized = S::decode_v1(&mut &serialized[..]).unwrap();
552
- assert_eq!(deserialized, *obj);
553
- }
554
-
555
- #[test]
556
- fn test_serialize_unlock_key() {
557
- let unlock_key: UnlockKey = PublicKey::new([
558
- 0x9a, 0xac, 0x1f, 0xfb, 0x1c, 0xfd, 0x10, 0x79, 0xa8, 0xc6, 0xc8, 0x7b, 0x47, 0xda,
559
- 0x1d, 0x56, 0x7e, 0x35, 0xb9, 0x72, 0x34, 0x99, 0x3c, 0x28, 0x8c, 0x1a, 0xd0, 0xdb,
560
- 0x1d, 0x1c, 0xe1, 0xb6,
561
- ])
562
- .into();
563
-
564
- // binary
565
- let mut unlock_key_serialized: Vec<u8> = Vec::new();
566
- unlock_key.encode(&mut unlock_key_serialized).unwrap();
567
- assert_eq!(
568
- unlock_key_serialized,
569
- [
570
- 0x65, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571
- 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xac, 0x1f, 0xfb,
572
- 0x1c, 0xfd, 0x10, 0x79, 0xa8, 0xc6, 0xc8, 0x7b, 0x47, 0xda, 0x1d, 0x56, 0x7e, 0x35,
573
- 0xb9, 0x72, 0x34, 0x99, 0x3c, 0x28, 0x8c, 0x1a, 0xd0, 0xdb, 0x1d, 0x1c, 0xe1, 0xb6
574
- ]
575
- );
576
- //assert_eq!(unlock_key_deserialized, unlock_key);
577
-
578
- // json
579
- let unlock_key_serialized = serde_json::to_string(&unlock_key).unwrap();
580
- let unlock_key_deserialized: UnlockKey =
581
- serde_json::from_str(&unlock_key_serialized).unwrap();
582
- assert_eq!(
583
- unlock_key_serialized,
584
- "\"ed25519:9aac1ffb1cfd1079a8c6c87b47da1d567e35b97234993c288c1ad0db1d1ce1b6\""
585
- );
586
- assert_eq!(unlock_key_deserialized, unlock_key);
587
- }
588
-
589
- #[test]
590
- fn test_serialize_unlock_conditions() {
591
- let unlock_conditions = UnlockConditions::new(
592
- 123,
593
- vec![
594
- PublicKey::new([
595
- 0x9a, 0xac, 0x1f, 0xfb, 0x1c, 0xfd, 0x10, 0x79, 0xa8, 0xc6, 0xc8, 0x7b, 0x47,
596
- 0xda, 0x1d, 0x56, 0x7e, 0x35, 0xb9, 0x72, 0x34, 0x99, 0x3c, 0x28, 0x8c, 0x1a,
597
- 0xd0, 0xdb, 0x1d, 0x1c, 0xe1, 0xb6,
598
- ])
599
- .into(),
600
- ],
601
- 1,
602
- );
603
-
604
- // binary
605
- let mut unlock_conditions_serialized: Vec<u8> = Vec::new();
606
- unlock_conditions
607
- .encode(&mut unlock_conditions_serialized)
608
- .unwrap();
609
-
610
- assert_eq!(
611
- unlock_conditions_serialized,
612
- [
613
- 123, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 101, 100, 50, 53, 53, 49, 57, 0,
614
- 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 154, 172, 31, 251, 28, 253, 16,
615
- 121, 168, 198, 200, 123, 71, 218, 29, 86, 126, 53, 185, 114, 52, 153, 60, 40, 140,
616
- 26, 208, 219, 29, 28, 225, 182, 1, 0, 0, 0, 0, 0, 0, 0
617
- ]
618
- );
619
- //assert_eq!(unlock_conditions_deserialized, unlock_conditions);
620
-
621
- // json
622
- let unlock_conditions_serialized = serde_json::to_string(&unlock_conditions).unwrap();
623
- let unlock_conditions_deserialized: UnlockConditions =
624
- serde_json::from_str(&unlock_conditions_serialized).unwrap();
625
- assert_eq!(
626
- unlock_conditions_serialized,
627
- "{\"timelock\":123,\"publicKeys\":[\"ed25519:9aac1ffb1cfd1079a8c6c87b47da1d567e35b97234993c288c1ad0db1d1ce1b6\"],\"signaturesRequired\":1}"
628
- );
629
- assert_eq!(unlock_conditions_deserialized, unlock_conditions);
630
- }
631
-
632
- #[test]
633
- fn test_serialize_covered_fields() {
634
- let mut cf = CoveredFields::default();
635
- cf.siacoin_inputs.push(1);
636
- cf.siacoin_outputs.push(2);
637
- cf.siacoin_outputs.push(3);
638
-
639
- let binary_str = "000100000000000000010000000000000002000000000000000200000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
640
- test_serialize_v1(&cf, binary_str);
641
-
642
- let json_str =
643
- "{\"wholeTransaction\":false,\"siacoinInputs\":[1],\"siacoinOutputs\":[2,3]}";
644
- test_serialize_json(&cf, json_str);
645
- }
646
-
647
- #[test]
648
- fn test_serialize_siacoin_input() {
649
- let siacoin_input = SiacoinInput {
650
- parent_id: siacoin_id!(
651
- "b3633a1370a72002ae2a956d21e8d481c3a69e146633470cf625ecd83fdeaa24"
652
- ),
653
- unlock_conditions: UnlockConditions::new(
654
- 123,
655
- vec![
656
- PublicKey::new([
657
- 0x9a, 0xac, 0x1f, 0xfb, 0x1c, 0xfd, 0x10, 0x79, 0xa8, 0xc6, 0xc8, 0x7b,
658
- 0x47, 0xda, 0x1d, 0x56, 0x7e, 0x35, 0xb9, 0x72, 0x34, 0x99, 0x3c, 0x28,
659
- 0x8c, 0x1a, 0xd0, 0xdb, 0x1d, 0x1c, 0xe1, 0xb6,
660
- ])
661
- .into(),
662
- ],
663
- 1,
664
- ),
665
- };
666
-
667
- let binary_str = hex::encode([
668
- 179, 99, 58, 19, 112, 167, 32, 2, 174, 42, 149, 109, 33, 232, 212, 129, 195, 166, 158,
669
- 20, 102, 51, 71, 12, 246, 37, 236, 216, 63, 222, 170, 36, 123, 0, 0, 0, 0, 0, 0, 0, 1,
670
- 0, 0, 0, 0, 0, 0, 0, 101, 100, 50, 53, 53, 49, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0,
671
- 0, 0, 0, 0, 0, 154, 172, 31, 251, 28, 253, 16, 121, 168, 198, 200, 123, 71, 218, 29,
672
- 86, 126, 53, 185, 114, 52, 153, 60, 40, 140, 26, 208, 219, 29, 28, 225, 182, 1, 0, 0,
673
- 0, 0, 0, 0, 0,
674
- ]);
675
- test_serialize_v1(&siacoin_input, binary_str.as_str());
676
-
677
- let json_str = "{\"parentID\":\"b3633a1370a72002ae2a956d21e8d481c3a69e146633470cf625ecd83fdeaa24\",\"unlockConditions\":{\"timelock\":123,\"publicKeys\":[\"ed25519:9aac1ffb1cfd1079a8c6c87b47da1d567e35b97234993c288c1ad0db1d1ce1b6\"],\"signaturesRequired\":1}}";
678
- test_serialize_json(&siacoin_input, json_str);
679
- }
680
-
681
- #[test]
682
- fn test_serialize_siafund_input() {
683
- let siafund_input = SiafundInput {
684
- parent_id: siafund_id!(
685
- "b3633a1370a72002ae2a956d21e8d481c3a69e146633470cf625ecd83fdeaa24"
686
- ),
687
- unlock_conditions: UnlockConditions::new(
688
- 123,
689
- vec![
690
- PublicKey::new([
691
- 0x9a, 0xac, 0x1f, 0xfb, 0x1c, 0xfd, 0x10, 0x79, 0xa8, 0xc6, 0xc8, 0x7b,
692
- 0x47, 0xda, 0x1d, 0x56, 0x7e, 0x35, 0xb9, 0x72, 0x34, 0x99, 0x3c, 0x28,
693
- 0x8c, 0x1a, 0xd0, 0xdb, 0x1d, 0x1c, 0xe1, 0xb6,
694
- ])
695
- .into(),
696
- ],
697
- 1,
698
- ),
699
- claim_address: Address::new(
700
- hex::decode("8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c")
701
- .unwrap()
702
- .try_into()
703
- .unwrap(),
704
- ),
705
- };
706
-
707
- // binary
708
- let binary_str = hex::encode([
709
- 179, 99, 58, 19, 112, 167, 32, 2, 174, 42, 149, 109, 33, 232, 212, 129, 195, 166, 158,
710
- 20, 102, 51, 71, 12, 246, 37, 236, 216, 63, 222, 170, 36, 123, 0, 0, 0, 0, 0, 0, 0, 1,
711
- 0, 0, 0, 0, 0, 0, 0, 101, 100, 50, 53, 53, 49, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0,
712
- 0, 0, 0, 0, 0, 154, 172, 31, 251, 28, 253, 16, 121, 168, 198, 200, 123, 71, 218, 29,
713
- 86, 126, 53, 185, 114, 52, 153, 60, 40, 140, 26, 208, 219, 29, 28, 225, 182, 1, 0, 0,
714
- 0, 0, 0, 0, 0, 143, 180, 156, 207, 23, 223, 220, 201, 82, 109, 236, 110, 232, 165, 204,
715
- 162, 15, 248, 36, 115, 2, 5, 61, 55, 119, 65, 11, 155, 4, 148, 186, 140,
716
- ]);
717
- test_serialize_v1(&siafund_input, binary_str.as_str());
718
-
719
- let json_str = "{\"parentID\":\"b3633a1370a72002ae2a956d21e8d481c3a69e146633470cf625ecd83fdeaa24\",\"unlockConditions\":{\"timelock\":123,\"publicKeys\":[\"ed25519:9aac1ffb1cfd1079a8c6c87b47da1d567e35b97234993c288c1ad0db1d1ce1b6\"],\"signaturesRequired\":1},\"claimAddress\":\"8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8cdf32abee86f0\"}";
720
- test_serialize_json(&siafund_input, json_str);
721
- }
722
-
723
- #[test]
724
- fn test_serialize_transaction_signature() {
725
- let signature = TransactionSignature {
726
- parent_id: hash_256!(
727
- "b3633a1370a72002ae2a956d21e8d481c3a69e146633470cf625ecd83fdeaa24"
728
- ),
729
- public_key_index: 1,
730
- timelock: 2,
731
- covered_fields: CoveredFields {
732
- whole_transaction: true,
733
- ..Default::default()
734
- },
735
- signature: Signature::new([3u8; 64]).data().to_vec(),
736
- };
737
-
738
- let binary_str = hex::encode([
739
- 179, 99, 58, 19, 112, 167, 32, 2, 174, 42, 149, 109, 33, 232, 212, 129, 195, 166, 158,
740
- 20, 102, 51, 71, 12, 246, 37, 236, 216, 63, 222, 170, 36, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0,
741
- 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
742
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
743
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
744
- 64, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
745
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
746
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
747
- ]);
748
- test_serialize_v1(&signature, binary_str.as_str());
749
-
750
- let json_str = "{\"parentID\":\"b3633a1370a72002ae2a956d21e8d481c3a69e146633470cf625ecd83fdeaa24\",\"publicKeyIndex\":1,\"timelock\":2,\"coveredFields\":{\"wholeTransaction\":true},\"signature\":\"AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw==\"}";
751
- test_serialize_json(&signature, json_str);
752
- }
753
-
754
- #[test]
755
- fn test_serialize_filecontract() {
756
- let contract = FileContract {
757
- file_size: 1,
758
- file_merkle_root: Hash256::from([
759
- 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
760
- 0, 0, 0, 0,
761
- ]),
762
- window_start: 2,
763
- window_end: 3,
764
- payout: Currency::new(456),
765
- valid_proof_outputs: vec![SiacoinOutput {
766
- value: Currency::new(789),
767
- address: Address::new([
768
- 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
769
- 0, 0, 0, 0, 0, 0,
770
- ]),
771
- }],
772
- missed_proof_outputs: vec![SiacoinOutput {
773
- value: Currency::new(101112),
774
- address: Address::new([
775
- 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
776
- 0, 0, 0, 0, 0, 0,
777
- ]),
778
- }],
779
- unlock_hash: Address::from([
780
- 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
781
- 0, 0, 0, 0,
782
- ]),
783
- revision_number: 4,
784
- };
785
-
786
- let binary_str = hex::encode([
787
- 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
788
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0,
789
- 0, 0, 0, 0, 0, 0, 1, 200, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 21, 2, 2,
790
- 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
791
- 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 138, 248, 3, 3, 3, 0, 0, 0, 0, 0,
792
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0,
793
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
794
- 0, 0, 0, 0, 0, 0,
795
- ]);
796
- test_serialize_v1(&contract, binary_str.as_str());
797
-
798
- let json_str = "{\"filesize\":1,\"fileMerkleRoot\":\"0101010000000000000000000000000000000000000000000000000000000000\",\"windowStart\":2,\"windowEnd\":3,\"payout\":\"456\",\"validProofOutputs\":[{\"value\":\"789\",\"address\":\"02020200000000000000000000000000000000000000000000000000000000008749787b31db\"}],\"missedProofOutputs\":[{\"value\":\"101112\",\"address\":\"0303030000000000000000000000000000000000000000000000000000000000c596d559a239\"}],\"unlockHash\":\"04040400000000000000000000000000000000000000000000000000000000006c604f10c928\",\"revisionNumber\":4}";
799
- test_serialize_json(&contract, json_str);
800
- }
801
-
802
- #[test]
803
- fn test_serialize_filecontract_revision() {
804
- let revision = FileContractRevision {
805
- parent_id: FileContractID::from([
806
- 9, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
807
- 0, 0, 0, 0,
808
- ]),
809
- file_size: 1,
810
- file_merkle_root: Hash256::from([
811
- 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
812
- 0, 0, 0, 0,
813
- ]),
814
- window_start: 2,
815
- window_end: 3,
816
- valid_proof_outputs: vec![SiacoinOutput {
817
- value: Currency::new(789),
818
- address: Address::new([
819
- 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
820
- 0, 0, 0, 0, 0, 0,
821
- ]),
822
- }],
823
- missed_proof_outputs: vec![SiacoinOutput {
824
- value: Currency::new(789),
825
- address: Address::new([
826
- 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
827
- 0, 0, 0, 0, 0, 0,
828
- ]),
829
- }],
830
- unlock_conditions: UnlockConditions::new(
831
- 123,
832
- vec![
833
- PublicKey::new([
834
- 0x9a, 0xac, 0x1f, 0xfb, 0x1c, 0xfd, 0x10, 0x79, 0xa8, 0xc6, 0xc8, 0x7b,
835
- 0x47, 0xda, 0x1d, 0x56, 0x7e, 0x35, 0xb9, 0x72, 0x34, 0x99, 0x3c, 0x28,
836
- 0x8c, 0x1a, 0xd0, 0xdb, 0x1d, 0x1c, 0xe1, 0xb6,
837
- ])
838
- .into(),
839
- ],
840
- 1,
841
- ),
842
- unlock_hash: Address::from([
843
- 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
844
- 0, 0, 0, 0,
845
- ]),
846
- revision_number: 4,
847
- };
848
-
849
- let binary_str = hex::encode([
850
- 9, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
851
- 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 101, 100, 50, 53, 53, 49,
852
- 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 154, 172, 31, 251, 28, 253, 16,
853
- 121, 168, 198, 200, 123, 71, 218, 29, 86, 126, 53, 185, 114, 52, 153, 60, 40, 140, 26,
854
- 208, 219, 29, 28, 225, 182, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
855
- 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
856
- 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
857
- 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 21, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
858
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
859
- 0, 0, 3, 21, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
860
- 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
861
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
862
- ]);
863
- test_serialize_v1(&revision, binary_str.as_str());
864
-
865
- let json_str = "{\"parentID\":\"0908070000000000000000000000000000000000000000000000000000000000\",\"unlockConditions\":{\"timelock\":123,\"publicKeys\":[\"ed25519:9aac1ffb1cfd1079a8c6c87b47da1d567e35b97234993c288c1ad0db1d1ce1b6\"],\"signaturesRequired\":1},\"revisionNumber\":4,\"filesize\":1,\"fileMerkleRoot\":\"0101010000000000000000000000000000000000000000000000000000000000\",\"windowStart\":2,\"windowEnd\":3,\"validProofOutputs\":[{\"value\":\"789\",\"address\":\"02020200000000000000000000000000000000000000000000000000000000008749787b31db\"}],\"missedProofOutputs\":[{\"value\":\"789\",\"address\":\"0303030000000000000000000000000000000000000000000000000000000000c596d559a239\"}],\"unlockHash\":\"04040400000000000000000000000000000000000000000000000000000000006c604f10c928\"}";
866
- test_serialize_json(&revision, json_str);
867
- }
868
-
869
- #[test]
870
- fn test_serialize_storage_proof() {
871
- let storage_proof = StorageProof {
872
- parent_id: contract_id!(
873
- "b3633a1370a72002ae2a956d21e8d481c3a69e146633470cf625ecd83fdeaa24"
874
- ),
875
- leaf: Leaf::from([
876
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
877
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
878
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
879
- ]),
880
- proof: vec![
881
- hash_256!("0102030000000000000000000000000000000000000000000000000000000000"),
882
- hash_256!("0405060000000000000000000000000000000000000000000000000000000000"),
883
- ],
884
- };
885
-
886
- let binary_str = hex::encode([
887
- 179, 99, 58, 19, 112, 167, 32, 2, 174, 42, 149, 109, 33, 232, 212, 129, 195, 166, 158,
888
- 20, 102, 51, 71, 12, 246, 37, 236, 216, 63, 222, 170, 36, 1, 2, 3, 4, 5, 6, 7, 8, 9,
889
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
890
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
891
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 2, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0,
892
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6,
893
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
894
- ]);
895
- test_serialize_v1(&storage_proof, binary_str.as_str());
896
-
897
- let json_str = "{\"parentID\":\"b3633a1370a72002ae2a956d21e8d481c3a69e146633470cf625ecd83fdeaa24\",\"leaf\":\"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40\",\"proof\":[\"0102030000000000000000000000000000000000000000000000000000000000\",\"0405060000000000000000000000000000000000000000000000000000000000\"]}";
898
- test_serialize_json(&storage_proof, json_str);
899
- }
900
-
901
- #[test]
902
- fn test_serialize_transaction() {
903
- let transaction = Transaction {
904
- siacoin_inputs: vec![SiacoinInput {
905
- parent_id: siacoin_id!(
906
- "750d22eff727689d1d8d1c83e513a30bb68ee7f9125a4dafc882459e34c2069d"
907
- ),
908
- unlock_conditions: UnlockConditions {
909
- timelock: 0,
910
- public_keys: vec!["ed25519:800ed6c2760e3e4ba1ff00128585c8cf8fed2e3dc1e3da1eb92d49f405bd6360".parse().unwrap()],
911
- signatures_required: 6312611591377486220,
912
- },
913
- }],
914
- siacoin_outputs: vec![SiacoinOutput {
915
- value: Currency::new(890415399000000000000000000000000),
916
- address: address!("480a064b5fca13002a7fe575845154bbf0b3af4cc4f147cbed387d43cce3568ae2497366eaa7"),
917
- }],
918
- file_contracts: vec![
919
- FileContract{
920
- file_size: 0,
921
- file_merkle_root: Hash256::default(),
922
- window_start: 10536451586783908586,
923
- window_end: 9324702155635244357,
924
- payout: Currency::new(0),
925
- unlock_hash: Address::default(),
926
- revision_number: 9657412421282982780,
927
- valid_proof_outputs: vec![
928
- SiacoinOutput{
929
- value: Currency::new(1933513214000000000000000000000000),
930
- address: address!("944524fff2c49c401e748db37cfda7569fa6df35b704fe716394f2ac3f40ce87b4506e9906f0"),
931
- }
932
- ],
933
- missed_proof_outputs: vec![
934
- SiacoinOutput{
935
- value: Currency::new(2469287901000000000000000000000000),
936
- address: address!("1df67838262d7109ffcd9018f183b1eb33f05659a274b89ea6b52ff3617d34a770e9dd071d2e"),
937
- }
938
- ]
939
- }
940
- ],
941
- file_contract_revisions: vec![
942
- FileContractRevision{
943
- parent_id: contract_id!(
944
- "e4e26d93771d3bbb3d9dd306105d77cfb3a6254d1cc3495903af6e013442c63c"),
945
- unlock_conditions: UnlockConditions { timelock: 0, public_keys: vec!["ed25519:e6b9cde4eb058f8ecbb083d99779cb0f6d518d5386f019af6ead09fa52de8567".parse().unwrap()], signatures_required: 206644730660526450 },
946
- revision_number: 10595710523108536025,
947
- file_size: 0,
948
- file_merkle_root: Hash256::default(),
949
- window_start: 4348934140507359445,
950
- window_end: 14012366839994454386,
951
- valid_proof_outputs: vec![
952
- SiacoinOutput{
953
- value: Currency::new(2435858510000000000000000000000000),
954
- address: address!("543bc0eda69f728d0a0fbce08e5bfc5ed7b961300e0af226949e135f7d12e32f0544e5262d6f"),
955
- }
956
- ],
957
- missed_proof_outputs: vec![
958
- SiacoinOutput{
959
- value: Currency::new(880343701000000000000000000000000),
960
- address: address!("7b7f9aee981fe0d93bb3f49c6233cf847ebdd39d7dc5253f7fc330df2167073b35f035703237"),
961
- },
962
- ],
963
- unlock_hash: Address::default(),
964
- }
965
- ],
966
- storage_proofs: vec![
967
- StorageProof{
968
- parent_id: contract_id!(
969
- "c0b9e98c9e03a2740c75d673871c1ee91f36d1bb329ff3ddbf1dfa8c6e1a64eb"),
970
- leaf: "b78fa521dc62d9ced82bc3b61e0aa5a5c221d6cca5db63d94c9879543fb98c0a971094a89cd4408487ae32902248d321b545f9a051729aa0bb1725b848e3d453".parse().unwrap(),
971
- proof: vec![
972
- hash_256!("fe08c0a061475e7e5dec19e717cf98792fa7b555d0b5d3540a05db09f59ab8de"),
973
- ],
974
- }
975
- ],
976
- siafund_inputs: Vec::new(),
977
- siafund_outputs: Vec::new(),
978
- miner_fees: vec![
979
- Currency::new(241119475000000000000000000000000),
980
- ],
981
- arbitrary_data: vec![
982
- vec![218,200,115,32,113,20,37,140,46,52,124,250,115,248,15,207,230,147,17,102,81,78,144,211,153,233,151,247,38,0,42,86]
983
- ],
984
- signatures: vec![
985
- TransactionSignature{
986
- parent_id: hash_256!("06d1fca03c5ddd9b09116db1b97c5451f7dc792b05362969f83e3e8dc1007f46"),
987
- public_key_index: 6088345341283457116,
988
- timelock: 2014247885072555224,
989
- covered_fields: CoveredFields::whole_transaction(),
990
- signature: vec![217,115,68,40,102,107,151,212,97,49,173,137,152,107,47,114,106,144,88,2,23,254,236,109,51,2,231,60,142,149,36,247,23,170,230,250,169,130,46,160,4,225,98,159,77,3,6,157,147,237,70,27,160,151,11,174,160,226,179,163,21,139,141,72],
991
- },
992
- ],
993
- };
994
- let binary_str = "0100000000000000750d22eff727689d1d8d1c83e513a30bb68ee7f9125a4dafc882459e34c2069d00000000000000000100000000000000656432353531390000000000000000002000000000000000800ed6c2760e3e4ba1ff00128585c8cf8fed2e3dc1e3da1eb92d49f405bd63608c8111f5cbe69a5701000000000000000e000000000000002be69f532be55cd4697c87000000480a064b5fca13002a7fe575845154bbf0b3af4cc4f147cbed387d43cce3568a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ea125bc7e4fe3892453df5c634ff6781000000000000000001000000000000000e000000000000005f545e24bc638098ba76be000000944524fff2c49c401e748db37cfda7569fa6df35b704fe716394f2ac3f40ce8701000000000000000e0000000000000079becb8684da8f5198dafd0000001df67838262d7109ffcd9018f183b1eb33f05659a274b89ea6b52ff3617d34a700000000000000000000000000000000000000000000000000000000000000007c6b04146e0506860100000000000000e4e26d93771d3bbb3d9dd306105d77cfb3a6254d1cc3495903af6e013442c63c00000000000000000100000000000000656432353531390000000000000000002000000000000000e6b9cde4eb058f8ecbb083d99779cb0f6d518d5386f019af6ead09fa52de85677219baa54926de02d9aec01095860b9300000000000000000000000000000000000000000000000000000000000000000000000000000000d58882248f845a3c7211557866ed75c201000000000000000e000000000000007818db5664f130fd08a70e000000543bc0eda69f728d0a0fbce08e5bfc5ed7b961300e0af226949e135f7d12e32f01000000000000000e000000000000002b677fe9d9b27794cd88b50000007b7f9aee981fe0d93bb3f49c6233cf847ebdd39d7dc5253f7fc330df2167073b00000000000000000000000000000000000000000000000000000000000000000100000000000000c0b9e98c9e03a2740c75d673871c1ee91f36d1bb329ff3ddbf1dfa8c6e1a64ebb78fa521dc62d9ced82bc3b61e0aa5a5c221d6cca5db63d94c9879543fb98c0a971094a89cd4408487ae32902248d321b545f9a051729aa0bb1725b848e3d4530100000000000000fe08c0a061475e7e5dec19e717cf98792fa7b555d0b5d3540a05db09f59ab8de0000000000000000000000000000000001000000000000000e000000000000000be35b0b076a36b5d2bfd300000001000000000000002000000000000000dac873207114258c2e347cfa73f80fcfe6931166514e90d399e997f726002a56010000000000000006d1fca03c5ddd9b09116db1b97c5451f7dc792b05362969f83e3e8dc1007f465cd81a99d4257e54d8dc548fc70bf41b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000d9734428666b97d46131ad89986b2f726a90580217feec6d3302e73c8e9524f717aae6faa9822ea004e1629f4d03069d93ed461ba0970baea0e2b3a3158b8d48";
995
- test_serialize_v1(&transaction, binary_str);
996
-
997
- let json_str = "{\"siacoinInputs\":[{\"parentID\":\"750d22eff727689d1d8d1c83e513a30bb68ee7f9125a4dafc882459e34c2069d\",\"unlockConditions\":{\"timelock\":0,\"publicKeys\":[\"ed25519:800ed6c2760e3e4ba1ff00128585c8cf8fed2e3dc1e3da1eb92d49f405bd6360\"],\"signaturesRequired\":6312611591377486220}}],\"siacoinOutputs\":[{\"value\":\"890415399000000000000000000000000\",\"address\":\"480a064b5fca13002a7fe575845154bbf0b3af4cc4f147cbed387d43cce3568ae2497366eaa7\"}],\"fileContracts\":[{\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"windowStart\":10536451586783908586,\"windowEnd\":9324702155635244357,\"payout\":\"0\",\"validProofOutputs\":[{\"value\":\"1933513214000000000000000000000000\",\"address\":\"944524fff2c49c401e748db37cfda7569fa6df35b704fe716394f2ac3f40ce87b4506e9906f0\"}],\"missedProofOutputs\":[{\"value\":\"2469287901000000000000000000000000\",\"address\":\"1df67838262d7109ffcd9018f183b1eb33f05659a274b89ea6b52ff3617d34a770e9dd071d2e\"}],\"unlockHash\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\",\"revisionNumber\":9657412421282982780}],\"fileContractRevisions\":[{\"parentID\":\"e4e26d93771d3bbb3d9dd306105d77cfb3a6254d1cc3495903af6e013442c63c\",\"unlockConditions\":{\"timelock\":0,\"publicKeys\":[\"ed25519:e6b9cde4eb058f8ecbb083d99779cb0f6d518d5386f019af6ead09fa52de8567\"],\"signaturesRequired\":206644730660526450},\"revisionNumber\":10595710523108536025,\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"windowStart\":4348934140507359445,\"windowEnd\":14012366839994454386,\"validProofOutputs\":[{\"value\":\"2435858510000000000000000000000000\",\"address\":\"543bc0eda69f728d0a0fbce08e5bfc5ed7b961300e0af226949e135f7d12e32f0544e5262d6f\"}],\"missedProofOutputs\":[{\"value\":\"880343701000000000000000000000000\",\"address\":\"7b7f9aee981fe0d93bb3f49c6233cf847ebdd39d7dc5253f7fc330df2167073b35f035703237\"}],\"unlockHash\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"}],\"storageProofs\":[{\"parentID\":\"c0b9e98c9e03a2740c75d673871c1ee91f36d1bb329ff3ddbf1dfa8c6e1a64eb\",\"leaf\":\"b78fa521dc62d9ced82bc3b61e0aa5a5c221d6cca5db63d94c9879543fb98c0a971094a89cd4408487ae32902248d321b545f9a051729aa0bb1725b848e3d453\",\"proof\":[\"fe08c0a061475e7e5dec19e717cf98792fa7b555d0b5d3540a05db09f59ab8de\"]}],\"minerFees\":[\"241119475000000000000000000000000\"],\"arbitraryData\":[\"2shzIHEUJYwuNHz6c/gPz+aTEWZRTpDTmemX9yYAKlY=\"],\"signatures\":[{\"parentID\":\"06d1fca03c5ddd9b09116db1b97c5451f7dc792b05362969f83e3e8dc1007f46\",\"publicKeyIndex\":6088345341283457116,\"timelock\":2014247885072555224,\"coveredFields\":{\"wholeTransaction\":true},\"signature\":\"2XNEKGZrl9RhMa2JmGsvcmqQWAIX/uxtMwLnPI6VJPcXqub6qYIuoAThYp9NAwadk+1GG6CXC66g4rOjFYuNSA==\"}]}";
998
- test_serialize_json(&transaction, json_str);
999
- }
1000
-
1001
- #[test]
1002
- fn test_transaction_id() {
1003
- let txn = Transaction::default();
1004
- let id = txn.id();
1005
- assert_eq!(
1006
- hex::encode(id),
1007
- "b3633a1370a72002ae2a956d21e8d481c3a69e146633470cf625ecd83fdeaa24"
1008
- );
1009
- }
1010
-
1011
- #[test]
1012
- fn test_transaction_whole_sig_hash() {
1013
- let cs = ChainState {
1014
- state: State {
1015
- index: ChainIndex {
1016
- height: 1,
1017
- id: BlockID::default(),
1018
- },
1019
- prev_timestamps: [DateTime::UNIX_EPOCH; 11],
1020
- depth: BlockID::default(),
1021
- child_target: BlockID::default(),
1022
- siafund_pool: Currency::new(0),
1023
- oak_time: Duration::zero(),
1024
- oak_target: BlockID::default(),
1025
- foundation_primary_address: Address::new([0u8; 32]),
1026
- foundation_failsafe_address: Address::new([0u8; 32]),
1027
- total_work: Work::zero(),
1028
- difficulty: Work::zero(),
1029
- oak_work: Work::zero(),
1030
- attestations: 0,
1031
- elements: ElementAccumulator::default(),
1032
- },
1033
- network: Network {
1034
- name: "test".to_string(),
1035
- initial_coinbase: Currency::new(0),
1036
- minimum_coinbase: Currency::new(0),
1037
- initial_target: BlockID::default(),
1038
- block_interval: Duration::seconds(1),
1039
- maturity_delay: 0,
1040
- hardfork_dev_addr: HardforkDevAddr {
1041
- height: 0,
1042
- old_address: Address::new([0u8; 32]),
1043
- new_address: Address::new([0u8; 32]),
1044
- },
1045
- hardfork_tax: HardforkTax { height: 10 },
1046
- hardfork_storage_proof: HardforkStorageProof { height: 0 },
1047
- hardfork_asic: HardforkASIC {
1048
- height: 0,
1049
- oak_time: Duration::zero(),
1050
- oak_target: BlockID::default(),
1051
- },
1052
- hardfork_oak: HardforkOak {
1053
- height: 0,
1054
- fix_height: 0,
1055
- genesis_timestamp: DateTime::UNIX_EPOCH,
1056
- },
1057
- hardfork_foundation: HardforkFoundation {
1058
- height: 0,
1059
- primary_address: Address::new([0u8; 32]),
1060
- failsafe_address: Address::new([0u8; 32]),
1061
- },
1062
- hardfork_v2: HardforkV2 {
1063
- // test was made for pre-v2
1064
- allow_height: 100,
1065
- require_height: 100,
1066
- },
1067
- },
1068
- };
1069
- let pk = PrivateKey::from_seed(&[
1070
- 136, 215, 58, 248, 45, 30, 78, 97, 128, 111, 82, 204, 43, 233, 223, 111, 110, 29, 73,
1071
- 157, 52, 25, 242, 96, 131, 16, 187, 22, 232, 107, 17, 205,
1072
- ]);
1073
- struct TestCase {
1074
- transaction: Transaction,
1075
- parent_id: Hash256,
1076
- timelock: u64,
1077
- key_index: u64,
1078
- expected: &'static str,
1079
- }
1080
- let test_cases = vec![
1081
- TestCase{
1082
- transaction: Transaction {
1083
- siacoin_inputs: vec![
1084
- SiacoinInput{
1085
- parent_id: siacoin_id!("200bd724a6ae87005cd7b3124ae5349addc2d5d8db2fe1cdfb54f80245fc2575"),
1086
- unlock_conditions: UnlockConditions::standard_unlock_conditions(pk.public_key()),
1087
- }
1088
- ],
1089
- siacoin_outputs: vec![
1090
- SiacoinOutput{
1091
- value: Currency::new(67856467336433871),
1092
- address: address!("000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69"),
1093
- }
1094
- ],
1095
- file_contracts: Vec::new(),
1096
- file_contract_revisions: Vec::new(),
1097
- storage_proofs: Vec::new(),
1098
- siafund_inputs: Vec::new(),
1099
- siafund_outputs: Vec::new(),
1100
- miner_fees: Vec::new(),
1101
- arbitrary_data: Vec::new(),
1102
- signatures: Vec::new(),
1103
- },
1104
- parent_id: hash_256!("200bd724a6ae87005cd7b3124ae5349addc2d5d8db2fe1cdfb54f80245fc2575"),
1105
- timelock: 0,
1106
- key_index: 0,
1107
- expected: "a4b1855c546db7ec902237f730717faae96187db8ce9fe139504323a639f731e"
1108
- },
1109
- TestCase{
1110
- transaction: serde_json::from_str("{\"siacoinInputs\":[{\"parentID\":\"750d22eff727689d1d8d1c83e513a30bb68ee7f9125a4dafc882459e34c2069d\",\"unlockConditions\":{\"timelock\":0,\"publicKeys\":[\"ed25519:800ed6c2760e3e4ba1ff00128585c8cf8fed2e3dc1e3da1eb92d49f405bd6360\"],\"signaturesRequired\":6312611591377486220}}],\"siacoinOutputs\":[{\"value\":\"890415399000000000000000000000000\",\"address\":\"480a064b5fca13002a7fe575845154bbf0b3af4cc4f147cbed387d43cce3568ae2497366eaa7\"}],\"fileContracts\":[{\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"windowStart\":10536451586783908586,\"windowEnd\":9324702155635244357,\"payout\":\"0\",\"validProofOutputs\":[{\"value\":\"1933513214000000000000000000000000\",\"address\":\"944524fff2c49c401e748db37cfda7569fa6df35b704fe716394f2ac3f40ce87b4506e9906f0\"}],\"missedProofOutputs\":[{\"value\":\"2469287901000000000000000000000000\",\"address\":\"1df67838262d7109ffcd9018f183b1eb33f05659a274b89ea6b52ff3617d34a770e9dd071d2e\"}],\"unlockHash\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\",\"revisionNumber\":9657412421282982780}],\"fileContractRevisions\":[{\"parentID\":\"e4e26d93771d3bbb3d9dd306105d77cfb3a6254d1cc3495903af6e013442c63c\",\"unlockConditions\":{\"timelock\":0,\"publicKeys\":[\"ed25519:e6b9cde4eb058f8ecbb083d99779cb0f6d518d5386f019af6ead09fa52de8567\"],\"signaturesRequired\":206644730660526450},\"revisionNumber\":10595710523108536025,\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"windowStart\":4348934140507359445,\"windowEnd\":14012366839994454386,\"validProofOutputs\":[{\"value\":\"2435858510000000000000000000000000\",\"address\":\"543bc0eda69f728d0a0fbce08e5bfc5ed7b961300e0af226949e135f7d12e32f0544e5262d6f\"}],\"missedProofOutputs\":[{\"value\":\"880343701000000000000000000000000\",\"address\":\"7b7f9aee981fe0d93bb3f49c6233cf847ebdd39d7dc5253f7fc330df2167073b35f035703237\"}],\"unlockHash\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"}],\"storageProofs\":[{\"parentID\":\"c0b9e98c9e03a2740c75d673871c1ee91f36d1bb329ff3ddbf1dfa8c6e1a64eb\",\"leaf\":\"b78fa521dc62d9ced82bc3b61e0aa5a5c221d6cca5db63d94c9879543fb98c0a971094a89cd4408487ae32902248d321b545f9a051729aa0bb1725b848e3d453\",\"proof\":[\"fe08c0a061475e7e5dec19e717cf98792fa7b555d0b5d3540a05db09f59ab8de\"]}],\"minerFees\":[\"241119475000000000000000000000000\"],\"arbitraryData\":[\"2shzIHEUJYwuNHz6c/gPz+aTEWZRTpDTmemX9yYAKlY=\"],\"signatures\":[{\"parentID\":\"06d1fca03c5ddd9b09116db1b97c5451f7dc792b05362969f83e3e8dc1007f46\",\"publicKeyIndex\":6088345341283457116,\"timelock\":2014247885072555224,\"coveredFields\":{\"wholeTransaction\":true},\"signature\":\"2XNEKGZrl9RhMa2JmGsvcmqQWAIX/uxtMwLnPI6VJPcXqub6qYIuoAThYp9NAwadk+1GG6CXC66g4rOjFYuNSA==\"}]}").expect("valid transaction"),
1111
- parent_id: hash_256!("59c36e89224f681c1a843c3f30e12c77823d17581d4061724ec6d61555c49095"),
1112
- timelock: 0,
1113
- key_index: 0,
1114
- expected: "f93b095e09f8c860ba8638737ba5f4c81a311af1a840c6b18635009e4d90574e",
1115
- },
1116
- TestCase{
1117
- transaction: serde_json::from_str("{\"siacoinInputs\":[{\"parentID\":\"750d22eff727689d1d8d1c83e513a30bb68ee7f9125a4dafc882459e34c2069d\",\"unlockConditions\":{\"timelock\":0,\"publicKeys\":[\"ed25519:800ed6c2760e3e4ba1ff00128585c8cf8fed2e3dc1e3da1eb92d49f405bd6360\"],\"signaturesRequired\":6312611591377486220}}],\"siacoinOutputs\":[{\"value\":\"890415399000000000000000000000000\",\"address\":\"480a064b5fca13002a7fe575845154bbf0b3af4cc4f147cbed387d43cce3568ae2497366eaa7\"}],\"fileContracts\":[{\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"windowStart\":10536451586783908586,\"windowEnd\":9324702155635244357,\"payout\":\"0\",\"validProofOutputs\":[{\"value\":\"1933513214000000000000000000000000\",\"address\":\"944524fff2c49c401e748db37cfda7569fa6df35b704fe716394f2ac3f40ce87b4506e9906f0\"}],\"missedProofOutputs\":[{\"value\":\"2469287901000000000000000000000000\",\"address\":\"1df67838262d7109ffcd9018f183b1eb33f05659a274b89ea6b52ff3617d34a770e9dd071d2e\"}],\"unlockHash\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\",\"revisionNumber\":9657412421282982780}],\"fileContractRevisions\":[{\"parentID\":\"e4e26d93771d3bbb3d9dd306105d77cfb3a6254d1cc3495903af6e013442c63c\",\"unlockConditions\":{\"timelock\":0,\"publicKeys\":[\"ed25519:e6b9cde4eb058f8ecbb083d99779cb0f6d518d5386f019af6ead09fa52de8567\"],\"signaturesRequired\":206644730660526450},\"revisionNumber\":10595710523108536025,\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"windowStart\":4348934140507359445,\"windowEnd\":14012366839994454386,\"validProofOutputs\":[{\"value\":\"2435858510000000000000000000000000\",\"address\":\"543bc0eda69f728d0a0fbce08e5bfc5ed7b961300e0af226949e135f7d12e32f0544e5262d6f\"}],\"missedProofOutputs\":[{\"value\":\"880343701000000000000000000000000\",\"address\":\"7b7f9aee981fe0d93bb3f49c6233cf847ebdd39d7dc5253f7fc330df2167073b35f035703237\"}],\"unlockHash\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"}],\"storageProofs\":[{\"parentID\":\"c0b9e98c9e03a2740c75d673871c1ee91f36d1bb329ff3ddbf1dfa8c6e1a64eb\",\"leaf\":\"b78fa521dc62d9ced82bc3b61e0aa5a5c221d6cca5db63d94c9879543fb98c0a971094a89cd4408487ae32902248d321b545f9a051729aa0bb1725b848e3d453\",\"proof\":[\"fe08c0a061475e7e5dec19e717cf98792fa7b555d0b5d3540a05db09f59ab8de\"]}],\"minerFees\":[\"241119475000000000000000000000000\"],\"arbitraryData\":[\"2shzIHEUJYwuNHz6c/gPz+aTEWZRTpDTmemX9yYAKlY=\"],\"signatures\":[{\"parentID\":\"06d1fca03c5ddd9b09116db1b97c5451f7dc792b05362969f83e3e8dc1007f46\",\"publicKeyIndex\":6088345341283457116,\"timelock\":2014247885072555224,\"coveredFields\":{\"wholeTransaction\":true},\"signature\":\"2XNEKGZrl9RhMa2JmGsvcmqQWAIX/uxtMwLnPI6VJPcXqub6qYIuoAThYp9NAwadk+1GG6CXC66g4rOjFYuNSA==\"}]}").expect("valid transaction"),
1118
- parent_id: hash_256!("59c36e89224f681c1a843c3f30e12c77823d17581d4061724ec6d61555c49095"),
1119
- timelock: 467251739279473577,
1120
- key_index: 1493934879227647507,
1121
- expected: "7aea4ec52e1f7de90261c4448a928081d4be6015252e482ec9c1cfa01663d768",
1122
- },
1123
- ];
1124
-
1125
- for (i, case) in test_cases.iter().enumerate() {
1126
- let sig_hash = case
1127
- .transaction
1128
- .whole_sig_hash(&cs, &case.parent_id, case.key_index, case.timelock)
1129
- .expect("encoded sig hash");
1130
- assert_eq!(sig_hash.to_string(), case.expected, "case {i}")
1131
- }
1132
- }
1133
-
1134
- #[test]
1135
- fn test_transaction_partial_sig_hash() {
1136
- let cs = ChainState {
1137
- state: State {
1138
- index: ChainIndex {
1139
- height: 1,
1140
- id: BlockID::default(),
1141
- },
1142
- prev_timestamps: [DateTime::UNIX_EPOCH; 11],
1143
- depth: BlockID::default(),
1144
- child_target: BlockID::default(),
1145
- siafund_pool: Currency::new(0),
1146
- oak_time: Duration::zero(),
1147
- oak_target: BlockID::default(),
1148
- foundation_primary_address: Address::new([0u8; 32]),
1149
- foundation_failsafe_address: Address::new([0u8; 32]),
1150
- total_work: Work::zero(),
1151
- difficulty: Work::zero(),
1152
- oak_work: Work::zero(),
1153
- attestations: 0,
1154
- elements: ElementAccumulator::default(),
1155
- },
1156
- network: Network {
1157
- name: "test".to_string(),
1158
- initial_coinbase: Currency::new(0),
1159
- minimum_coinbase: Currency::new(0),
1160
- initial_target: BlockID::default(),
1161
- block_interval: Duration::seconds(1),
1162
- maturity_delay: 0,
1163
- hardfork_dev_addr: HardforkDevAddr {
1164
- height: 0,
1165
- old_address: Address::new([0u8; 32]),
1166
- new_address: Address::new([0u8; 32]),
1167
- },
1168
- hardfork_tax: HardforkTax { height: 10 },
1169
- hardfork_storage_proof: HardforkStorageProof { height: 0 },
1170
- hardfork_asic: HardforkASIC {
1171
- height: 0,
1172
- oak_time: Duration::zero(),
1173
- oak_target: BlockID::default(),
1174
- },
1175
- hardfork_oak: HardforkOak {
1176
- height: 0,
1177
- fix_height: 0,
1178
- genesis_timestamp: DateTime::UNIX_EPOCH,
1179
- },
1180
- hardfork_foundation: HardforkFoundation {
1181
- height: 0,
1182
- primary_address: Address::new([0u8; 32]),
1183
- failsafe_address: Address::new([0u8; 32]),
1184
- },
1185
- hardfork_v2: HardforkV2 {
1186
- // test was made for pre-v2
1187
- allow_height: 100,
1188
- require_height: 100,
1189
- },
1190
- },
1191
- };
1192
- let txn: Transaction = serde_json::from_str("{\"siacoinInputs\":[{\"parentID\":\"750d22eff727689d1d8d1c83e513a30bb68ee7f9125a4dafc882459e34c2069d\",\"unlockConditions\":{\"timelock\":0,\"publicKeys\":[\"ed25519:800ed6c2760e3e4ba1ff00128585c8cf8fed2e3dc1e3da1eb92d49f405bd6360\"],\"signaturesRequired\":6312611591377486220}}],\"siacoinOutputs\":[{\"value\":\"890415399000000000000000000000000\",\"address\":\"480a064b5fca13002a7fe575845154bbf0b3af4cc4f147cbed387d43cce3568ae2497366eaa7\"}],\"fileContracts\":[{\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"windowStart\":10536451586783908586,\"windowEnd\":9324702155635244357,\"payout\":\"0\",\"validProofOutputs\":[{\"value\":\"1933513214000000000000000000000000\",\"address\":\"944524fff2c49c401e748db37cfda7569fa6df35b704fe716394f2ac3f40ce87b4506e9906f0\"}],\"missedProofOutputs\":[{\"value\":\"2469287901000000000000000000000000\",\"address\":\"1df67838262d7109ffcd9018f183b1eb33f05659a274b89ea6b52ff3617d34a770e9dd071d2e\"}],\"unlockHash\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\",\"revisionNumber\":9657412421282982780}],\"fileContractRevisions\":[{\"parentID\":\"e4e26d93771d3bbb3d9dd306105d77cfb3a6254d1cc3495903af6e013442c63c\",\"unlockConditions\":{\"timelock\":0,\"publicKeys\":[\"ed25519:e6b9cde4eb058f8ecbb083d99779cb0f6d518d5386f019af6ead09fa52de8567\"],\"signaturesRequired\":206644730660526450},\"revisionNumber\":10595710523108536025,\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"windowStart\":4348934140507359445,\"windowEnd\":14012366839994454386,\"validProofOutputs\":[{\"value\":\"2435858510000000000000000000000000\",\"address\":\"543bc0eda69f728d0a0fbce08e5bfc5ed7b961300e0af226949e135f7d12e32f0544e5262d6f\"}],\"missedProofOutputs\":[{\"value\":\"880343701000000000000000000000000\",\"address\":\"7b7f9aee981fe0d93bb3f49c6233cf847ebdd39d7dc5253f7fc330df2167073b35f035703237\"}],\"unlockHash\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"}],\"storageProofs\":[{\"parentID\":\"c0b9e98c9e03a2740c75d673871c1ee91f36d1bb329ff3ddbf1dfa8c6e1a64eb\",\"leaf\":\"b78fa521dc62d9ced82bc3b61e0aa5a5c221d6cca5db63d94c9879543fb98c0a971094a89cd4408487ae32902248d321b545f9a051729aa0bb1725b848e3d453\",\"proof\":[\"fe08c0a061475e7e5dec19e717cf98792fa7b555d0b5d3540a05db09f59ab8de\"]}],\"minerFees\":[\"241119475000000000000000000000000\"],\"arbitraryData\":[\"2shzIHEUJYwuNHz6c/gPz+aTEWZRTpDTmemX9yYAKlY=\"],\"signatures\":[{\"parentID\":\"06d1fca03c5ddd9b09116db1b97c5451f7dc792b05362969f83e3e8dc1007f46\",\"publicKeyIndex\":6088345341283457116,\"timelock\":2014247885072555224,\"coveredFields\":{\"wholeTransaction\":true},\"signature\":\"2XNEKGZrl9RhMa2JmGsvcmqQWAIX/uxtMwLnPI6VJPcXqub6qYIuoAThYp9NAwadk+1GG6CXC66g4rOjFYuNSA==\"}]}").expect("valid transaction");
1193
-
1194
- let test_cases = vec![
1195
- (
1196
- CoveredFields {
1197
- whole_transaction: false,
1198
- siacoin_inputs: vec![0],
1199
- siacoin_outputs: vec![0],
1200
- file_contracts: vec![0],
1201
- file_contract_revisions: vec![0],
1202
- storage_proofs: vec![0],
1203
- siafund_inputs: vec![],
1204
- siafund_outputs: vec![],
1205
- miner_fees: vec![0],
1206
- arbitrary_data: vec![0],
1207
- signatures: vec![0],
1208
- },
1209
- "5a9a69acb9211dc952b7458754e9fdf7f86fef419c03e8054f992d95c14ebf63",
1210
- ),
1211
- (
1212
- CoveredFields {
1213
- whole_transaction: false,
1214
- siacoin_inputs: vec![],
1215
- siacoin_outputs: vec![0],
1216
- file_contracts: vec![0],
1217
- file_contract_revisions: vec![0],
1218
- storage_proofs: vec![0],
1219
- siafund_inputs: vec![],
1220
- siafund_outputs: vec![],
1221
- miner_fees: vec![0],
1222
- arbitrary_data: vec![0],
1223
- signatures: vec![0],
1224
- },
1225
- "81c3e106089f1c86f3402c3bbc0d572d49eafe559961b18344102de4ee1abd94",
1226
- ),
1227
- (
1228
- CoveredFields {
1229
- whole_transaction: false,
1230
- siacoin_inputs: vec![0],
1231
- siacoin_outputs: vec![],
1232
- file_contracts: vec![0],
1233
- file_contract_revisions: vec![0],
1234
- storage_proofs: vec![0],
1235
- siafund_inputs: vec![],
1236
- siafund_outputs: vec![],
1237
- miner_fees: vec![0],
1238
- arbitrary_data: vec![0],
1239
- signatures: vec![0],
1240
- },
1241
- "78d8dca99a5a775e5223867af702bf6304326784c4e7f3fd431043504a7f7a98",
1242
- ),
1243
- (
1244
- CoveredFields {
1245
- whole_transaction: false,
1246
- siacoin_inputs: vec![0],
1247
- siacoin_outputs: vec![0],
1248
- file_contracts: vec![0],
1249
- file_contract_revisions: vec![0],
1250
- storage_proofs: vec![0],
1251
- siafund_inputs: vec![],
1252
- siafund_outputs: vec![],
1253
- miner_fees: vec![0],
1254
- arbitrary_data: vec![],
1255
- signatures: vec![0],
1256
- },
1257
- "79efc21fbdbf9536fe90b49b4858d5e2945a6bcb28f82b49b189d793f22f150b",
1258
- ),
1259
- (
1260
- CoveredFields {
1261
- whole_transaction: false,
1262
- siacoin_inputs: vec![],
1263
- siacoin_outputs: vec![],
1264
- file_contracts: vec![],
1265
- file_contract_revisions: vec![0],
1266
- storage_proofs: vec![],
1267
- siafund_inputs: vec![],
1268
- siafund_outputs: vec![],
1269
- miner_fees: vec![],
1270
- arbitrary_data: vec![],
1271
- signatures: vec![],
1272
- },
1273
- "22d26fe3e660d58a26a7da864357c1930c3c24393dd5712d851e0c1c0a0706c2",
1274
- ),
1275
- ];
1276
-
1277
- for (i, (cf, expected)) in test_cases.iter().enumerate() {
1278
- let sig_hash = txn.partial_sig_hash(&cs, cf).expect("valid sig hash");
1279
- assert_eq!(sig_hash.to_string(), *expected, "case {i}")
1280
- }
1281
- }
1282
-
1283
- #[test]
1284
- fn test_standard_unlockhash() {
1285
- let test_cases = vec![
1286
- (
1287
- "80f637df83a93a6916d1b5c8bdbb061f967fb9fe8fe51ef4d97eeec73c6bfc394771e4a04f42",
1288
- hex::decode("ad08d551ab7116b8c2285de81ffa528ef3679f9e242c3f551b560a60ab9763db")
1289
- .unwrap(),
1290
- ),
1291
- (
1292
- "99a27a168bdde2e9c59bc967f6c662e3db0b2cf13da26ddae26004fa19c61d3db017dca7d0d3",
1293
- hex::decode("18ac9c05b0c5e7c62859812b943572429cda178aa3df92697569b8984c603b4c")
1294
- .unwrap(),
1295
- ),
1296
- (
1297
- "128151658b256d0185f3f91504758349a96e73c1a68a39c7ff7bf9d0e416997c964d773858ce",
1298
- hex::decode("2b36cc860796f2e8a1990b437f46a4b905840e6ba41ba5f68fe2b8ebe23626af")
1299
- .unwrap(),
1300
- ),
1301
- (
1302
- "1f47d453cfd7369bce4034d3ab461feb2a4d073bf59c959225993d00e38d71a8fea7c57cd3f1",
1303
- hex::decode("a3e3c2f3493a079d3dfe69681bf878c59337e3d1c79d17a34e3da81f062bbe21")
1304
- .unwrap(),
1305
- ),
1306
- (
1307
- "e03c56f8d95894cea875711e2f909c68c07dd37142a8253813ad09abceb2b6e5dd89992c9638",
1308
- hex::decode("a03d3b27db7e143cb8b39a1eb9234bffad59d6f50adf4f0ee916afd510a939a0")
1309
- .unwrap(),
1310
- ),
1311
- (
1312
- "68b6dd2e50f12e2deef2efd6b7baa660d87950ea16c5a8402a6db5873e062bcdd5246940b44e",
1313
- hex::decode("52e4438ca9b6eb2d33953f97255e410130d55749432094fe9963f4fc65167ce5")
1314
- .unwrap(),
1315
- ),
1316
- (
1317
- "c766e0a5ef49b7bab6c2e9c6a0b699e87eb3580e08f3fe77648dd93b66795a8606787cc5e29e",
1318
- hex::decode("4110f8b0ade1cca7aa40008a9b9911655393288eaacc3948fecd13edd3f092ec")
1319
- .unwrap(),
1320
- ),
1321
- (
1322
- "b455cf3c22de0d84ab8599499b0c2056d4916ab4c642b6b716148487f83ca5a85ad199b7a454",
1323
- hex::decode("861d50c4ee90b0a6a5544a3820978dad1fd9391c4813ede9e4963f0d6bec010a")
1324
- .unwrap(),
1325
- ),
1326
- (
1327
- "5274e9f3db1acfe8bb2d67dbbb5b6f2cc20769a0b42c8a9187ae827bf637f06e62ecada30f9f",
1328
- hex::decode("a5329c135951f3505d9a26d2833cb6c1aebb875fbada80f38b09bd3314f26802")
1329
- .unwrap(),
1330
- ),
1331
- (
1332
- "1540f42840b0479b238ec0143984a784c58240a8ca5e21da4b66be89a2f54353c99739938947",
1333
- hex::decode("e11589e1857b7a0d2fc3526fbdfdc4d4708dfbf251184be1118138df4ef2d47e")
1334
- .unwrap(),
1335
- ),
1336
- (
1337
- "21592f041e6f6861f199d54a26fe6bdfc5d629bb5dda12058d3ce28549c4aeffdbbdb67c2b95",
1338
- hex::decode("d57887af5b838ea2d20a582f659b3e36ca47d33b253364e3b774a1f4feb8415b")
1339
- .unwrap(),
1340
- ),
1341
- (
1342
- "f34b1e0b74a695f8bc82a97bab3b9d1ebe420956cbb3f7611c349c9659ba13fa362a417b1fd2",
1343
- hex::decode("5da4058d2f95e3c547aab8b5c70817ed3795856aa7988676f266cb429d75ce06")
1344
- .unwrap(),
1345
- ),
1346
- (
1347
- "3549a1680fcc093347e2674f4e89c84200965e1b779e2b3c05e4b21645a0b2fd5ac86923ef7a",
1348
- hex::decode("98ced26430f3be35b29ca76d3f65ea616f89e2510a3c1307856522e23057d958")
1349
- .unwrap(),
1350
- ),
1351
- (
1352
- "86fc291f7f53def33f2f7566f5ff08763bf5ada158f97c87fc240d1dcb04aa2a7b289018e33e",
1353
- hex::decode("e715d5dc3bd8edecb453c59f85998591d7c14fd08057a0605cb416f6751eaad9")
1354
- .unwrap(),
1355
- ),
1356
- (
1357
- "46e60abc3acbff858e382783f0739a8b2f2ba4c51b26941d979e60cb5292f11df1112b7016c0",
1358
- hex::decode("359eee8d1ef18ed647bbd63cb4b2be85061f8e3fd67318e13924ddbc1beb815f")
1359
- .unwrap(),
1360
- ),
1361
- (
1362
- "015b4b0759b0adee6c01de051bdacefe1f30eb571c83fa6c37607008696a9fa7f85273061e72",
1363
- hex::decode("cf5cd07f31ca3aa3b7d2947da7e92c42ec5f981eff80ff1b438e59fd456465fb")
1364
- .unwrap(),
1365
- ),
1366
- (
1367
- "7435604655772ca5ff011127c83692e40945187954da3bc7c01102d59701c7351aadbdc9ac8b",
1368
- hex::decode("7f6a73aeb6de28f1d3935941caa8cab286d13d8c74f2352b5b717c3d743db9c1")
1369
- .unwrap(),
1370
- ),
1371
- (
1372
- "c554d56a2eaffd8426006fb6d987cc615fb4ec05b1b15e793ab9d9127d79cf323787817467e6",
1373
- hex::decode("14b98855c4f22295fcf3e2ec5d5fdfbb877979639c963bf6e226a0fb71902baf")
1374
- .unwrap(),
1375
- ),
1376
- (
1377
- "c4850dbcddb9dfac6f44007ec58fe824bc58e3de2432de478f3e53f7965c2afd7ea651b6c2bf",
1378
- hex::decode("6f5c23f8797f93d3d3c689fe1a3f5d9a1fbf326a7a6ea51fecbeaa9aba46f180")
1379
- .unwrap(),
1380
- ),
1381
- (
1382
- "6a8f4f1d5a7405aa24cb1fb2a3c1dcaae74175c712002627289b5cd9dd887088afe605460abd",
1383
- hex::decode("45f12760f6005a93cece248f5ec78adf15f9d29dafe397c8c28fefc72781d6fb")
1384
- .unwrap(),
1385
- ),
1386
- (
1387
- "e464b9b1c9282d8edeed5832b95405761db6dacf6a156fc9119a396bdc8f8892815c7dce20fd",
1388
- hex::decode("1c12d17a2a8b2c25950872f312d5d0758f07d8357c98897fc472565a44b3d1f1")
1389
- .unwrap(),
1390
- ),
1391
- (
1392
- "9ae839af434aa13de6e8baa280541716811dcbaa33165fea5e9bad0c33998c10f16fcac4f214",
1393
- hex::decode("686d28bf7e4b4cadf759994caed1e52092e12c11cef257a265b50402dbd70c3b")
1394
- .unwrap(),
1395
- ),
1396
- (
1397
- "e92722d80103af9574f19a6cf72aab424335927eb7da022455f53314e3587dc8ece40d254981",
1398
- hex::decode("b2e9ddef40897219a997ae7af277a5550cc10c54e793b6d2146de94df3bd552b")
1399
- .unwrap(),
1400
- ),
1401
- (
1402
- "e2a02510f242f35e46b8840d8da42c087ea906b09d8e454c734663650236977da0362dd2ab43",
1403
- hex::decode("4f756e475a706cdcec8eb1c02b21a591e0c0450cc0408ae8aec82ae97f634ecf")
1404
- .unwrap(),
1405
- ),
1406
- (
1407
- "8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8cdf32abee86f0",
1408
- hex::decode("cd46b523d2ee92f205a00726d8544094bb4fe58142ecffd20ea32b37b6e6bfc3")
1409
- .unwrap(),
1410
- ),
1411
- ];
1412
-
1413
- for (expected_str, public_key) in test_cases {
1414
- let expected = expected_str.parse().unwrap();
1415
-
1416
- let public_key = PublicKey::new(public_key.as_slice().try_into().unwrap());
1417
- let addr = UnlockConditions::standard_unlock_conditions(public_key).address();
1418
-
1419
- assert_eq!(addr, expected);
1420
- // test string round-trip
1421
- if !expected_str.starts_with("") {
1422
- assert_eq!(addr.to_string(), "".to_string() + expected_str)
1423
- } else {
1424
- assert_eq!(addr.to_string(), expected_str)
1425
- }
1426
- }
1427
- }
1428
-
1429
- #[test]
1430
- fn test_seed_standard_unlock_hash() {
1431
- const PHRASE: &str =
1432
- "song renew capable taxi follow sword more hybrid laptop dance unfair poem";
1433
- let test_addresses = vec![
1434
- (
1435
- 0,
1436
- address!(
1437
- "16e09f8dc8a100a03ba1f9503e4035661738d1bea0b6cdc9bb012d3cd25edaacfd780909e550"
1438
- ),
1439
- ),
1440
- (
1441
- 1,
1442
- address!(
1443
- "cb016a7018485325fa299bc247113e3792dbea27ee08d2bb57a16cb0804fa449d3a91ee647a1"
1444
- ),
1445
- ),
1446
- (
1447
- 2,
1448
- address!(
1449
- "5eb70f141387df1e2ecd434b22be50bff57a6e08484f3890fe4415a6d323b5e9e758b4f79b34"
1450
- ),
1451
- ),
1452
- (
1453
- 3,
1454
- address!(
1455
- "c3bc7bc1431460ed2556874cb63714760120125da758ebbd78198534cb3d25774352fdbb3e8b"
1456
- ),
1457
- ),
1458
- (
1459
- 4,
1460
- address!(
1461
- "ebc7eae02ecf76e3ba7312bab6b6f71e9d255801a3a3b83f7cc26bd520b2c27a511cd8604e4b"
1462
- ),
1463
- ),
1464
- (
1465
- 5,
1466
- address!(
1467
- "fce241a44b944b10f414782dd35f5d96b92aec3d6da92a45ae44b7dc8cfb4b4ba97a34ce7032"
1468
- ),
1469
- ),
1470
- (
1471
- 6,
1472
- address!(
1473
- "36d253e7c3af2213eccaf0a61c6d24be8668f72af6e773463f3c41efc8bb70f2b353b90de9dd"
1474
- ),
1475
- ),
1476
- (
1477
- 7,
1478
- address!(
1479
- "c8f85375fb264428c86594863440f856db1da4614d75f4a30e3d9db3dfc88af6995128c6a845"
1480
- ),
1481
- ),
1482
- (
1483
- 8,
1484
- address!(
1485
- "85ef2ba14ee464060570b16bddaac91353961e7545067ccdf868a0ece305f00d2c08ec6844c6"
1486
- ),
1487
- ),
1488
- (
1489
- 9,
1490
- address!(
1491
- "9dcf644245eba91e7ea70c47ccadf479e6834c1c1221335e7246e0a6bc40e18362c4faa760b8"
1492
- ),
1493
- ),
1494
- (
1495
- 4294967295,
1496
- address!(
1497
- "a906891f0c524fd272a905aa5dd7018c69e5d68222385cbd9d5292f38f021ce4bf00953a0659"
1498
- ),
1499
- ),
1500
- (
1501
- 4294967296,
1502
- address!(
1503
- "b6ab338e624a304add7afe205361ac71821b87559a3b9c5b3735eaafa914eed533613a0af7fa"
1504
- ),
1505
- ),
1506
- (
1507
- 18446744073709551615,
1508
- address!(
1509
- "832d0e8b5f967677d812d75559c373d930ad16eb90c31c29982a190bb7db9edf9438fd827938"
1510
- ),
1511
- ),
1512
- ];
1513
-
1514
- let seed = Seed::new(PHRASE).unwrap();
1515
- for (i, expected) in test_addresses {
1516
- let pk = seed.private_key(i).public_key();
1517
- let addr: Address = UnlockConditions::standard_unlock_conditions(pk).address();
1518
-
1519
- assert_eq!(addr, expected, "index {i}");
1520
- }
1521
- }
1522
-
1523
- #[test]
1524
- fn test_file_contract_tax() {
1525
- struct TestCase {
1526
- payout: Currency,
1527
- prefork: Currency,
1528
- postfork: Currency,
1529
- }
1530
- let test_cases = vec![
1531
- TestCase {
1532
- payout: Currency::new(0),
1533
- prefork: Currency::new(0),
1534
- postfork: Currency::new(0),
1535
- },
1536
- TestCase {
1537
- payout: Currency::new(1),
1538
- prefork: Currency::new(0),
1539
- postfork: Currency::new(0),
1540
- },
1541
- TestCase {
1542
- payout: Currency::new(2),
1543
- prefork: Currency::new(0),
1544
- postfork: Currency::new(0),
1545
- },
1546
- TestCase {
1547
- payout: Currency::new(340282366920938463463374607431768211455),
1548
- prefork: Currency::new(13271012309916600075071609689838960000),
1549
- postfork: Currency::new(13271012309916600075071609689838960000),
1550
- },
1551
- TestCase {
1552
- payout: Currency::new(595540520000000000000000000000000),
1553
- prefork: Currency::new(23226080280000000000000000000000),
1554
- postfork: Currency::new(23226080280000000000000000000000),
1555
- },
1556
- TestCase {
1557
- payout: Currency::new(103983762872653413852682180916164570605),
1558
- prefork: Currency::new(4055366752033483140254605055730410000),
1559
- postfork: Currency::new(4055366752033483140254605055730410000),
1560
- },
1561
- TestCase {
1562
- payout: Currency::new(3827764528000000000000000000000000),
1563
- prefork: Currency::new(149282816592000000000000000000000),
1564
- postfork: Currency::new(149282816592000000000000000000000),
1565
- },
1566
- TestCase {
1567
- payout: Currency::new(216196544861605368913933682930139323360),
1568
- prefork: Currency::new(8431665249602609387643413634275430000),
1569
- postfork: Currency::new(8431665249602609387643413634275430000),
1570
- },
1571
- TestCase {
1572
- payout: Currency::new(2630651610000000000000000000000000),
1573
- prefork: Currency::new(102595412790000000000000000000000),
1574
- postfork: Currency::new(102595412790000000000000000000000),
1575
- },
1576
- TestCase {
1577
- payout: Currency::new(242035606817835258338180817515298863866),
1578
- prefork: Currency::new(9439388665895575075189051883096650000),
1579
- postfork: Currency::new(9439388665895575075189051883096650000),
1580
- },
1581
- TestCase {
1582
- payout: Currency::new(3830155529000000000000000000000000),
1583
- prefork: Currency::new(149376065631000000000000000000000),
1584
- postfork: Currency::new(149376065631000000000000000000000),
1585
- },
1586
- TestCase {
1587
- payout: Currency::new(126852058180828682198189558142776852406),
1588
- prefork: Currency::new(4947230269052318605729392767568290000),
1589
- postfork: Currency::new(4947230269052318605729392767568290000),
1590
- },
1591
- TestCase {
1592
- payout: Currency::new(3497644816000000000000000000000000),
1593
- prefork: Currency::new(136408147824000000000000000000000),
1594
- postfork: Currency::new(136408147824000000000000000000000),
1595
- },
1596
- TestCase {
1597
- payout: Currency::new(202288428857506739014982837533616200189),
1598
- prefork: Currency::new(7889248725442762821584330663811030000),
1599
- postfork: Currency::new(7889248725442762821584330663811030000),
1600
- },
1601
- TestCase {
1602
- payout: Currency::new(3717108920000000000000000000000000),
1603
- prefork: Currency::new(144967247880000000000000000000000),
1604
- postfork: Currency::new(144967247880000000000000000000000),
1605
- },
1606
- TestCase {
1607
- payout: Currency::new(319915558118289110319073160920214552278),
1608
- prefork: Currency::new(12476706766613275302443853275888360000),
1609
- postfork: Currency::new(12476706766613275302443853275888360000),
1610
- },
1611
- TestCase {
1612
- payout: Currency::new(2205536583000000000000000000000000),
1613
- prefork: Currency::new(86015926737000000000000000000000),
1614
- postfork: Currency::new(86015926737000000000000000000000),
1615
- },
1616
- TestCase {
1617
- payout: Currency::new(138040906509763116024244911687441931808),
1618
- prefork: Currency::new(5383595353880761524945551555810230000),
1619
- postfork: Currency::new(5383595353880761524945551555810230000),
1620
- },
1621
- TestCase {
1622
- payout: Currency::new(1110927021000000000000000000000000),
1623
- prefork: Currency::new(43326153819000000000000000000000),
1624
- postfork: Currency::new(43326153819000000000000000000000),
1625
- },
1626
- TestCase {
1627
- payout: Currency::new(215175656237682186102553629801543673418),
1628
- prefork: Currency::new(8391850593269605257999591562260200000),
1629
- postfork: Currency::new(8391850593269605257999591562260200000),
1630
- },
1631
- TestCase {
1632
- payout: Currency::new(646634091000000000000000000000000),
1633
- prefork: Currency::new(25218729549000000000000000000000),
1634
- postfork: Currency::new(25218729549000000000000000000000),
1635
- },
1636
- TestCase {
1637
- payout: Currency::new(128469923315667767051668090462322677166),
1638
- prefork: Currency::new(5010327009311042915015055528030580000),
1639
- postfork: Currency::new(5010327009311042915015055528030580000),
1640
- },
1641
- TestCase {
1642
- payout: Currency::new(2889549915000000000000000000000000),
1643
- prefork: Currency::new(112692446685000000000000000000000),
1644
- postfork: Currency::new(112692446685000000000000000000000),
1645
- },
1646
- TestCase {
1647
- payout: Currency::new(269364173205837265395254441592734706401),
1648
- prefork: Currency::new(10505202755027653350414923222116650000),
1649
- postfork: Currency::new(10505202755027653350414923222116650000),
1650
- },
1651
- ];
1652
-
1653
- let mut cs = ChainState {
1654
- state: State {
1655
- index: ChainIndex {
1656
- height: 1,
1657
- id: BlockID::default(),
1658
- },
1659
- prev_timestamps: [DateTime::UNIX_EPOCH; 11],
1660
- depth: BlockID::default(),
1661
- child_target: BlockID::default(),
1662
- siafund_pool: Currency::new(0),
1663
- oak_time: Duration::zero(),
1664
- oak_target: BlockID::default(),
1665
- foundation_primary_address: Address::new([0u8; 32]),
1666
- foundation_failsafe_address: Address::new([0u8; 32]),
1667
- total_work: Work::zero(),
1668
- difficulty: Work::zero(),
1669
- oak_work: Work::zero(),
1670
- attestations: 0,
1671
- elements: ElementAccumulator::default(),
1672
- },
1673
- network: Network {
1674
- name: "test".to_string(),
1675
- initial_coinbase: Currency::new(0),
1676
- minimum_coinbase: Currency::new(0),
1677
- initial_target: BlockID::default(),
1678
- block_interval: Duration::seconds(1),
1679
- maturity_delay: 0,
1680
- hardfork_dev_addr: HardforkDevAddr {
1681
- height: 0,
1682
- old_address: Address::new([0u8; 32]),
1683
- new_address: Address::new([0u8; 32]),
1684
- },
1685
- hardfork_tax: HardforkTax { height: 10 },
1686
- hardfork_storage_proof: HardforkStorageProof { height: 0 },
1687
- hardfork_asic: HardforkASIC {
1688
- height: 0,
1689
- oak_time: Duration::zero(),
1690
- oak_target: BlockID::default(),
1691
- },
1692
- hardfork_oak: HardforkOak {
1693
- height: 0,
1694
- fix_height: 0,
1695
- genesis_timestamp: DateTime::UNIX_EPOCH,
1696
- },
1697
- hardfork_foundation: HardforkFoundation {
1698
- height: 0,
1699
- primary_address: Address::new([0u8; 32]),
1700
- failsafe_address: Address::new([0u8; 32]),
1701
- },
1702
- hardfork_v2: HardforkV2 {
1703
- allow_height: 0,
1704
- require_height: 0,
1705
- },
1706
- },
1707
- };
1708
-
1709
- for tc in test_cases.iter() {
1710
- let fc = FileContract {
1711
- payout: tc.payout,
1712
- file_size: 0,
1713
- file_merkle_root: Hash256::default(),
1714
- window_start: 0,
1715
- window_end: 0,
1716
- unlock_hash: Address::new([0u8; 32]),
1717
- revision_number: 0,
1718
- valid_proof_outputs: vec![],
1719
- missed_proof_outputs: vec![],
1720
- };
1721
-
1722
- let tax = fc.tax(&cs);
1723
- assert_eq!(
1724
- tax, tc.prefork,
1725
- "prefork tax incorrect for payout {:?}",
1726
- tc.payout
1727
- );
1728
- cs.state.index.height = 11;
1729
- let tax = fc.tax(&cs);
1730
- assert_eq!(
1731
- tax, tc.postfork,
1732
- "postfork tax incorrect for payout {:?}",
1733
- tc.payout
1734
- );
1735
- }
1736
- }
1737
- }