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,1726 +0,0 @@
1
- use std::io;
2
-
3
- use crate::consensus::ChainState;
4
- use crate::encoding::{self, SiaDecodable, SiaDecode, SiaEncodable, SiaEncode};
5
- use crate::encoding_async::{
6
- AsyncDecoder, AsyncEncoder, AsyncSiaDecodable, AsyncSiaDecode, AsyncSiaEncodable,
7
- AsyncSiaEncode,
8
- };
9
- use blake2b_simd::Params;
10
- use serde::de::{Error, MapAccess, Visitor};
11
- use serde::ser::SerializeStruct;
12
- use serde::{Deserialize, Serialize};
13
- use serde_json::json;
14
- use thiserror::Error;
15
-
16
- use crate::signing::{PublicKey, Signature};
17
- use crate::types::common::BlockID;
18
-
19
- use super::{
20
- Address, AttestationID, ChainIndex, Currency, FileContractID, Hash256, Leaf, SiacoinOutput,
21
- SiacoinOutputID, SiafundOutput, SiafundOutputID, StateElement, TransactionID,
22
- };
23
-
24
- // expose spend policies
25
- pub use super::spendpolicy::*;
26
-
27
- #[derive(Debug, PartialEq, Eq, Clone, Copy)]
28
- pub enum Protocol {
29
- SiaMux,
30
- QUIC,
31
- }
32
-
33
- #[derive(Debug, Error)]
34
- pub enum ProtocolParseError {
35
- #[error("invalid protocol {0}")]
36
- InvalidProtocol(String),
37
- }
38
-
39
- impl Protocol {
40
- pub const fn as_str(&self) -> &'static str {
41
- match self {
42
- Protocol::SiaMux => "siamux",
43
- Protocol::QUIC => "quic",
44
- }
45
- }
46
- }
47
-
48
- impl TryFrom<String> for Protocol {
49
- type Error = ProtocolParseError;
50
-
51
- fn try_from(value: String) -> Result<Self, Self::Error> {
52
- match value.as_str() {
53
- "siamux" => Ok(Protocol::SiaMux),
54
- "quic" => Ok(Protocol::QUIC),
55
- _ => Err(ProtocolParseError::InvalidProtocol(value)),
56
- }
57
- }
58
- }
59
-
60
- impl Serialize for Protocol {
61
- fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
62
- where
63
- S: serde::Serializer,
64
- {
65
- serializer.serialize_str(self.as_str())
66
- }
67
- }
68
-
69
- impl<'de> Deserialize<'de> for Protocol {
70
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
71
- where
72
- D: serde::Deserializer<'de>,
73
- {
74
- let s = String::deserialize(deserializer)?;
75
- Protocol::try_from(s).map_err(|e| D::Error::custom(format!("{e:?}")))
76
- }
77
- }
78
-
79
- impl SiaEncodable for Protocol {
80
- fn encode<W: io::Write>(&self, w: &mut W) -> encoding::Result<()> {
81
- self.as_str().as_bytes().encode(w)
82
- }
83
- }
84
-
85
- impl SiaDecodable for Protocol {
86
- fn decode<R: io::Read>(r: &mut R) -> encoding::Result<Self> {
87
- let s = String::decode(r)?;
88
- let v = Protocol::try_from(s).map_err(|e| encoding::Error::InvalidValue(e.to_string()))?;
89
- Ok(v)
90
- }
91
- }
92
-
93
- impl AsyncSiaEncodable for Protocol {
94
- async fn encode_async<E: AsyncEncoder>(&self, e: &mut E) -> Result<(), E::Error> {
95
- self.as_str().as_bytes().encode_async(e).await
96
- }
97
- }
98
-
99
- impl AsyncSiaDecodable for Protocol {
100
- async fn decode_async<D: AsyncDecoder>(d: &mut D) -> Result<Self, D::Error> {
101
- let s = String::decode_async(d).await?;
102
- let v = Protocol::try_from(s).map_err(|e| encoding::Error::InvalidValue(e.to_string()))?;
103
- Ok(v)
104
- }
105
- }
106
-
107
- #[derive(
108
- Debug,
109
- PartialEq,
110
- Clone,
111
- SiaEncode,
112
- SiaDecode,
113
- AsyncSiaEncode,
114
- AsyncSiaDecode,
115
- Serialize,
116
- Deserialize,
117
- )]
118
- #[serde(rename_all = "camelCase")]
119
- pub struct NetAddress {
120
- pub protocol: Protocol,
121
- pub address: String,
122
- }
123
-
124
- /// An Attestation associates a key-value pair with an identity. For example,
125
- /// hosts attest to their network address by setting Key to "HostAnnouncement"
126
- /// and Value to their address, thereby allowing renters to discover them.
127
- /// Generally, an attestation for a particular key is considered to overwrite any
128
- /// previous attestations with the same key. (This allows hosts to announce a new
129
- /// network address, for example.)
130
- #[derive(
131
- Debug, PartialEq, Serialize, Deserialize, SiaEncode, SiaDecode, AsyncSiaEncode, AsyncSiaDecode,
132
- )]
133
- #[serde(rename_all = "camelCase")]
134
- pub struct Attestation {
135
- pub public_key: PublicKey,
136
- pub key: String,
137
- #[serde(with = "crate::types::utils::base64")]
138
- pub value: Vec<u8>,
139
-
140
- pub signature: Signature,
141
- }
142
-
143
- impl Attestation {
144
- fn encode_semantics<W: std::io::Write>(&self, w: &mut W) -> encoding::Result<()> {
145
- self.public_key.encode(w)?;
146
- self.key.encode(w)?;
147
- self.value.encode(w)?;
148
- [0u8; 64].encode(w) // empty sig
149
- }
150
-
151
- pub fn sig_hash(&self, cs: &ChainState) -> Hash256 {
152
- let mut state = Params::new().hash_length(32).to_state();
153
- state.update("sia/sig/attestation|".as_bytes());
154
- state.update(cs.replay_prefix());
155
- self.encode_semantics(&mut state).unwrap();
156
- state.finalize().into()
157
- }
158
- }
159
-
160
- /// A FileContract is a storage agreement between a renter and a host. It
161
- /// consists of a bidirectional payment channel that resolves as either "valid"
162
- /// or "missed" depending on whether a valid StorageProof is submitted for the
163
- /// contract.
164
- #[derive(
165
- Debug,
166
- PartialEq,
167
- Serialize,
168
- Deserialize,
169
- SiaEncode,
170
- SiaDecode,
171
- AsyncSiaEncode,
172
- AsyncSiaDecode,
173
- Clone,
174
- )]
175
- #[serde(rename_all = "camelCase")]
176
- pub struct FileContract {
177
- pub capacity: u64,
178
- pub filesize: u64,
179
- pub file_merkle_root: Hash256,
180
- pub proof_height: u64,
181
- pub expiration_height: u64,
182
- pub renter_output: SiacoinOutput,
183
- pub host_output: SiacoinOutput,
184
- pub missed_host_value: Currency,
185
- pub total_collateral: Currency,
186
- pub renter_public_key: PublicKey,
187
- pub host_public_key: PublicKey,
188
- pub revision_number: u64,
189
-
190
- pub renter_signature: Signature,
191
- pub host_signature: Signature,
192
- }
193
-
194
- impl FileContract {
195
- pub fn tax(&self, cs: &ChainState) -> Currency {
196
- let tax = (self.renter_output.value + self.host_output.value) / Currency::new(25); // 4%
197
- tax - (tax % Currency::new(cs.siafund_count() as u128))
198
- }
199
-
200
- fn encode_semantics<W: std::io::Write>(&self, w: &mut W) -> encoding::Result<()> {
201
- self.capacity.encode(w)?;
202
- self.filesize.encode(w)?;
203
- self.file_merkle_root.encode(w)?;
204
- self.proof_height.encode(w)?;
205
- self.expiration_height.encode(w)?;
206
- self.renter_output.encode(w)?;
207
- self.host_output.encode(w)?;
208
- self.missed_host_value.encode(w)?;
209
- self.total_collateral.encode(w)?;
210
- self.renter_public_key.encode(w)?;
211
- self.host_public_key.encode(w)?;
212
- self.revision_number.encode(w)?;
213
- [0u8; 64].encode(w)?; // nil renter signature
214
- [0u8; 64].encode(w)?; // nil host signature
215
- Ok(())
216
- }
217
-
218
- pub fn sig_hash(&self, cs: &ChainState) -> Hash256 {
219
- let mut state = Params::new().hash_length(32).to_state();
220
- state.update("sia/sig/filecontract|".as_bytes());
221
- state.update(cs.replay_prefix());
222
- self.encode_semantics(&mut state).unwrap();
223
- state.finalize().into()
224
- }
225
- }
226
-
227
- /// A SiacoinElement is a record of a Siacoin UTXO within the state accumulator.
228
- #[derive(
229
- Debug,
230
- PartialEq,
231
- Serialize,
232
- Deserialize,
233
- SiaEncode,
234
- SiaDecode,
235
- AsyncSiaDecode,
236
- AsyncSiaEncode,
237
- Clone,
238
- )]
239
- #[serde(rename_all = "camelCase")]
240
- pub struct SiacoinElement {
241
- pub state_element: StateElement,
242
- pub id: SiacoinOutputID,
243
- pub siacoin_output: SiacoinOutput,
244
- pub maturity_height: u64,
245
- }
246
-
247
- /// A SiafundElement is a record of a Siafund UTXO within the state accumulator.
248
- #[derive(
249
- Debug, PartialEq, Serialize, Deserialize, SiaEncode, SiaDecode, AsyncSiaDecode, AsyncSiaEncode,
250
- )]
251
- #[serde(rename_all = "camelCase")]
252
- pub struct SiafundElement {
253
- pub state_element: StateElement,
254
- pub id: SiafundOutputID,
255
- pub siafund_output: SiafundOutput,
256
- pub claim_start: Currency,
257
- }
258
-
259
- /// A V2FileContractElement is a record of a FileContract within the state
260
- /// accumulator.
261
- #[derive(
262
- Debug, PartialEq, Serialize, Deserialize, SiaEncode, SiaDecode, AsyncSiaDecode, AsyncSiaEncode,
263
- )]
264
- #[serde(rename_all = "camelCase")]
265
- pub struct FileContractElement {
266
- pub state_element: StateElement,
267
- pub id: FileContractID,
268
- pub v2_file_contract: FileContract,
269
- }
270
-
271
- /// A ChainIndexElement is a record of a ChainIndex within the state accumulator.
272
- #[derive(
273
- Debug, PartialEq, Serialize, Deserialize, SiaEncode, SiaDecode, AsyncSiaDecode, AsyncSiaEncode,
274
- )]
275
- #[serde(rename_all = "camelCase")]
276
- pub struct ChainIndexElement {
277
- pub state_element: StateElement,
278
- pub id: BlockID,
279
- pub chain_index: ChainIndex,
280
- }
281
-
282
- impl ChainIndexElement {
283
- pub fn encode_semantics<W: std::io::Write>(&self, w: &mut W) -> encoding::Result<()> {
284
- self.state_element.leaf_index.encode(w)?;
285
- Vec::<Hash256>::new().encode(w)?; // empty merkle proof
286
- self.id.encode(w)?;
287
- self.chain_index.encode(w)?;
288
- Ok(())
289
- }
290
- }
291
-
292
- /// An AttestationElement is a record of an Attestation within the state
293
- /// accumulator.
294
- pub struct AttestationElement {
295
- pub state_element: StateElement,
296
- pub id: AttestationID,
297
- pub attestation: Attestation,
298
- }
299
-
300
- /// A V2SiacoinInput represents a Siacoin UTXO that is being spent in a v2
301
- /// transaction.
302
- #[derive(
303
- Debug, PartialEq, Serialize, Deserialize, SiaEncode, SiaDecode, AsyncSiaEncode, AsyncSiaDecode,
304
- )]
305
- #[serde(rename_all = "camelCase")]
306
- pub struct SiacoinInput {
307
- pub parent: SiacoinElement,
308
- pub satisfied_policy: SatisfiedPolicy,
309
- }
310
-
311
- /// A V2SiafundInput represents a Siafund UTXO that is being spent in a v2
312
- /// transaction.
313
- #[derive(
314
- Debug, PartialEq, Serialize, Deserialize, AsyncSiaDecode, AsyncSiaEncode, SiaEncode, SiaDecode,
315
- )]
316
- #[serde(rename_all = "camelCase")]
317
- pub struct SiafundInput {
318
- pub parent: SiafundElement,
319
- pub claim_address: Address,
320
- pub satisfied_policy: SatisfiedPolicy,
321
- }
322
-
323
- /// A FileContractRevision updates the state of an existing file contract.
324
- #[derive(
325
- Debug, PartialEq, Serialize, Deserialize, AsyncSiaDecode, AsyncSiaEncode, SiaEncode, SiaDecode,
326
- )]
327
- #[serde(rename_all = "camelCase")]
328
- pub struct FileContractRevision {
329
- pub parent: FileContractElement,
330
- pub revision: FileContract,
331
- }
332
-
333
- impl FileContractRevision {
334
- fn encode_semantics<W: std::io::Write>(&self, w: &mut W) -> encoding::Result<()> {
335
- self.parent.id.encode(w)?;
336
- self.revision.encode_semantics(w)?;
337
- Ok(())
338
- }
339
- }
340
-
341
- /// A FileContractRenewal renews a file contract with optional rollover
342
- /// of any unspent funds.
343
- #[derive(
344
- Debug, PartialEq, Serialize, Deserialize, AsyncSiaDecode, AsyncSiaEncode, SiaEncode, SiaDecode,
345
- )]
346
- #[serde(rename_all = "camelCase")]
347
- pub struct FileContractRenewal {
348
- pub final_revision: FileContract,
349
- pub new_contract: FileContract,
350
- pub renter_rollover: Currency,
351
- pub host_rollover: Currency,
352
-
353
- // signatures cover above fields
354
- pub renter_signature: Signature,
355
- pub host_signature: Signature,
356
- }
357
-
358
- impl FileContractRenewal {
359
- fn encode_semantics<W: std::io::Write>(&self, w: &mut W) -> encoding::Result<()> {
360
- self.final_revision.encode_semantics(w)?;
361
- self.new_contract.encode_semantics(w)?;
362
- self.renter_rollover.encode(w)?;
363
- self.host_rollover.encode(w)?;
364
- [0u8; 64].encode(w)?; // empty renter sig
365
- [0u8; 64].encode(w)?; // empty host sig
366
- Ok(())
367
- }
368
-
369
- pub fn sig_hash(&self, cs: &ChainState) -> Hash256 {
370
- let mut state = Params::new().hash_length(32).to_state();
371
- state.update("sia/sig/filecontractrenewal|".as_bytes());
372
- state.update(cs.replay_prefix());
373
- self.encode_semantics(&mut state).unwrap();
374
- state.finalize().into()
375
- }
376
- }
377
-
378
- /// A StorageProof asserts the presence of a randomly-selected leaf within the
379
- /// Merkle tree of a V2FileContract's data.
380
- #[derive(
381
- Debug, PartialEq, Serialize, Deserialize, AsyncSiaDecode, AsyncSiaEncode, SiaEncode, SiaDecode,
382
- )]
383
- #[serde(rename_all = "camelCase")]
384
- pub struct StorageProof {
385
- // Selecting the leaf requires a source of unpredictable entropy; we use the
386
- // ID of the block at the contract's ProofHeight. The storage proof thus
387
- // includes a proof that this ID is the correct ancestor.
388
- //
389
- // During validation, it is imperative to check that ProofIndex.Height
390
- // matches the ProofHeight field of the contract's final revision;
391
- // otherwise, the prover could use any ProofIndex, giving them control over
392
- // the leaf index.
393
- pub proof_index: ChainIndexElement,
394
- // The leaf is always 64 bytes, extended with zeros if necessary.
395
- pub leaf: Leaf,
396
- pub proof: Vec<Hash256>,
397
- }
398
-
399
- impl StorageProof {
400
- fn encode_semantics<W: std::io::Write>(&self, w: &mut W) -> encoding::Result<()> {
401
- self.proof_index.encode_semantics(w)?;
402
- self.leaf.encode(w)?;
403
- self.proof.encode(w)?;
404
- Ok(())
405
- }
406
- }
407
-
408
- // A ContractResolution closes a v2 file contract's payment channel. There
409
- /// are four ways a contract can be resolved:
410
- ///
411
- /// 1. The renter can finalize the contract's current state, preventing further
412
- /// revisions and immediately creating its outputs.
413
- ///
414
- /// 2. The renter and host can jointly renew the contract. The old contract is
415
- /// finalized, and a portion of its funds are "rolled over" into a new contract.
416
- ///
417
- /// 3. The host can submit a storage proof, asserting that it has faithfully
418
- /// stored the contract data for the agreed-upon duration. A storage proof can only be submitted after the
419
- /// contract's ProofHeight; this allows the renter (or host) to broadcast the
420
- /// latest contract revision prior to the proof.
421
- ///
422
- /// 4. Lastly, anyone can submit a contract expiration. Typically, an expiration
423
- /// is only required if the host is unable or unwilling to sign a finalization or
424
- /// renewal. An expiration can only be submitted after the contract's
425
- /// ExpirationHeight; this gives the host a reasonable window of time after the
426
- /// ProofHeight in which to submit a storage proof.
427
- ///
428
- /// Once a contract has been resolved, it cannot be altered or resolved again.
429
- /// When a contract is resolved, its RenterOutput and HostOutput are created
430
- /// immediately (though they will not be spendable until their timelock expires).
431
- /// However, if the contract is resolved via an expiration, the HostOutput will
432
- /// have value equal to MissedHostValue; in other words, the host forfeits its
433
- /// collateral. This is considered a "missed" resolution; all other resolution
434
- /// types are "valid." As a special case, the expiration of an empty contract is
435
- /// considered valid, reflecting the fact that the host has not failed to perform
436
- /// any duty.
437
- #[derive(Debug, PartialEq, Serialize, Deserialize)]
438
- #[serde(rename_all = "camelCase")]
439
- #[allow(clippy::large_enum_variant)]
440
- pub enum ContractResolution {
441
- Renewal(FileContractRenewal),
442
- StorageProof(StorageProof),
443
- Expiration(),
444
- }
445
-
446
- /// A FileContractResolution closes a v2 file contract's payment channel.
447
- #[derive(Debug, PartialEq)]
448
- pub struct FileContractResolution {
449
- pub parent: FileContractElement,
450
- pub resolution: ContractResolution,
451
- }
452
-
453
- impl FileContractResolution {
454
- fn encode_semantics<W: std::io::Write>(&self, w: &mut W) -> encoding::Result<()> {
455
- self.parent.id.encode(w)?;
456
- match &self.resolution {
457
- // type is not encoded in the resolution semantics
458
- ContractResolution::Renewal(renewal) => renewal.encode_semantics(w),
459
- ContractResolution::StorageProof(proof) => proof.encode_semantics(w),
460
- ContractResolution::Expiration() => Ok(()),
461
- }
462
- }
463
- }
464
-
465
- impl SiaEncodable for FileContractResolution {
466
- fn encode<W: std::io::Write>(&self, w: &mut W) -> encoding::Result<()> {
467
- self.parent.encode(w)?;
468
- match &self.resolution {
469
- ContractResolution::Renewal(renewal) => {
470
- 0u8.encode(w)?;
471
- renewal.encode(w)
472
- }
473
- ContractResolution::StorageProof(proof) => {
474
- 1u8.encode(w)?;
475
- proof.encode(w)
476
- }
477
- ContractResolution::Expiration() => 2u8.encode(w),
478
- }
479
- }
480
- }
481
-
482
- impl SiaDecodable for FileContractResolution {
483
- fn decode<R: std::io::Read>(r: &mut R) -> encoding::Result<Self> {
484
- let parent = FileContractElement::decode(r)?;
485
- let resolution = match u8::decode(r)? {
486
- 0 => ContractResolution::Renewal(FileContractRenewal::decode(r)?),
487
- 1 => ContractResolution::StorageProof(StorageProof::decode(r)?),
488
- 2 => ContractResolution::Expiration(),
489
- _ => {
490
- return Err(encoding::Error::Custom(
491
- "invalid contract resolution type".to_string(),
492
- ));
493
- }
494
- };
495
- Ok(FileContractResolution { parent, resolution })
496
- }
497
- }
498
-
499
- impl AsyncSiaEncodable for FileContractResolution {
500
- async fn encode_async<E: AsyncEncoder>(&self, e: &mut E) -> Result<(), E::Error> {
501
- self.parent.encode_async(e).await?;
502
- match &self.resolution {
503
- ContractResolution::Renewal(renewal) => {
504
- 0u8.encode_async(e).await?;
505
- renewal.encode_async(e).await
506
- }
507
- ContractResolution::StorageProof(proof) => {
508
- 1u8.encode_async(e).await?;
509
- proof.encode_async(e).await
510
- }
511
- ContractResolution::Expiration() => 2u8.encode_async(e).await,
512
- }
513
- }
514
- }
515
-
516
- impl AsyncSiaDecodable for FileContractResolution {
517
- async fn decode_async<D: AsyncDecoder>(d: &mut D) -> Result<Self, D::Error> {
518
- let parent = FileContractElement::decode_async(d).await?;
519
- let resolution_type = u8::decode_async(d).await?;
520
- let resolution = match resolution_type {
521
- 0 => ContractResolution::Renewal(FileContractRenewal::decode_async(d).await?),
522
- 1 => ContractResolution::StorageProof(StorageProof::decode_async(d).await?),
523
- 2 => ContractResolution::Expiration(),
524
- _ => {
525
- return Err(encoding::Error::InvalidValue(format!(
526
- "invalid contract resolution type: {resolution_type}"
527
- ))
528
- .into());
529
- }
530
- };
531
- Ok(FileContractResolution { parent, resolution })
532
- }
533
- }
534
-
535
- impl Serialize for FileContractResolution {
536
- fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
537
- where
538
- S: serde::Serializer,
539
- {
540
- let mut state = serializer.serialize_struct("FileContractResolution", 3)?;
541
- state.serialize_field("parent", &self.parent)?;
542
- state.serialize_field(
543
- "type",
544
- &match &self.resolution {
545
- ContractResolution::Renewal(_) => "renewal",
546
- ContractResolution::StorageProof(_) => "storageProof",
547
- ContractResolution::Expiration() => "expiration",
548
- },
549
- )?;
550
- let resolution = match &self.resolution {
551
- ContractResolution::Renewal(renewal) => {
552
- serde_json::to_value(renewal).map_err(serde::ser::Error::custom)?
553
- }
554
- ContractResolution::StorageProof(proof) => {
555
- serde_json::to_value(proof).map_err(serde::ser::Error::custom)?
556
- }
557
- ContractResolution::Expiration() => json!({}),
558
- };
559
- state.serialize_field("resolution", &resolution)?;
560
- state.end()
561
- }
562
- }
563
-
564
- impl<'de> Deserialize<'de> for FileContractResolution {
565
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
566
- where
567
- D: serde::Deserializer<'de>,
568
- {
569
- struct FileContractResolutionVisitor;
570
-
571
- impl<'de> Visitor<'de> for FileContractResolutionVisitor {
572
- type Value = FileContractResolution;
573
-
574
- fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
575
- formatter.write_str("struct FileContractResolution")
576
- }
577
-
578
- fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
579
- where
580
- V: MapAccess<'de>,
581
- {
582
- let mut parent: Option<FileContractElement> = None;
583
- let mut resolution_type: Option<String> = None;
584
- let mut resolution_value: Option<serde_json::Value> = None;
585
-
586
- while let Some(key) = map.next_key::<String>()? {
587
- match key.as_str() {
588
- "parent" => parent = Some(map.next_value()?),
589
- "type" => resolution_type = Some(map.next_value()?),
590
- "resolution" => resolution_value = Some(map.next_value()?),
591
- _ => {
592
- return Err(serde::de::Error::unknown_field(
593
- key.as_str(),
594
- &["parent", "type", "resolution"],
595
- ));
596
- }
597
- }
598
- }
599
-
600
- let parent = parent.ok_or_else(|| serde::de::Error::missing_field("parent"))?;
601
- let resolution_type =
602
- resolution_type.ok_or_else(|| serde::de::Error::missing_field("type"))?;
603
- let resolution_value = resolution_value
604
- .ok_or_else(|| serde::de::Error::missing_field("resolution"))?;
605
-
606
- let resolution = match resolution_type.as_str() {
607
- "renewal" => ContractResolution::Renewal(
608
- serde_json::from_value(resolution_value).map_err(Error::custom)?,
609
- ),
610
- "storageProof" => ContractResolution::StorageProof(
611
- serde_json::from_value(resolution_value).map_err(Error::custom)?,
612
- ),
613
- "expiration" => ContractResolution::Expiration(),
614
- _ => return Err(serde::de::Error::custom("invalid contract resolution type")),
615
- };
616
-
617
- Ok(FileContractResolution { parent, resolution })
618
- }
619
- }
620
- deserializer.deserialize_struct(
621
- "FileContractResolution",
622
- &["parent", "type", "resolution"],
623
- FileContractResolutionVisitor,
624
- )
625
- }
626
- }
627
-
628
- /// A Transaction effects a change of blockchain state.
629
- #[derive(Debug, PartialEq, Serialize, Deserialize)]
630
- #[serde(rename_all = "camelCase")]
631
- pub struct Transaction {
632
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
633
- pub siacoin_inputs: Vec<SiacoinInput>,
634
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
635
- pub siacoin_outputs: Vec<SiacoinOutput>,
636
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
637
- pub siafund_inputs: Vec<SiafundInput>,
638
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
639
- pub siafund_outputs: Vec<SiafundOutput>,
640
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
641
- pub file_contracts: Vec<FileContract>,
642
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
643
- pub file_contract_revisions: Vec<FileContractRevision>,
644
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
645
- pub file_contract_resolutions: Vec<FileContractResolution>,
646
- #[serde(default, skip_serializing_if = "Vec::is_empty")]
647
- pub attestations: Vec<Attestation>,
648
- #[serde(
649
- default,
650
- with = "crate::types::utils::base64",
651
- skip_serializing_if = "Vec::is_empty"
652
- )]
653
- pub arbitrary_data: Vec<u8>,
654
- #[serde(default, skip_serializing_if = "Option::is_none")]
655
- pub new_foundation_address: Option<Address>,
656
- pub miner_fee: Currency,
657
- }
658
-
659
- impl Transaction {
660
- fn encode_semantics<W: io::Write>(&self, w: &mut W) -> encoding::Result<()> {
661
- self.siacoin_inputs.len().encode(w)?;
662
- for input in &self.siacoin_inputs {
663
- input.parent.id.encode(w)?;
664
- }
665
- self.siacoin_outputs.encode(w)?;
666
- self.siafund_inputs.len().encode(w)?;
667
- for input in &self.siafund_inputs {
668
- input.parent.id.encode(w)?;
669
- }
670
- self.siafund_outputs.encode(w)?;
671
- self.file_contracts.len().encode(w)?;
672
- for fc in &self.file_contracts {
673
- fc.encode_semantics(w)?;
674
- }
675
- self.file_contract_revisions.len().encode(w)?;
676
- for fcr in &self.file_contract_revisions {
677
- fcr.encode_semantics(w)?;
678
- }
679
- self.file_contract_resolutions.len().encode(w)?;
680
- for fcr in &self.file_contract_resolutions {
681
- fcr.encode_semantics(w)?;
682
- }
683
- self.attestations.encode(w)?;
684
- self.arbitrary_data.encode(w)?;
685
- self.new_foundation_address.encode(w)?;
686
- self.miner_fee.encode(w)?;
687
- Ok(())
688
- }
689
-
690
- pub fn id(&self) -> TransactionID {
691
- let mut state = Params::new().hash_length(32).to_state();
692
- self.encode_semantics(&mut state).unwrap();
693
- state.finalize().into()
694
- }
695
-
696
- pub fn input_sig_hash(&self, cs: &ChainState) -> Hash256 {
697
- let mut state = Params::new().hash_length(32).to_state();
698
- state.update("sia/sig/input|".as_bytes());
699
- state.update(cs.replay_prefix());
700
- self.encode_semantics(&mut state).unwrap();
701
- state.finalize().into()
702
- }
703
- }
704
-
705
- impl Default for Transaction {
706
- fn default() -> Self {
707
- Transaction {
708
- siacoin_inputs: Vec::new(),
709
- siacoin_outputs: Vec::new(),
710
- siafund_inputs: Vec::new(),
711
- siafund_outputs: Vec::new(),
712
- file_contracts: Vec::new(),
713
- file_contract_revisions: Vec::new(),
714
- file_contract_resolutions: Vec::new(),
715
- attestations: Vec::new(),
716
- arbitrary_data: Vec::new(),
717
- new_foundation_address: None,
718
- miner_fee: Currency::zero(),
719
- }
720
- }
721
- }
722
-
723
- const TXN_VERSION: u8 = 2;
724
-
725
- impl SiaEncodable for Transaction {
726
- fn encode<W: io::Write>(&self, w: &mut W) -> encoding::Result<()> {
727
- TXN_VERSION.encode(w)?;
728
-
729
- let fields = [
730
- !self.siacoin_inputs.is_empty(),
731
- !self.siacoin_outputs.is_empty(),
732
- !self.siafund_inputs.is_empty(),
733
- !self.siafund_outputs.is_empty(),
734
- !self.file_contracts.is_empty(),
735
- !self.file_contract_revisions.is_empty(),
736
- !self.file_contract_resolutions.is_empty(),
737
- !self.attestations.is_empty(),
738
- !self.arbitrary_data.is_empty(),
739
- self.new_foundation_address.is_some(),
740
- self.miner_fee != Currency::zero(),
741
- ]
742
- .iter()
743
- .enumerate()
744
- .filter(|&(_, condition)| *condition)
745
- .map(|(i, _)| 1 << i)
746
- .sum::<u64>();
747
- fields.encode(w)?;
748
-
749
- if !self.siacoin_inputs.is_empty() {
750
- self.siacoin_inputs.encode(w)?;
751
- }
752
- if !self.siacoin_outputs.is_empty() {
753
- self.siacoin_outputs.encode(w)?;
754
- }
755
- if !self.siafund_inputs.is_empty() {
756
- self.siafund_inputs.encode(w)?;
757
- }
758
- if !self.siafund_outputs.is_empty() {
759
- self.siafund_outputs.encode(w)?;
760
- }
761
- if !self.file_contracts.is_empty() {
762
- self.file_contracts.encode(w)?;
763
- }
764
- if !self.file_contract_revisions.is_empty() {
765
- self.file_contract_revisions.encode(w)?;
766
- }
767
- if !self.file_contract_resolutions.is_empty() {
768
- self.file_contract_resolutions.encode(w)?;
769
- }
770
- if !self.attestations.is_empty() {
771
- self.attestations.encode(w)?;
772
- }
773
- if !self.arbitrary_data.is_empty() {
774
- self.arbitrary_data.encode(w)?;
775
- }
776
- if let Some(addr) = &self.new_foundation_address {
777
- addr.encode(w)?;
778
- }
779
- if self.miner_fee != Currency::zero() {
780
- self.miner_fee.encode(w)?;
781
- }
782
- Ok(())
783
- }
784
- }
785
-
786
- impl SiaDecodable for Transaction {
787
- fn decode<R: io::Read>(r: &mut R) -> encoding::Result<Self> {
788
- let version = u8::decode(r)?;
789
- if version != TXN_VERSION {
790
- return Err(encoding::Error::Custom(
791
- "unsupported transaction version".to_string(),
792
- ));
793
- }
794
-
795
- let fields = u64::decode(r)?;
796
- let mut txn = Transaction {
797
- siacoin_inputs: Vec::new(),
798
- siacoin_outputs: Vec::new(),
799
- siafund_inputs: Vec::new(),
800
- siafund_outputs: Vec::new(),
801
- file_contracts: Vec::new(),
802
- file_contract_revisions: Vec::new(),
803
- file_contract_resolutions: Vec::new(),
804
- attestations: Vec::new(),
805
- arbitrary_data: Vec::new(),
806
- new_foundation_address: None,
807
- miner_fee: Currency::zero(),
808
- };
809
- if fields & 1 != 0 {
810
- txn.siacoin_inputs = Vec::decode(r)?;
811
- }
812
- if fields & 2 != 0 {
813
- txn.siacoin_outputs = Vec::decode(r)?;
814
- }
815
- if fields & 4 != 0 {
816
- txn.siafund_inputs = Vec::decode(r)?;
817
- }
818
- if fields & 8 != 0 {
819
- txn.siafund_outputs = Vec::decode(r)?;
820
- }
821
- if fields & 16 != 0 {
822
- txn.file_contracts = Vec::decode(r)?;
823
- }
824
- if fields & 32 != 0 {
825
- txn.file_contract_revisions = Vec::decode(r)?;
826
- }
827
- if fields & 64 != 0 {
828
- txn.file_contract_resolutions = Vec::decode(r)?;
829
- }
830
- if fields & 128 != 0 {
831
- txn.attestations = Vec::decode(r)?;
832
- }
833
- if fields & 256 != 0 {
834
- txn.arbitrary_data = Vec::decode(r)?;
835
- }
836
- if fields & 512 != 0 {
837
- txn.new_foundation_address = Some(Address::decode(r)?);
838
- }
839
- if fields & 1024 != 0 {
840
- txn.miner_fee = Currency::decode(r)?;
841
- }
842
-
843
- Ok(txn)
844
- }
845
- }
846
-
847
- impl AsyncSiaEncodable for Transaction {
848
- async fn encode_async<E: AsyncEncoder>(&self, e: &mut E) -> Result<(), E::Error> {
849
- TXN_VERSION.encode_async(e).await?;
850
-
851
- let fields = [
852
- !self.siacoin_inputs.is_empty(),
853
- !self.siacoin_outputs.is_empty(),
854
- !self.siafund_inputs.is_empty(),
855
- !self.siafund_outputs.is_empty(),
856
- !self.file_contracts.is_empty(),
857
- !self.file_contract_revisions.is_empty(),
858
- !self.file_contract_resolutions.is_empty(),
859
- !self.attestations.is_empty(),
860
- !self.arbitrary_data.is_empty(),
861
- self.new_foundation_address.is_some(),
862
- self.miner_fee != Currency::zero(),
863
- ]
864
- .iter()
865
- .enumerate()
866
- .filter(|&(_, condition)| *condition)
867
- .map(|(i, _)| 1 << i)
868
- .sum::<u64>();
869
- fields.encode_async(e).await?;
870
-
871
- if !self.siacoin_inputs.is_empty() {
872
- self.siacoin_inputs.encode_async(e).await?;
873
- }
874
- if !self.siacoin_outputs.is_empty() {
875
- self.siacoin_outputs.encode_async(e).await?;
876
- }
877
- if !self.siafund_inputs.is_empty() {
878
- self.siafund_inputs.encode_async(e).await?;
879
- }
880
- if !self.siafund_outputs.is_empty() {
881
- self.siafund_outputs.encode_async(e).await?;
882
- }
883
- if !self.file_contracts.is_empty() {
884
- self.file_contracts.encode_async(e).await?;
885
- }
886
- if !self.file_contract_revisions.is_empty() {
887
- self.file_contract_revisions.encode_async(e).await?;
888
- }
889
- if !self.file_contract_resolutions.is_empty() {
890
- self.file_contract_resolutions.encode_async(e).await?;
891
- }
892
- if !self.attestations.is_empty() {
893
- self.attestations.encode_async(e).await?;
894
- }
895
- if !self.arbitrary_data.is_empty() {
896
- self.arbitrary_data.encode_async(e).await?;
897
- }
898
- if let Some(addr) = &self.new_foundation_address {
899
- addr.encode_async(e).await?;
900
- }
901
- if self.miner_fee != Currency::zero() {
902
- self.miner_fee.encode_async(e).await?;
903
- }
904
- Ok(())
905
- }
906
- }
907
-
908
- impl AsyncSiaDecodable for Transaction {
909
- async fn decode_async<D: AsyncDecoder>(d: &mut D) -> Result<Self, D::Error> {
910
- let version = u8::decode_async(d).await?;
911
- if version != TXN_VERSION {
912
- return Err(encoding::Error::InvalidValue(format!(
913
- "invalid transaction version: {version}"
914
- ))
915
- .into());
916
- }
917
-
918
- let fields = u64::decode_async(d).await?;
919
- let mut txn = Transaction {
920
- siacoin_inputs: Vec::new(),
921
- siacoin_outputs: Vec::new(),
922
- siafund_inputs: Vec::new(),
923
- siafund_outputs: Vec::new(),
924
- file_contracts: Vec::new(),
925
- file_contract_revisions: Vec::new(),
926
- file_contract_resolutions: Vec::new(),
927
- attestations: Vec::new(),
928
- arbitrary_data: Vec::new(),
929
- new_foundation_address: None,
930
- miner_fee: Currency::zero(),
931
- };
932
- if fields & 1 != 0 {
933
- txn.siacoin_inputs = Vec::decode_async(d).await?;
934
- }
935
- if fields & 2 != 0 {
936
- txn.siacoin_outputs = Vec::decode_async(d).await?;
937
- }
938
- if fields & 4 != 0 {
939
- txn.siafund_inputs = Vec::decode_async(d).await?;
940
- }
941
- if fields & 8 != 0 {
942
- txn.siafund_outputs = Vec::decode_async(d).await?;
943
- }
944
- if fields & 16 != 0 {
945
- txn.file_contracts = Vec::decode_async(d).await?;
946
- }
947
- if fields & 32 != 0 {
948
- txn.file_contract_revisions = Vec::decode_async(d).await?;
949
- }
950
- if fields & 64 != 0 {
951
- txn.file_contract_resolutions = Vec::decode_async(d).await?;
952
- }
953
- if fields & 128 != 0 {
954
- txn.attestations = Vec::decode_async(d).await?;
955
- }
956
- if fields & 256 != 0 {
957
- txn.arbitrary_data = Vec::decode_async(d).await?;
958
- }
959
- if fields & 512 != 0 {
960
- txn.new_foundation_address = Some(Address::decode_async(d).await?);
961
- }
962
- if fields & 1024 != 0 {
963
- txn.miner_fee = Currency::decode_async(d).await?;
964
- }
965
-
966
- Ok(txn)
967
- }
968
- }
969
-
970
- #[cfg(test)]
971
- mod tests {
972
- use super::*;
973
- use crate::consensus::{
974
- ElementAccumulator, HardforkASIC, HardforkDevAddr, HardforkFoundation, HardforkOak,
975
- HardforkStorageProof, HardforkTax, HardforkV2, Network, State,
976
- };
977
- use crate::types::Work;
978
- use crate::{address, hash_256, public_key, siacoin_id};
979
- use chrono::{DateTime, Duration};
980
- use core::fmt::Debug;
981
- use serde::Serialize;
982
- use serde::de::DeserializeOwned;
983
-
984
- /// test_serialize_json is a helper to test serialization and deserialization of a struct to and from JSON.
985
- fn test_serialize_json<S: Serialize + DeserializeOwned + Debug + PartialEq>(
986
- obj: &S,
987
- json_str: &str,
988
- ) {
989
- let serialized = serde_json::to_string(&obj).unwrap();
990
- assert_eq!(serialized, json_str);
991
- let deserialized: S = serde_json::from_str(&serialized).unwrap();
992
- assert_eq!(deserialized, *obj);
993
- }
994
-
995
- /// test_serialize is a helper to test serialization and deserialization of a struct to and from Sia's
996
- /// custom binary encoding.
997
- fn test_serialize<S: SiaEncodable + SiaDecodable + Debug + PartialEq>(
998
- obj: &S,
999
- hex_binary: &str,
1000
- ) {
1001
- let mut serialized = Vec::new();
1002
- obj.encode(&mut serialized).unwrap();
1003
- assert_eq!(hex::encode(serialized.clone()), hex_binary);
1004
- let deserialized = S::decode(&mut &serialized[..]).unwrap();
1005
- assert_eq!(deserialized, *obj);
1006
- }
1007
-
1008
- #[test]
1009
- fn test_serialize_siacoin_element() {
1010
- let se = SiacoinElement {
1011
- id: SiacoinOutputID::default(),
1012
- siacoin_output: SiacoinOutput {
1013
- value: Currency::new(2389084800000000000000000000000000),
1014
- address: Address::new([0; 32]),
1015
- },
1016
- state_element: StateElement {
1017
- leaf_index: 0,
1018
- merkle_proof: vec![Hash256::default()],
1019
- },
1020
- maturity_height: 0,
1021
- };
1022
-
1023
- let binary_str = "0000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000809ab5dad71c4e547dca75000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
1024
- test_serialize(&se, binary_str);
1025
-
1026
- let json_str = "{\"stateElement\":{\"leafIndex\":0,\"merkleProof\":[\"0000000000000000000000000000000000000000000000000000000000000000\"]},\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"siacoinOutput\":{\"value\":\"2389084800000000000000000000000000\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"maturityHeight\":0}";
1027
- test_serialize_json(&se, json_str);
1028
- }
1029
-
1030
- #[test]
1031
- fn test_serialize_siafund_element() {
1032
- let se = SiafundElement {
1033
- id: SiafundOutputID::default(),
1034
- state_element: StateElement {
1035
- leaf_index: 0,
1036
- merkle_proof: vec![Hash256::default()],
1037
- },
1038
- siafund_output: SiafundOutput {
1039
- value: 1086708929188041408,
1040
- address: Address::new([0; 32]),
1041
- },
1042
- claim_start: Currency::new(0),
1043
- };
1044
-
1045
- let binary_str = "0000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0927f7203c4140f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
1046
- test_serialize(&se, binary_str);
1047
-
1048
- let json_str = "{\"stateElement\":{\"leafIndex\":0,\"merkleProof\":[\"0000000000000000000000000000000000000000000000000000000000000000\"]},\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"siafundOutput\":{\"value\":1086708929188041408,\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"claimStart\":\"0\"}";
1049
- test_serialize_json(&se, json_str);
1050
- }
1051
-
1052
- #[test]
1053
- fn test_serialize_file_contract_element() {
1054
- let fce = FileContractElement {
1055
- id: FileContractID::default(),
1056
- state_element: StateElement {
1057
- leaf_index: 0,
1058
- merkle_proof: vec![Hash256::default()],
1059
- },
1060
- v2_file_contract: FileContract {
1061
- capacity: 7938725446189123975,
1062
- filesize: 4815560028289493432,
1063
- file_merkle_root: hash_256!(
1064
- "dc033023420634ed4c7685c82aa884eebe8415e16c57b6a55c673a5a98fa7b0d"
1065
- ),
1066
- proof_height: 6265010746208955018,
1067
- expiration_height: 5159880069065321628,
1068
- renter_output: SiacoinOutput {
1069
- value: Currency::new(3837391090000000000000000000000000),
1070
- address: Address::new([0; 32]),
1071
- },
1072
- host_output: SiacoinOutput {
1073
- value: Currency::new(3827725744000000000000000000000000),
1074
- address: Address::new([0; 32]),
1075
- },
1076
- missed_host_value: Currency::new(965900695000000000000000000000000),
1077
- total_collateral: Currency::new(0),
1078
- host_public_key: PublicKey::new([0; 32]),
1079
- renter_public_key: PublicKey::new([0; 32]),
1080
- revision_number: 0,
1081
-
1082
- host_signature: Signature::new([0; 64]),
1083
- renter_signature: Signature::new([0; 64]),
1084
- },
1085
- };
1086
-
1087
- let binary_str = "00000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008709756dbb042c6eb8e9c3f0544ed442dc033023420634ed4c7685c82aa884eebe8415e16c57b6a55c673a5a98fa7b0d8a2aca8914caf1569cac41a895939b470000003292d8b9e4856e58af32bd00000000000000000000000000000000000000000000000000000000000000000000000000b0f3637fb05e9bedb0b8bc00000000000000000000000000000000000000000000000000000000000000000000000000f7420336ee348e78619f2f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
1088
- test_serialize(&fce, binary_str);
1089
-
1090
- let json_str = "{\"stateElement\":{\"leafIndex\":0,\"merkleProof\":[\"0000000000000000000000000000000000000000000000000000000000000000\"]},\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"v2FileContract\":{\"capacity\":7938725446189123975,\"filesize\":4815560028289493432,\"fileMerkleRoot\":\"dc033023420634ed4c7685c82aa884eebe8415e16c57b6a55c673a5a98fa7b0d\",\"proofHeight\":6265010746208955018,\"expirationHeight\":5159880069065321628,\"renterOutput\":{\"value\":\"3837391090000000000000000000000000\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"hostOutput\":{\"value\":\"3827725744000000000000000000000000\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"965900695000000000000000000000000\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}";
1091
- test_serialize_json(&fce, json_str);
1092
- }
1093
-
1094
- #[test]
1095
- fn test_serialize_file_contract() {
1096
- let fc = FileContract {
1097
- capacity: 0,
1098
- filesize: 0,
1099
- file_merkle_root: Hash256::default(),
1100
- proof_height: 0,
1101
- expiration_height: 0,
1102
- renter_output: SiacoinOutput {
1103
- value: Currency::new(0),
1104
- address: Address::new([0; 32]),
1105
- },
1106
- host_output: SiacoinOutput {
1107
- value: Currency::new(0),
1108
- address: Address::new([0; 32]),
1109
- },
1110
- missed_host_value: Currency::new(0),
1111
- total_collateral: Currency::new(0),
1112
- host_public_key: PublicKey::new([0; 32]),
1113
- renter_public_key: PublicKey::new([0; 32]),
1114
- revision_number: 0,
1115
-
1116
- host_signature: Signature::new([0; 64]),
1117
- renter_signature: Signature::new([0; 64]),
1118
- };
1119
-
1120
- let binary_str = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
1121
- test_serialize(&fc, binary_str);
1122
-
1123
- let json_str = "{\"capacity\":0,\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}";
1124
- test_serialize_json(&fc, json_str);
1125
- }
1126
-
1127
- #[test]
1128
- fn test_serialize_file_contract_revision() {
1129
- let fcr = FileContractRevision {
1130
- parent: FileContractElement {
1131
- id: FileContractID::default(),
1132
- state_element: StateElement {
1133
- leaf_index: 0,
1134
- merkle_proof: vec![Hash256::default()],
1135
- },
1136
- v2_file_contract: FileContract {
1137
- capacity: 0,
1138
- filesize: 0,
1139
- file_merkle_root: Hash256::default(),
1140
- proof_height: 0,
1141
- expiration_height: 0,
1142
- renter_output: SiacoinOutput {
1143
- value: Currency::new(0),
1144
- address: Address::new([0; 32]),
1145
- },
1146
- host_output: SiacoinOutput {
1147
- value: Currency::new(0),
1148
- address: Address::new([0; 32]),
1149
- },
1150
- missed_host_value: Currency::new(0),
1151
- total_collateral: Currency::new(0),
1152
- host_public_key: PublicKey::new([0; 32]),
1153
- renter_public_key: PublicKey::new([0; 32]),
1154
- revision_number: 0,
1155
-
1156
- host_signature: Signature::new([0; 64]),
1157
- renter_signature: Signature::new([0; 64]),
1158
- },
1159
- },
1160
- revision: FileContract {
1161
- capacity: 0,
1162
- filesize: 0,
1163
- file_merkle_root: Hash256::default(),
1164
- proof_height: 0,
1165
- expiration_height: 0,
1166
- renter_output: SiacoinOutput {
1167
- value: Currency::new(0),
1168
- address: Address::new([0; 32]),
1169
- },
1170
- host_output: SiacoinOutput {
1171
- value: Currency::new(0),
1172
- address: Address::new([0; 32]),
1173
- },
1174
- missed_host_value: Currency::new(0),
1175
- total_collateral: Currency::new(0),
1176
- host_public_key: PublicKey::new([0; 32]),
1177
- renter_public_key: PublicKey::new([0; 32]),
1178
- revision_number: 0,
1179
-
1180
- host_signature: Signature::new([0; 64]),
1181
- renter_signature: Signature::new([0; 64]),
1182
- },
1183
- };
1184
-
1185
- let binary_str = "000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
1186
- test_serialize(&fcr, binary_str);
1187
-
1188
- let json_str = "{\"parent\":{\"stateElement\":{\"leafIndex\":0,\"merkleProof\":[\"0000000000000000000000000000000000000000000000000000000000000000\"]},\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"v2FileContract\":{\"capacity\":0,\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}},\"revision\":{\"capacity\":0,\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}";
1189
- test_serialize_json(&fcr, json_str);
1190
- }
1191
-
1192
- #[test]
1193
- fn test_serialize_file_contract_renewal() {
1194
- let fcr = FileContractRenewal {
1195
- new_contract: FileContract {
1196
- capacity: 0,
1197
- filesize: 0,
1198
- file_merkle_root: Hash256::default(),
1199
- proof_height: 0,
1200
- expiration_height: 0,
1201
- renter_output: SiacoinOutput {
1202
- value: Currency::new(0),
1203
- address: Address::new([0; 32]),
1204
- },
1205
- host_output: SiacoinOutput {
1206
- value: Currency::new(0),
1207
- address: Address::new([0; 32]),
1208
- },
1209
- missed_host_value: Currency::new(0),
1210
- total_collateral: Currency::new(0),
1211
- host_public_key: PublicKey::new([0; 32]),
1212
- renter_public_key: PublicKey::new([0; 32]),
1213
- revision_number: 0,
1214
-
1215
- host_signature: Signature::new([0; 64]),
1216
- renter_signature: Signature::new([0; 64]),
1217
- },
1218
- final_revision: FileContract {
1219
- capacity: 0,
1220
- filesize: 0,
1221
- file_merkle_root: Hash256::default(),
1222
- proof_height: 0,
1223
- expiration_height: 0,
1224
- renter_output: SiacoinOutput {
1225
- value: Currency::new(0),
1226
- address: Address::new([0; 32]),
1227
- },
1228
- host_output: SiacoinOutput {
1229
- value: Currency::new(0),
1230
- address: Address::new([0; 32]),
1231
- },
1232
- missed_host_value: Currency::new(0),
1233
- total_collateral: Currency::new(0),
1234
- host_public_key: PublicKey::new([0; 32]),
1235
- renter_public_key: PublicKey::new([0; 32]),
1236
- revision_number: 0,
1237
-
1238
- host_signature: Signature::new([0; 64]),
1239
- renter_signature: Signature::new([0; 64]),
1240
- },
1241
- renter_rollover: Currency::new(0),
1242
- host_rollover: Currency::new(0),
1243
- renter_signature: Signature::new([0u8; 64]),
1244
- host_signature: Signature::new([0u8; 64]),
1245
- };
1246
-
1247
- let binary_str = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
1248
- test_serialize(&fcr, binary_str);
1249
-
1250
- let json_str = "{\"finalRevision\":{\"capacity\":0,\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"},\"newContract\":{\"capacity\":0,\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"},\"renterRollover\":\"0\",\"hostRollover\":\"0\",\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}";
1251
- test_serialize_json(&fcr, json_str);
1252
- }
1253
-
1254
- #[test]
1255
- fn test_serialize_storage_proof() {
1256
- let sp = StorageProof {
1257
- proof_index: ChainIndexElement {
1258
- id: BlockID::default(),
1259
- chain_index: ChainIndex {
1260
- id: BlockID::default(),
1261
- height: 0,
1262
- },
1263
- state_element: StateElement {
1264
- leaf_index: 0,
1265
- merkle_proof: vec![Hash256::default()],
1266
- },
1267
- },
1268
- leaf: [3u8; 64].into(),
1269
- proof: vec![Hash256::default()],
1270
- };
1271
-
1272
- let binary_str = "0000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030301000000000000000000000000000000000000000000000000000000000000000000000000000000";
1273
- test_serialize(&sp, binary_str);
1274
-
1275
- let json_str = "{\"proofIndex\":{\"stateElement\":{\"leafIndex\":0,\"merkleProof\":[\"0000000000000000000000000000000000000000000000000000000000000000\"]},\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"chainIndex\":{\"height\":0,\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\"}},\"leaf\":\"03030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303\",\"proof\":[\"0000000000000000000000000000000000000000000000000000000000000000\"]}";
1276
- test_serialize_json(&sp, json_str);
1277
- }
1278
-
1279
- fn test_chain_state() -> ChainState {
1280
- ChainState {
1281
- state: State {
1282
- index: ChainIndex {
1283
- height: 1,
1284
- id: BlockID::default(),
1285
- },
1286
- prev_timestamps: [DateTime::UNIX_EPOCH; 11],
1287
- depth: BlockID::default(),
1288
- child_target: BlockID::default(),
1289
- siafund_pool: Currency::new(0),
1290
- oak_time: Duration::zero(),
1291
- oak_target: BlockID::default(),
1292
- foundation_primary_address: Address::new([0u8; 32]),
1293
- foundation_failsafe_address: Address::new([0u8; 32]),
1294
- total_work: Work::zero(),
1295
- difficulty: Work::zero(),
1296
- oak_work: Work::zero(),
1297
- elements: ElementAccumulator::default(),
1298
- attestations: 0,
1299
- },
1300
- network: Network {
1301
- name: "test".to_string(),
1302
- initial_coinbase: Currency::new(0),
1303
- minimum_coinbase: Currency::new(0),
1304
- initial_target: BlockID::default(),
1305
- block_interval: Duration::seconds(1),
1306
- maturity_delay: 0,
1307
- hardfork_dev_addr: HardforkDevAddr {
1308
- height: 0,
1309
- old_address: Address::new([0u8; 32]),
1310
- new_address: Address::new([0u8; 32]),
1311
- },
1312
- hardfork_tax: HardforkTax { height: 10 },
1313
- hardfork_storage_proof: HardforkStorageProof { height: 0 },
1314
- hardfork_asic: HardforkASIC {
1315
- height: 0,
1316
- oak_time: Duration::zero(),
1317
- oak_target: BlockID::default(),
1318
- },
1319
- hardfork_oak: HardforkOak {
1320
- height: 0,
1321
- fix_height: 0,
1322
- genesis_timestamp: DateTime::UNIX_EPOCH,
1323
- },
1324
- hardfork_foundation: HardforkFoundation {
1325
- height: 0,
1326
- primary_address: Address::new([0u8; 32]),
1327
- failsafe_address: Address::new([0u8; 32]),
1328
- },
1329
- hardfork_v2: HardforkV2 {
1330
- allow_height: 0,
1331
- require_height: 0,
1332
- },
1333
- },
1334
- }
1335
- }
1336
-
1337
- #[test]
1338
- fn test_serialize_v2_file_contract_resolution() {
1339
- struct TestCase {
1340
- resolution: ContractResolution,
1341
- binary_str: String,
1342
- json_str: String,
1343
- }
1344
- let test_cases = vec![
1345
- TestCase{
1346
- resolution: ContractResolution::Renewal(FileContractRenewal {
1347
- new_contract: FileContract {
1348
- capacity: 0,
1349
- filesize: 0,
1350
- file_merkle_root: Hash256::default(),
1351
- proof_height: 0,
1352
- expiration_height: 0,
1353
- renter_output: SiacoinOutput {
1354
- value: Currency::new(0),
1355
- address: Address::new([0; 32]),
1356
- },
1357
- host_output: SiacoinOutput {
1358
- value: Currency::new(0),
1359
- address: Address::new([0; 32]),
1360
- },
1361
- missed_host_value: Currency::new(0),
1362
- total_collateral: Currency::new(0),
1363
- host_public_key: PublicKey::new([0; 32]),
1364
- renter_public_key: PublicKey::new([0; 32]),
1365
- revision_number: 0,
1366
-
1367
- host_signature: Signature::new([0; 64]),
1368
- renter_signature: Signature::new([0; 64]),
1369
- },
1370
- final_revision: FileContract {
1371
- capacity: 0,
1372
- filesize: 0,
1373
- file_merkle_root: Hash256::default(),
1374
- proof_height: 0,
1375
- expiration_height: 0,
1376
- renter_output: SiacoinOutput {
1377
- value: Currency::new(0),
1378
- address: Address::new([0; 32]),
1379
- },
1380
- host_output: SiacoinOutput {
1381
- value: Currency::new(0),
1382
- address: Address::new([0; 32]),
1383
- },
1384
- missed_host_value: Currency::new(0),
1385
- total_collateral: Currency::new(0),
1386
- host_public_key: PublicKey::new([0; 32]),
1387
- renter_public_key: PublicKey::new([0; 32]),
1388
- revision_number: 0,
1389
-
1390
- host_signature: Signature::new([0; 64]),
1391
- renter_signature: Signature::new([0; 64]),
1392
- },
1393
- renter_rollover: Currency::new(0),
1394
- host_rollover: Currency::new(0),
1395
- renter_signature: Signature::new([0u8; 64]),
1396
- host_signature: Signature::new([0u8; 64]),
1397
- }),
1398
- binary_str: "00000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".to_string(),
1399
- json_str: "{\"parent\":{\"stateElement\":{\"leafIndex\":0,\"merkleProof\":[\"0000000000000000000000000000000000000000000000000000000000000000\"]},\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"v2FileContract\":{\"capacity\":0,\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}},\"type\":\"renewal\",\"resolution\":{\"finalRevision\":{\"capacity\":0,\"expirationHeight\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"filesize\":0,\"hostOutput\":{\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\",\"value\":\"0\"},\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"missedHostValue\":\"0\",\"proofHeight\":0,\"renterOutput\":{\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\",\"value\":\"0\"},\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"totalCollateral\":\"0\"},\"hostRollover\":\"0\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"newContract\":{\"capacity\":0,\"expirationHeight\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"filesize\":0,\"hostOutput\":{\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\",\"value\":\"0\"},\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"missedHostValue\":\"0\",\"proofHeight\":0,\"renterOutput\":{\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\",\"value\":\"0\"},\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"totalCollateral\":\"0\"},\"renterRollover\":\"0\",\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}".to_string(),
1400
- },
1401
- TestCase{
1402
- resolution: ContractResolution::StorageProof(StorageProof{
1403
- proof_index: ChainIndexElement {
1404
- id: BlockID::default(),
1405
- chain_index: ChainIndex {
1406
- id: BlockID::default(),
1407
- height: 0,
1408
- },
1409
- state_element: StateElement {
1410
- leaf_index: 0,
1411
- merkle_proof: vec![Hash256::default()],
1412
- },
1413
- },
1414
- leaf: [0u8; 64].into(),
1415
- proof: vec![Hash256::default()],
1416
- }),
1417
- binary_str: "00000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000".to_string(),
1418
- json_str: "{\"parent\":{\"stateElement\":{\"leafIndex\":0,\"merkleProof\":[\"0000000000000000000000000000000000000000000000000000000000000000\"]},\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"v2FileContract\":{\"capacity\":0,\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}},\"type\":\"storageProof\",\"resolution\":{\"leaf\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"proof\":[\"0000000000000000000000000000000000000000000000000000000000000000\"],\"proofIndex\":{\"chainIndex\":{\"height\":0,\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\"},\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"stateElement\":{\"leafIndex\":0,\"merkleProof\":[\"0000000000000000000000000000000000000000000000000000000000000000\"]}}}}".to_string(),
1419
- },
1420
- TestCase{
1421
- resolution: ContractResolution::Expiration(),
1422
- binary_str: "0000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002".to_string(),
1423
- json_str: "{\"parent\":{\"stateElement\":{\"leafIndex\":0,\"merkleProof\":[\"0000000000000000000000000000000000000000000000000000000000000000\"]},\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"v2FileContract\":{\"capacity\":0,\"filesize\":0,\"fileMerkleRoot\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"renterSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"hostSignature\":\"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}},\"type\":\"expiration\",\"resolution\":{}}".to_string(),
1424
- }
1425
- ];
1426
- for tc in test_cases {
1427
- let fcr = FileContractResolution {
1428
- parent: FileContractElement {
1429
- id: FileContractID::default(),
1430
- state_element: StateElement {
1431
- leaf_index: 0,
1432
- merkle_proof: vec![Hash256::default()],
1433
- },
1434
- v2_file_contract: FileContract {
1435
- capacity: 0,
1436
- filesize: 0,
1437
- file_merkle_root: Hash256::default(),
1438
- proof_height: 0,
1439
- expiration_height: 0,
1440
- renter_output: SiacoinOutput {
1441
- value: Currency::new(0),
1442
- address: Address::new([0; 32]),
1443
- },
1444
- host_output: SiacoinOutput {
1445
- value: Currency::new(0),
1446
- address: Address::new([0; 32]),
1447
- },
1448
- missed_host_value: Currency::new(0),
1449
- total_collateral: Currency::new(0),
1450
- host_public_key: PublicKey::new([0; 32]),
1451
- renter_public_key: PublicKey::new([0; 32]),
1452
- revision_number: 0,
1453
-
1454
- host_signature: Signature::new([0; 64]),
1455
- renter_signature: Signature::new([0; 64]),
1456
- },
1457
- },
1458
- resolution: tc.resolution,
1459
- };
1460
-
1461
- test_serialize(&fcr, tc.binary_str.as_str());
1462
- test_serialize_json(&fcr, tc.json_str.as_str());
1463
- }
1464
- }
1465
-
1466
- #[test]
1467
- fn test_file_contract_tax() {
1468
- struct TestCase {
1469
- output_value: Currency,
1470
- tax: Currency,
1471
- }
1472
- let test_cases = vec![
1473
- TestCase {
1474
- output_value: Currency::new(0),
1475
- tax: Currency::new(0),
1476
- },
1477
- TestCase {
1478
- output_value: Currency::new(0),
1479
- tax: Currency::new(0),
1480
- },
1481
- TestCase {
1482
- output_value: Currency::new(1),
1483
- tax: Currency::new(0),
1484
- },
1485
- TestCase {
1486
- output_value: Currency::new(170141183460469231731687303715884105727),
1487
- tax: Currency::new(13611294676837538538534984297270720000),
1488
- },
1489
- TestCase {
1490
- output_value: Currency::new(805949712500000000000000000000000),
1491
- tax: Currency::new(64475977000000000000000000000000),
1492
- },
1493
- TestCase {
1494
- output_value: Currency::new(151318823166141058930638084278357033939),
1495
- tax: Currency::new(12105505853291284714451046742268560000),
1496
- },
1497
- TestCase {
1498
- output_value: Currency::new(2087287149000000000000000000000000),
1499
- tax: Currency::new(166982971920000000000000000000000),
1500
- },
1501
- TestCase {
1502
- output_value: Currency::new(19054329256128693174495496952954959442),
1503
- tax: Currency::new(1524346340490295453959639756236390000),
1504
- },
1505
- TestCase {
1506
- output_value: Currency::new(1463835551500000000000000000000000),
1507
- tax: Currency::new(117106844120000000000000000000000),
1508
- },
1509
- TestCase {
1510
- output_value: Currency::new(34808017277671855105213753517013880976),
1511
- tax: Currency::new(2784641382213748408417100281361110000),
1512
- },
1513
- TestCase {
1514
- output_value: Currency::new(1456475819000000000000000000000000),
1515
- tax: Currency::new(116518065520000000000000000000000),
1516
- },
1517
- TestCase {
1518
- output_value: Currency::new(4050009160038948139568737574567615426),
1519
- tax: Currency::new(324000732803115851165499005965400000),
1520
- },
1521
- TestCase {
1522
- output_value: Currency::new(611362349000000000000000000000000),
1523
- tax: Currency::new(48908987920000000000000000000000),
1524
- },
1525
- TestCase {
1526
- output_value: Currency::new(59744399278834191323014460064531501644),
1527
- tax: Currency::new(4779551942306735305841156805162520000),
1528
- },
1529
- TestCase {
1530
- output_value: Currency::new(1971395366500000000000000000000000),
1531
- tax: Currency::new(157711629320000000000000000000000),
1532
- },
1533
- TestCase {
1534
- output_value: Currency::new(129395477943018813820173885271365401215),
1535
- tax: Currency::new(10351638235441505105613910821709230000),
1536
- },
1537
- TestCase {
1538
- output_value: Currency::new(1562430843000000000000000000000000),
1539
- tax: Currency::new(124994467440000000000000000000000),
1540
- },
1541
- TestCase {
1542
- output_value: Currency::new(33394010960011557818205782768368594560),
1543
- tax: Currency::new(2671520876800924625456462621469480000),
1544
- },
1545
- TestCase {
1546
- output_value: Currency::new(1464305596000000000000000000000000),
1547
- tax: Currency::new(117144447680000000000000000000000),
1548
- },
1549
- TestCase {
1550
- output_value: Currency::new(33699424149038914903292787212706936885),
1551
- tax: Currency::new(2695953931923113192263422977016550000),
1552
- },
1553
- TestCase {
1554
- output_value: Currency::new(455795805000000000000000000000000),
1555
- tax: Currency::new(36463664400000000000000000000000),
1556
- },
1557
- TestCase {
1558
- output_value: Currency::new(88567642754201788868008131876936390234),
1559
- tax: Currency::new(7085411420336143109440650550154910000),
1560
- },
1561
- TestCase {
1562
- output_value: Currency::new(359253930000000000000000000000000),
1563
- tax: Currency::new(28740314400000000000000000000000),
1564
- },
1565
- TestCase {
1566
- output_value: Currency::new(56501907684312465044405566127405468273),
1567
- tax: Currency::new(4520152614744997203552445290192430000),
1568
- },
1569
- ];
1570
-
1571
- let cs = test_chain_state();
1572
- for tc in test_cases.iter() {
1573
- let fc = FileContract {
1574
- capacity: 0,
1575
- filesize: 0,
1576
- file_merkle_root: Hash256::default(),
1577
- revision_number: 0,
1578
- proof_height: 0,
1579
- expiration_height: 0,
1580
- missed_host_value: Currency::new(0),
1581
- total_collateral: Currency::new(0),
1582
- host_public_key: PublicKey::new([0u8; 32]),
1583
- renter_public_key: PublicKey::new([0u8; 32]),
1584
- host_signature: Signature::new([0u8; 64]),
1585
- renter_signature: Signature::new([0u8; 64]),
1586
- renter_output: SiacoinOutput {
1587
- value: tc.output_value,
1588
- address: Address::default(),
1589
- },
1590
- host_output: SiacoinOutput {
1591
- value: tc.output_value,
1592
- address: Address::default(),
1593
- },
1594
- };
1595
-
1596
- let tax = fc.tax(&cs);
1597
- assert_eq!(
1598
- tax, tc.tax,
1599
- "prefork tax incorrect for payout {:?}",
1600
- tc.output_value
1601
- );
1602
- }
1603
- }
1604
-
1605
- #[test]
1606
- fn test_attestation_sig_hash() {
1607
- let cs = test_chain_state();
1608
- let a = Attestation {
1609
- public_key: PublicKey::new([
1610
- 119, 70, 48, 66, 126, 125, 116, 9, 234, 170, 136, 51, 123, 122, 142, 138, 198, 136,
1611
- 19, 32, 194, 144, 129, 104, 130, 246, 58, 195, 16, 72, 139, 112,
1612
- ]),
1613
- key: "2d341885482102f2".to_string(),
1614
- value: vec![113, 1, 70, 231, 190, 215, 117, 38],
1615
- signature: Signature::default(),
1616
- };
1617
- let sig_hash = a.sig_hash(&cs);
1618
- assert_eq!(
1619
- hex::encode(sig_hash),
1620
- "5c4201fd4c261a1a3deb25130bd8f06d7d87a46281fd022252152844336a7c17"
1621
- )
1622
- }
1623
-
1624
- #[test]
1625
- fn test_file_contract_sig_hash() {
1626
- let cs = test_chain_state();
1627
- let s = "{\"capacity\":15437388468662742744,\"filesize\":16009828729725979578,\"fileMerkleRoot\":\"2d3b2c7b78f04eb1b66ac467ae7831081f7b495a2964b943c2c750e70180785a\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"2825068531000000000000000000000000\",\"address\":\"cf620149bcbde171fcd9611a32ba29e2e97687f3b1562c1fe14c504f642690c9d8f5ec3cbeaf\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"renterSignature\":\"bee650e82a5534269bef42be0dd9a0b0f6c465b31437567075275d2188c685b2b65ef0fc7f369c780a758786f480da4d55459a1d85215f64aa47db1e79b1b8de\",\"hostSignature\":\"c32cf921ee00344d76e96e6f2dd306bd9c21226c83bb2ac55ce69b8d991a2f2212f645341c720f2fd8a7c57edef9b32f26a2c29c55958a45fd5c0d56a2addae3\"}";
1628
-
1629
- let fc: FileContract = serde_json::from_str(s).unwrap();
1630
- let sig_hash = fc.sig_hash(&cs);
1631
- assert_eq!(
1632
- hex::encode(sig_hash),
1633
- "0b9b74e471b8936e0045e752a1a22a77b7c17807ec98a1a3f272f6d917790325"
1634
- );
1635
- }
1636
-
1637
- #[test]
1638
- fn test_contract_renewal_sig_hash() {
1639
- let cs = test_chain_state();
1640
- let s = "{\"finalRevision\":{\"capacity\":11959377077631068749,\"filesize\":10613077956865333006,\"fileMerkleRoot\":\"9482be576a5d68b6ad311b359b12070fae3df71fc0d2ec480a5ba8c3f4c9ad40\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"107325855000000000000000000000000\",\"address\":\"cc590b0901f908ee76ea2c8497b9c29d7f2250db4427b7b1dfd8d5c0a368845c4a70d66c8998\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":18446744073709551615,\"renterSignature\":\"a71062c50866e8e834143340117efc49adbe7c8e50775c2ef6c2d8fd84470231928115e377288d588d93342946adbcbc83c5e3be01d4d22accf59c86f44ad523\",\"hostSignature\":\"a277c4b62d6ab7eead9d02c9e6243810baa0af9a8fef8b70b2f33df83fc8e67b94b2247b53c5e6d3a93a6197d41dd07652b75896757cf1dfeb059edca458de40\"},\"newContract\":{\"capacity\":2615073250361876210,\"filesize\":14611382285114970285,\"fileMerkleRoot\":\"5942d80cb6816da220a9576d62f3979b5e4f96b769cf785bcddf31698afb1432\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"4046664893000000000000000000000000\",\"address\":\"41b74682d50aed617224d17162150c3854cc290b522c20d62260466ef13a95e212b7d9c6778b\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"renterSignature\":\"2614ae9d0b8300c98eadc1ffcab414298e30c678c0072359b1794623a04a68ef2474fbb1492071313b6f768946a52978b520c219a23649bfef9b9d0baabc7331\",\"hostSignature\":\"9c14a4f1428ad5bd72075c626fdf7dcf24143eda3a9cbecbc16ca751f0c88ee09e04a7f4f79718fb87df6debdd1d94d97bd00bcfa4fa77b3de582ad26eb45139\"},\"renterRollover\":\"3597839704000000000000000000000000\",\"hostRollover\":\"3099140907000000000000000000000000\",\"renterSignature\":\"4906067918dc6e7951c4e42b5b5bc1c3a3e3f02bddd10bf981275ccd0e8a5a067d35d4b5c2115256454490fed011e5c11ea35cb378eb6ada168b65d614515a44\",\"hostSignature\":\"5414a4c1e32f17b275148f3935a53b30cc30d1a0ff43e88f71e8308209282528a2942779638a6e2329314101e5ea79627d98b0f1b19830bf0ea89f670f7798bf\"}";
1641
-
1642
- let fcr: FileContractRenewal = serde_json::from_str(s).unwrap();
1643
- let sig_hash = fcr.sig_hash(&cs);
1644
- assert_eq!(
1645
- hex::encode(sig_hash),
1646
- "f20822926c53eac2bf91d54e5b39f7de76739226b131448e5508f077ebbccf3b"
1647
- );
1648
- }
1649
-
1650
- #[test]
1651
- fn test_input_sig_hash() {
1652
- let cs = test_chain_state();
1653
- let s = "{\"siacoinInputs\":[{\"parent\":{\"id\":\"af88fb86ace93d500549ad5d3ccae9d75184c932d8b9f6b39b22dc1beb19cb2b\",\"stateElement\":{\"leafIndex\":17247661272366213787,\"merkleProof\":[\"419c0046c59819e4541a3810134dac5c975eb61cb12382c0fbad713257a9efd3\"]},\"siacoinOutput\":{\"value\":\"3088711336000000000000000000000000\",\"address\":\"c6b4adae9284845d1075bc33a68d281bf02ed406206f58a50d13191af7b6f617933bf733cd42\"},\"maturityHeight\":0},\"satisfiedPolicy\":{\"policy\":{\"type\":\"pk\",\"policy\":\"ed25519:e655ec65952c4953c904c9ee16961dfb02e8689f1f82fcfd9e387c8ea1104a2b\"},\"signatures\":[\"7ba834e5e33ca4ac7ad7dbd2b3bd42c7ae62db25263feb2a51777f5c8d5569b1eb28e349544689d3f96242a66d33dcdebeab4e5fa30c906fd2caaf83c16f3bfe\"]}}],\"siacoinOutputs\":[{\"value\":\"1597553234000000000000000000000000\",\"address\":\"bc99db1f50a653604797de23d535c9fbf73b493ab70089c7716c1e5c5fc2d0a578575d367eb0\"}],\"fileContracts\":[{\"capacity\":10874342648285931495,\"filesize\":13810078500867640614,\"fileMerkleRoot\":\"424b9304a9fccf94945ef14c6377060be59fb7d58ac8c952d67be05c67d863a2\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"1556050983000000000000000000000000\",\"address\":\"4505c61036d22e5075c676ea5906a645eb1cfa9a6a53d933ecfa198654b7d3f0fe74bdfbdaef\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":18446744073709551615,\"renterSignature\":\"84d8091517ff09f11df171b21a1414200ea7074664c7e27d9de13c44bbb6cbc0de6de5783c6955065a77035bb2d92974fb5f11aa0dae9ac50dbddbb17d63d7fc\",\"hostSignature\":\"2fad832ddb5d6b11893851df4ecbd9a4b512a7a425dda67ac0da1604a0e8781d04e29cef928f31be706e6fc81089048ea87366449450e3da941a0b04487582f2\"}],\"fileContractRevisions\":[{\"parent\":{\"id\":\"22e9e60d81478b36fc44ee67b8d8ba874d196fc6e9c56bfacd5fcecdde39b736\",\"stateElement\":{\"leafIndex\":12023426945600912207,\"merkleProof\":[\"a0efcbdbe1f8e1b4fb6615eccac5948303d5a2c5afedda0baf658e5bbe41896e\"]},\"v2FileContract\":{\"capacity\":10776473623907646048,\"filesize\":7973631990249562263,\"fileMerkleRoot\":\"acd56f68224de7828076cb53f3476413819c8c78dde2461422c5a96644fba623\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"842083234000000000000000000000000\",\"address\":\"150084c56cd2bc38e80220eb69a485b5c298ee3c9f7fcc046c6b975ea8fb70f9098afe1ad85b\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":18446744073709551615,\"renterSignature\":\"94dd2555507b81cfd927b36891a9b37465c00cb46a61d96ede5f760f1c5a5cadabb8c7719adb5cb088eec92d9a9c52497973fc2b5d0c54a2dfa04e35490e25b5\",\"hostSignature\":\"d66133988a412e5542535e9a6c3815396c46020a4ad693074d6681049b39c438af9dd395478566e193263e8acfa915848ec23ff47a95eca51bac4ede2a92f634\"}},\"revision\":{\"capacity\":6034084714889303577,\"filesize\":12020548219123782123,\"fileMerkleRoot\":\"2ce9c19107be51ab776221d61300c6c1aa32c2195246473eb15d7db12ec0943f\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"2247488091000000000000000000000000\",\"address\":\"6f7add99e7eba38429b101ff31190aa3a148c0087a3ad775790a8e01a90f71a94ca9ba2ffc71\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":18446744073709551615,\"renterSignature\":\"7fb556fef4bfea24f7b9472b1b9874be600795da4535107d3910085a3e34c5818a60bd77d0bcbd92e6dbec604f1b67d827ba02072e83abfac217a2294157c53f\",\"hostSignature\":\"77664782e2c1dd42a3669f11f0519630561a4c0b48552c89bb74f79367f21fd73b6bc5ea112502f81bbc9e3df3b916158486c2e17145b95e5307ca56fb37fc6c\"}}],\"fileContractResolutions\":[{\"parent\":{\"id\":\"6b8527472e1143e07099e3f516f56ac2b46860f13652582b2abb6fffeac1f5d9\",\"stateElement\":{\"leafIndex\":14811616376775388856,\"merkleProof\":[\"bf4325ff8d463ba3bf62e9f697911a4bf8038971298440f4a2c5e010730ac594\"]},\"v2FileContract\":{\"capacity\":6642268570724229223,\"filesize\":15896577861535581162,\"fileMerkleRoot\":\"6e19255c03515dbbee1280f8e13e7378810243042a01a439849c0ddbc0fd7eac\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"2825432965000000000000000000000000\",\"address\":\"2ca7f5d7cbd79fbf4b5f2f5a4ead652342dd0413e39e9406b2935c53162d9347359d0477b320\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":18446744073709551615,\"renterSignature\":\"169330702f83d499de6bff18cc7c2474785e02b8101baf8427407e9f6cc3ee6e7768b7e6ef929a6510c1b0ac1c24eab8090af84c27c772c80201fe93da535e17\",\"hostSignature\":\"29bf20483727c327e36c3085a87d91ad3072ca82f5d62da1d9895980320ab7a65d133bb147d55bd97c9f5a36a85afbfb8d9209ac82afaca18df64054394f0f08\"}},\"type\":\"expiration\",\"resolution\":{}},{\"parent\":{\"id\":\"2dd1bedefe81f2914ddf9f61c9d714d134d0af7a75d1c1322474d5e8eea342f2\",\"stateElement\":{\"leafIndex\":11863728860462350395,\"merkleProof\":[\"91a391d6104f76e439580a90f56fec3c07d01ad5535315416243ae6d8e17289d\"]},\"v2FileContract\":{\"capacity\":3158332065060007910,\"filesize\":11561455863259225844,\"fileMerkleRoot\":\"b4db7aa14dc851a348e0981c3ed1161dc286bca85424da42609b3c12f5f31ee6\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"2522086295000000000000000000000000\",\"address\":\"36e4ed130d7a9f0cbcdd0ed6fa78738dcd9eb6e779fc7501dd06f7cf968ce215e33778f0c79e\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":18446744073709551615,\"renterSignature\":\"ff79f46439dd108ebe2c42434a11b916f7dee6f018798435b3c34a92ca121d3e21c0282d4efba4982a36e2cfe146e3c8ee31ba545911857a93d947faef543e2f\",\"hostSignature\":\"7f45f2f977e574ea980a0842f48d216b6680d129a98056cafa7f108487457bde8e0cd1cc5d74ba3187170f214115827bc961f0163203c479c3d4ab7e19f3d31f\"}},\"type\":\"storageProof\",\"resolution\":{\"proofIndex\":{\"id\":\"90da2d2ed68b716be7617b8c35c713ad66584a1dbf564cc44c09b6f3815e1d79\",\"stateElement\":{\"leafIndex\":1814794313179331469,\"merkleProof\":[\"8a3990c651140b9486c09559c54623a4e8ca5c2705a7de2b0b54de6d97e6d01d\"]},\"chainIndex\":{\"height\":17891680254001945312,\"id\":\"e5b6bf4a036b93d8a178ffe86ee209502a0ff3d45d2b3216052267b7a5561d21\"}},\"leaf\":\"c5e078423107b4d2c0ab10509404c525343e96eff45ea6353039194470aec04e3994d52cd2d9a6cbbd3709387207f59f063bec4e7266f6fa0c6dfcf7d7634a1c\",\"proof\":[\"f900e345a663fb6ec9eca5721a81e25fae111e50f38aeb76fd6258f2d4cecd86\"]}},{\"parent\":{\"id\":\"49d9f6a8cfae42cd9cc4d792b1799ab2752be164cd86ce5e474fe3731c31b492\",\"stateElement\":{\"leafIndex\":376572300431080610,\"merkleProof\":[\"b2945edc55afbc2344d201baaed373fc0a737c00216186c5e724c3e7d681a705\"]},\"v2FileContract\":{\"capacity\":14165001982102687892,\"filesize\":5514344128076756235,\"fileMerkleRoot\":\"3bcf704f911a925eea72629d71352e1f402fc7d3b632f0df6e203089a6fd9092\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"1548819653000000000000000000000000\",\"address\":\"c1f4c5d401041e4eb68455283ce6705f2dcdc5ac4d700f7dc233b13f91bbfa986aec255c62bb\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":18446744073709551615,\"renterSignature\":\"ac99ce31b11341a8835e2666eed317b0042d45ce6ccb52a11a3d2d6c7ec050f432ea8e1fef95b3481da64c5b2b3a772459db094a68d4a3cf52f2e928f3dd7b55\",\"hostSignature\":\"c8a097593157a24390c5fc77bed87c54355e03572ff2b49137801c51ac55ff092141dfb46505808fa97ee22e839d682f9de7f595896338ebf1c4e1885067747c\"}},\"type\":\"renewal\",\"resolution\":{\"finalRevision\":{\"capacity\":6539007356562521256,\"filesize\":17290867016333557028,\"fileMerkleRoot\":\"ebaa3f96d6572cc3caf3036468ddf52ef6fbfcc3eacef4cffd6eabcd43d1b91a\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"2415984205000000000000000000000000\",\"address\":\"1300755d91ac9d739e168f5e54eb2aba9aa0c29cc29142ab4babf0e92be83f17cde6a5ff4ed5\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":18446744073709551615,\"renterSignature\":\"a1489731bddba377854020ae706127938ce95c617d22db29b9f9aa331ee27dbfb625b67b3418647b40d4ab4f0075a69a10d66840a3cec4b3c86112ce7e648761\",\"hostSignature\":\"4181fc7c46f09d0124c365a1aeba76f906d99afb3f49d6637f54fc4e2746776a8f3aa343bc823c705c11a581a87ddb918d9bccec0cb2deb46aa4627cf5cf3e80\"},\"newContract\":{\"capacity\":2724141139581307456,\"filesize\":2682841277844293416,\"fileMerkleRoot\":\"62ea0682d909fb36df6557ea2d8174b20db44c0ad1ed692b7b11b40893147e36\",\"proofHeight\":0,\"expirationHeight\":0,\"renterOutput\":{\"value\":\"4004958805000000000000000000000000\",\"address\":\"cc6a403530f6da43fb262723a9536a96666bd74075d64dd7d0eb65df5c494c24b115cdee00c5\"},\"hostOutput\":{\"value\":\"0\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"},\"missedHostValue\":\"0\",\"totalCollateral\":\"0\",\"renterPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"hostPublicKey\":\"ed25519:0000000000000000000000000000000000000000000000000000000000000000\",\"revisionNumber\":0,\"renterSignature\":\"ed98b9027f795d3eeafac4928963a55189066fa8a447fd70041d498d6d1072ad5247d36cd657e1f5163889f14591e89159daca5c8c3e645af9b26ac782990cfc\",\"hostSignature\":\"841fff506bfbdc5c9f6dcda6de472dd6bc7e73e5f0974e0bc979fdcc24059246590ef2f6af2b75a786c27f78f43a27e5da91b320736a5cbb7bb15be8375e372e\"},\"renterRollover\":\"3037399761000000000000000000000000\",\"hostRollover\":\"2211277679000000000000000000000000\",\"renterSignature\":\"745f21dae4f1fba04c2d9b09ae69a9e5f096cf26707447fb3b1c17e486b71589b7dc5fda40ef08eac2122b51606b2fbe84211c5f6507631456ac0dd0ee164ef3\",\"hostSignature\":\"0510b572606c3144a4472538b722c2420165efda406b92b74457459d5c5b90a622490d7a70bd7e5e40b031fadd9d3edd90c13226869d8d358512aab5b0145a11\"}}],\"attestations\":[{\"publicKey\":\"ed25519:269ba257f490941f5fcfde5313e326fa205a1a8d91715d91f892581d7282bf21\",\"key\":\"629109f07df18f46\",\"value\":\"Adg+GFWhwVo=\",\"signature\":\"d44eb9a001803f52814adae65da4dc195d760e7afb00b9593716e54a116db7b98ad8e774e101098d31abca3b389a01a08438d7a33508f1f665d2d48f4524509d\"}],\"minerFee\":\"2208027072000000000000000000000000\"}";
1654
- let txn: Transaction = serde_json::from_str(s).unwrap();
1655
- let sig_hash = txn.input_sig_hash(&cs);
1656
- assert_eq!(
1657
- hex::encode(sig_hash),
1658
- "aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422"
1659
- );
1660
- }
1661
-
1662
- #[test]
1663
- fn test_transaction_serialization() {
1664
- let txn = Transaction {
1665
- siacoin_inputs: vec![],
1666
- siacoin_outputs: vec![],
1667
- siafund_inputs: vec![],
1668
- siafund_outputs: vec![],
1669
- file_contracts: vec![],
1670
- file_contract_revisions: vec![],
1671
- file_contract_resolutions: vec![],
1672
- attestations: vec![],
1673
- new_foundation_address: None,
1674
- arbitrary_data: vec![],
1675
- miner_fee: Currency::new(0),
1676
- };
1677
- test_serialize_json(&txn, "{\"minerFee\":\"0\"}");
1678
- test_serialize(&txn, "020000000000000000");
1679
-
1680
- let txn = Transaction {
1681
- siacoin_inputs: vec![SiacoinInput {
1682
- parent: SiacoinElement{
1683
- id: siacoin_id!("aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422"),
1684
- state_element: StateElement{
1685
- leaf_index: 12312413,
1686
- merkle_proof: vec![hash_256!("aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422")]
1687
- },
1688
- siacoin_output: SiacoinOutput{
1689
- value: Currency::new(100),
1690
- address: address!("8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8cdf32abee86f0")
1691
- },
1692
- maturity_height: 0,
1693
- },
1694
- satisfied_policy: SatisfiedPolicy {
1695
- policy: SpendPolicy::public_key(public_key!("ed25519:aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422")),
1696
- signatures: vec![
1697
- "aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422".parse().unwrap()
1698
- ],
1699
- preimages: vec![],
1700
- },
1701
- },
1702
- ],
1703
- siacoin_outputs: vec![SiacoinOutput {
1704
- value: Currency::new(100),
1705
- address: address!("8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8cdf32abee86f0")
1706
- }],
1707
- siafund_inputs: vec![],
1708
- siafund_outputs: vec![],
1709
- file_contracts: vec![],
1710
- file_contract_revisions: vec![],
1711
- file_contract_resolutions: vec![],
1712
- attestations: vec![],
1713
- new_foundation_address: None,
1714
- arbitrary_data: vec![],
1715
- miner_fee: Currency::new(123581),
1716
- };
1717
- test_serialize(
1718
- &txn,
1719
- "02030400000000000001000000000000005ddfbb00000000000100000000000000aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422640000000000000000000000000000008fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c00000000000000000103aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f14220100000000000000aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f142200000000000000000100000000000000640000000000000000000000000000008fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8cbde20100000000000000000000000000",
1720
- );
1721
- test_serialize_json(
1722
- &txn,
1723
- "{\"siacoinInputs\":[{\"parent\":{\"stateElement\":{\"leafIndex\":12312413,\"merkleProof\":[\"aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422\"]},\"id\":\"aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422\",\"siacoinOutput\":{\"value\":\"100\",\"address\":\"8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8cdf32abee86f0\"},\"maturityHeight\":0},\"satisfiedPolicy\":{\"policy\":{\"type\":\"pk\",\"policy\":\"ed25519:aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422\"},\"signatures\":[\"aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422aefb1120a3f69fc8293caeb0bd36b4637d6fdf12f2f60494a2875358552f1422\"]}}],\"siacoinOutputs\":[{\"value\":\"100\",\"address\":\"8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8cdf32abee86f0\"}],\"minerFee\":\"123581\"}",
1724
- );
1725
- }
1726
- }