diff --git a/.changeset/add_id_derivation_helpers_to_transactions_blocks_and_siafund_claims.md b/.changeset/add_id_derivation_helpers_to_transactions_blocks_and_siafund_claims.md new file mode 100644 index 0000000..a094d74 --- /dev/null +++ b/.changeset/add_id_derivation_helpers_to_transactions_blocks_and_siafund_claims.md @@ -0,0 +1,5 @@ +--- +sia_sdk: minor +--- + +# Add ID derivation helpers to transactions, blocks, and siafund claims diff --git a/sia/src/consensus.rs b/sia/src/consensus.rs index c437385..33e3f42 100644 --- a/sia/src/consensus.rs +++ b/sia/src/consensus.rs @@ -523,14 +523,13 @@ impl ChainState { 1009 } - pub fn max_block_weight() -> u64 { + pub fn max_block_weight(&self) -> u64 { 2_000_000 } } #[cfg(test)] mod tests { - use crate::{block_id, hash_256}; use super::*; @@ -596,14 +595,14 @@ mod tests { attestations: 0, }; - const EMPTY_JSON_STR: &'static str = "{\"index\":{\"height\":0,\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\"},\"prevTimestamps\":[\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\"],\"depth\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"childTarget\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"siafundPool\":\"0\",\"oakTime\":0,\"oakTarget\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"foundationPrimaryAddress\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\",\"foundationFailsafeAddress\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\",\"totalWork\":\"0\",\"difficulty\":\"0\",\"oakWork\":\"0\",\"elements\":{\"numLeaves\":0,\"trees\":[]},\"attestations\":0}"; + const EMPTY_JSON_STR: &str = "{\"index\":{\"height\":0,\"id\":\"0000000000000000000000000000000000000000000000000000000000000000\"},\"prevTimestamps\":[\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\",\"1970-01-01T00:00:00Z\"],\"depth\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"childTarget\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"siafundPool\":\"0\",\"oakTime\":0,\"oakTarget\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"foundationPrimaryAddress\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\",\"foundationFailsafeAddress\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\",\"totalWork\":\"0\",\"difficulty\":\"0\",\"oakWork\":\"0\",\"elements\":{\"numLeaves\":0,\"trees\":[]},\"attestations\":0}"; let serialized = serde_json::to_string(&s).unwrap(); assert_eq!(EMPTY_JSON_STR, serialized); let deserialized: State = serde_json::from_str(&serialized).unwrap(); assert_eq!(s, deserialized); - const EMPTY_BINARY_STR: &'static str = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + const EMPTY_BINARY_STR: &str = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; let mut serialized = Vec::new(); s.encode(&mut serialized).unwrap(); @@ -783,14 +782,14 @@ mod tests { attestations: 4796228701811883082, }; - const JSON_STR: &'static str = "{\"index\":{\"height\":16173070238323073115,\"id\":\"54b6800181215b654a2b64e8a0f39da6d5ad20f4e6eda87d50d36e93efd9cdb9\"},\"prevTimestamps\":[\"2167-03-19T00:08:40Z\",\"1971-03-30T15:40:44Z\",\"2226-11-13T03:51:30Z\",\"2013-09-10T22:07:20Z\",\"2230-05-19T03:13:07Z\",\"1983-10-28T03:37:21Z\",\"2068-03-31T17:25:10Z\",\"2159-06-30T01:46:49Z\",\"2089-05-03T06:45:50Z\",\"2073-02-27T08:01:11Z\",\"2005-07-10T18:50:37Z\"],\"depth\":\"fb66f6dd0517bd80a57c6fc1dd186eeb25a5f7dc550adc94a996731734f4a478\",\"childTarget\":\"188d65bc61f7398757be167c70139bc79e2f387551bd0338b81f3938850033c2\",\"siafundPool\":\"184937863921143879963732603265618430015\",\"oakTime\":5097318764767379519,\"oakTarget\":\"5e7e960e017d5772f3341bd8d80fc797de245c760a3f9e84f4da66f9e0ee95aa\",\"foundationPrimaryAddress\":\"95ae9eb00188ade3367e57e5bdc522a16e95a8d28e1b940d2d128273aa7a833001a060dec431\",\"foundationFailsafeAddress\":\"cfb49736296ae52965fd7d66d55720eeadfc2be586db65699050bce175c56056d3fbc1803e15\",\"totalWork\":\"74729819229046869798018345563024899883189146032533830356652983039509219541660\",\"difficulty\":\"65194889020289389878379369533805235500859175566680960159551424936807420310662\",\"oakWork\":\"57256974569838769713335634640292932580615837804690422146878608831130432685755\",\"elements\":{\"numLeaves\":4899977171010125798,\"trees\":[\"78a9fabda865dafcaf474d48bdb1272595513cf92290917392ff58ca8bea591a\",\"e6a5ea278d90592e0518fbf2e83f41507486fe57e8e4ffbe152f13250df696bf\",\"2488cae3f7046f8b04aec217a09358db22d8ae36f883d1ccae9382edca79c54e\",\"e498f1adbe88c58bc9dabf487437b8d191a78fbb3d8cfe19a4c1759ae232b4f4\",\"96130e35228422970057745ef4b92d285434c25187c44110922554d0ae040678\",\"44f29b39d6e4f509d5d41834db4fd6a831ccca33bb46185a5ad01f2789581337\",\"75f0b42f9d291c4ff4e57f403893e0ca18fdc64f0723e0f29b6aeed834db1ac2\",\"4ce129d69c69971497c556d9eeec0de8c1dd9cc4b0750be9fffd9ec3226ce7a3\",\"f3321bf48aed89100db44b3080f3f350d10b6de213527b19ad57bdd1cd47576a\",\"724c8bf4c8459625190ae18b2fc1d9353d2d3b34c80d4d4fbcd48258c9a11c97\",\"062b2371de9dfad15931a1e72c46afe492ad697447680ea43300ed516bcc2742\",\"b23ca0a83b0367755e2c53c1f7ed9e6d372c220ae0f344082cf5d52c40287893\",\"9b1b446dd599fd5dab08e83738b92651d8aaa7be072db313d237c68ce1094ea1\",\"a03c962c184055ccbf7a42c9a13a0d4c38125535a830832a6fff3029d6deada3\",\"df5d9e1e3a220d2429f9064adecb86ecae916619c93e17d237b5972692e558fd\",\"2d6315b7a91d62bd31e4738259f56f58075bd14ee2f1e2625738f506a7564176\",\"26b1d48ab8c3f0707bd5afdf4a3ef757abc9b6a0be75b8a3cecbcd5994473a72\",\"f897c92aca8d6ef46a41a3a50aff0527bd09be029355d28c2360ec9cb309b1ae\",\"f80ff7cbcad8c465278a59588a3a0d000cc3130e96fb56d257229c1a50d93125\",\"7a84f42433ecd9352e2ffd8bdc8556c87ec93697cf4c4873d4ab51d2b85c44c1\",\"00c03e0af90a26d0a4bb4b243f99b2d361de2412d82f357f6224eceb2f19c142\",\"e0a8f77abd726e928580656d7ab49dc276603e936e04b9caf53a2a27338e3cd1\",\"e376ebd2f0c93013cf6c856fb76e7b60e64a300a9a4b839844074cac4da42b8d\",\"5fcc77f29cfdb51aac9fff250e1ee7607457ce5a280e946150931d793272593a\",\"ad34b2dce6a7136584c5ffea74c66e5613593dddac9eb666ff6a6aef42386968\",\"3d1afa6b931fea014211bb6b08d9508389dd0a9c47a25670ca110bcc8ce8ead1\",\"df427b938f6ef07cd67da1ab11ad8fb4e6b0a97c03325c1fc8b1c3b0c4b8f7f4\",\"8c3d435fdb6ee44e26155c116a86f4dc2b54b05becb08777a63e1d1ad7c3cbc2\",\"11671f5bd2856de1b4925ee0b82f9cda6179db132c9930431d26f0ccdbb8a822\",\"19dcd3ac59669e10420b36d4e588206ae123a0c8ae64b20e1ede697efc556291\",\"65542a8b2c1bca8d78d6517357853c1d54f6b53f04a8327f28ae2d5d022c5597\"]},\"attestations\":4796228701811883082}"; + const JSON_STR: &str = "{\"index\":{\"height\":16173070238323073115,\"id\":\"54b6800181215b654a2b64e8a0f39da6d5ad20f4e6eda87d50d36e93efd9cdb9\"},\"prevTimestamps\":[\"2167-03-19T00:08:40Z\",\"1971-03-30T15:40:44Z\",\"2226-11-13T03:51:30Z\",\"2013-09-10T22:07:20Z\",\"2230-05-19T03:13:07Z\",\"1983-10-28T03:37:21Z\",\"2068-03-31T17:25:10Z\",\"2159-06-30T01:46:49Z\",\"2089-05-03T06:45:50Z\",\"2073-02-27T08:01:11Z\",\"2005-07-10T18:50:37Z\"],\"depth\":\"fb66f6dd0517bd80a57c6fc1dd186eeb25a5f7dc550adc94a996731734f4a478\",\"childTarget\":\"188d65bc61f7398757be167c70139bc79e2f387551bd0338b81f3938850033c2\",\"siafundPool\":\"184937863921143879963732603265618430015\",\"oakTime\":5097318764767379519,\"oakTarget\":\"5e7e960e017d5772f3341bd8d80fc797de245c760a3f9e84f4da66f9e0ee95aa\",\"foundationPrimaryAddress\":\"95ae9eb00188ade3367e57e5bdc522a16e95a8d28e1b940d2d128273aa7a833001a060dec431\",\"foundationFailsafeAddress\":\"cfb49736296ae52965fd7d66d55720eeadfc2be586db65699050bce175c56056d3fbc1803e15\",\"totalWork\":\"74729819229046869798018345563024899883189146032533830356652983039509219541660\",\"difficulty\":\"65194889020289389878379369533805235500859175566680960159551424936807420310662\",\"oakWork\":\"57256974569838769713335634640292932580615837804690422146878608831130432685755\",\"elements\":{\"numLeaves\":4899977171010125798,\"trees\":[\"78a9fabda865dafcaf474d48bdb1272595513cf92290917392ff58ca8bea591a\",\"e6a5ea278d90592e0518fbf2e83f41507486fe57e8e4ffbe152f13250df696bf\",\"2488cae3f7046f8b04aec217a09358db22d8ae36f883d1ccae9382edca79c54e\",\"e498f1adbe88c58bc9dabf487437b8d191a78fbb3d8cfe19a4c1759ae232b4f4\",\"96130e35228422970057745ef4b92d285434c25187c44110922554d0ae040678\",\"44f29b39d6e4f509d5d41834db4fd6a831ccca33bb46185a5ad01f2789581337\",\"75f0b42f9d291c4ff4e57f403893e0ca18fdc64f0723e0f29b6aeed834db1ac2\",\"4ce129d69c69971497c556d9eeec0de8c1dd9cc4b0750be9fffd9ec3226ce7a3\",\"f3321bf48aed89100db44b3080f3f350d10b6de213527b19ad57bdd1cd47576a\",\"724c8bf4c8459625190ae18b2fc1d9353d2d3b34c80d4d4fbcd48258c9a11c97\",\"062b2371de9dfad15931a1e72c46afe492ad697447680ea43300ed516bcc2742\",\"b23ca0a83b0367755e2c53c1f7ed9e6d372c220ae0f344082cf5d52c40287893\",\"9b1b446dd599fd5dab08e83738b92651d8aaa7be072db313d237c68ce1094ea1\",\"a03c962c184055ccbf7a42c9a13a0d4c38125535a830832a6fff3029d6deada3\",\"df5d9e1e3a220d2429f9064adecb86ecae916619c93e17d237b5972692e558fd\",\"2d6315b7a91d62bd31e4738259f56f58075bd14ee2f1e2625738f506a7564176\",\"26b1d48ab8c3f0707bd5afdf4a3ef757abc9b6a0be75b8a3cecbcd5994473a72\",\"f897c92aca8d6ef46a41a3a50aff0527bd09be029355d28c2360ec9cb309b1ae\",\"f80ff7cbcad8c465278a59588a3a0d000cc3130e96fb56d257229c1a50d93125\",\"7a84f42433ecd9352e2ffd8bdc8556c87ec93697cf4c4873d4ab51d2b85c44c1\",\"00c03e0af90a26d0a4bb4b243f99b2d361de2412d82f357f6224eceb2f19c142\",\"e0a8f77abd726e928580656d7ab49dc276603e936e04b9caf53a2a27338e3cd1\",\"e376ebd2f0c93013cf6c856fb76e7b60e64a300a9a4b839844074cac4da42b8d\",\"5fcc77f29cfdb51aac9fff250e1ee7607457ce5a280e946150931d793272593a\",\"ad34b2dce6a7136584c5ffea74c66e5613593dddac9eb666ff6a6aef42386968\",\"3d1afa6b931fea014211bb6b08d9508389dd0a9c47a25670ca110bcc8ce8ead1\",\"df427b938f6ef07cd67da1ab11ad8fb4e6b0a97c03325c1fc8b1c3b0c4b8f7f4\",\"8c3d435fdb6ee44e26155c116a86f4dc2b54b05becb08777a63e1d1ad7c3cbc2\",\"11671f5bd2856de1b4925ee0b82f9cda6179db132c9930431d26f0ccdbb8a822\",\"19dcd3ac59669e10420b36d4e588206ae123a0c8ae64b20e1ede697efc556291\",\"65542a8b2c1bca8d78d6517357853c1d54f6b53f04a8327f28ae2d5d022c5597\"]},\"attestations\":4796228701811883082}"; let serialized = serde_json::to_string(&s).unwrap(); assert_eq!(JSON_STR, serialized); let deserialized: State = serde_json::from_str(&serialized).unwrap(); assert_eq!(s, deserialized); - const BINARY_STR: &'static str = "5b60b072b14972e054b6800181215b654a2b64e8a0f39da6d5ad20f4e6eda87d50d36e93efd9cdb9086ff17201000000fc13560200000000420d26e30100000018982f5200000000c378c1e901000000f146ff1900000000f6f6ccb80000000089116d64010000009eb377e000000000c79509c200000000fd6dd14200000000fb66f6dd0517bd80a57c6fc1dd186eeb25a5f7dc550adc94a996731734f4a478188d65bc61f7398757be167c70139bc79e2f387551bd0338b81f3938850033c23f48064ca312d68970452ce1abbc218b3f80e4e86850bd465e7e960e017d5772f3341bd8d80fc797de245c760a3f9e84f4da66f9e0ee95aa95ae9eb00188ade3367e57e5bdc522a16e95a8d28e1b940d2d128273aa7a8330cfb49736296ae52965fd7d66d55720eeadfc2be586db65699050bce175c56056a537942b3dcc3fb364ca2cdd33416f2ad78e92cd50081c59c5c9f67c9a64829c9022ffe17973176b934cf5ab04186591c97b2b86f290de9dace84dac6fe2b4867e964c967126699e34e7e3114292eca3140a6f0a94e76e39c047b064bfdbc6bbe6ff949d4637004478a9fabda865dafcaf474d48bdb1272595513cf92290917392ff58ca8bea591ae6a5ea278d90592e0518fbf2e83f41507486fe57e8e4ffbe152f13250df696bf2488cae3f7046f8b04aec217a09358db22d8ae36f883d1ccae9382edca79c54ee498f1adbe88c58bc9dabf487437b8d191a78fbb3d8cfe19a4c1759ae232b4f496130e35228422970057745ef4b92d285434c25187c44110922554d0ae04067844f29b39d6e4f509d5d41834db4fd6a831ccca33bb46185a5ad01f278958133775f0b42f9d291c4ff4e57f403893e0ca18fdc64f0723e0f29b6aeed834db1ac24ce129d69c69971497c556d9eeec0de8c1dd9cc4b0750be9fffd9ec3226ce7a3f3321bf48aed89100db44b3080f3f350d10b6de213527b19ad57bdd1cd47576a724c8bf4c8459625190ae18b2fc1d9353d2d3b34c80d4d4fbcd48258c9a11c97062b2371de9dfad15931a1e72c46afe492ad697447680ea43300ed516bcc2742b23ca0a83b0367755e2c53c1f7ed9e6d372c220ae0f344082cf5d52c402878939b1b446dd599fd5dab08e83738b92651d8aaa7be072db313d237c68ce1094ea1a03c962c184055ccbf7a42c9a13a0d4c38125535a830832a6fff3029d6deada3df5d9e1e3a220d2429f9064adecb86ecae916619c93e17d237b5972692e558fd2d6315b7a91d62bd31e4738259f56f58075bd14ee2f1e2625738f506a756417626b1d48ab8c3f0707bd5afdf4a3ef757abc9b6a0be75b8a3cecbcd5994473a72f897c92aca8d6ef46a41a3a50aff0527bd09be029355d28c2360ec9cb309b1aef80ff7cbcad8c465278a59588a3a0d000cc3130e96fb56d257229c1a50d931257a84f42433ecd9352e2ffd8bdc8556c87ec93697cf4c4873d4ab51d2b85c44c100c03e0af90a26d0a4bb4b243f99b2d361de2412d82f357f6224eceb2f19c142e0a8f77abd726e928580656d7ab49dc276603e936e04b9caf53a2a27338e3cd1e376ebd2f0c93013cf6c856fb76e7b60e64a300a9a4b839844074cac4da42b8d5fcc77f29cfdb51aac9fff250e1ee7607457ce5a280e946150931d793272593aad34b2dce6a7136584c5ffea74c66e5613593dddac9eb666ff6a6aef423869683d1afa6b931fea014211bb6b08d9508389dd0a9c47a25670ca110bcc8ce8ead1df427b938f6ef07cd67da1ab11ad8fb4e6b0a97c03325c1fc8b1c3b0c4b8f7f48c3d435fdb6ee44e26155c116a86f4dc2b54b05becb08777a63e1d1ad7c3cbc211671f5bd2856de1b4925ee0b82f9cda6179db132c9930431d26f0ccdbb8a82219dcd3ac59669e10420b36d4e588206ae123a0c8ae64b20e1ede697efc55629165542a8b2c1bca8d78d6517357853c1d54f6b53f04a8327f28ae2d5d022c55974abc07c197a08f42"; + const BINARY_STR: &str = "5b60b072b14972e054b6800181215b654a2b64e8a0f39da6d5ad20f4e6eda87d50d36e93efd9cdb9086ff17201000000fc13560200000000420d26e30100000018982f5200000000c378c1e901000000f146ff1900000000f6f6ccb80000000089116d64010000009eb377e000000000c79509c200000000fd6dd14200000000fb66f6dd0517bd80a57c6fc1dd186eeb25a5f7dc550adc94a996731734f4a478188d65bc61f7398757be167c70139bc79e2f387551bd0338b81f3938850033c23f48064ca312d68970452ce1abbc218b3f80e4e86850bd465e7e960e017d5772f3341bd8d80fc797de245c760a3f9e84f4da66f9e0ee95aa95ae9eb00188ade3367e57e5bdc522a16e95a8d28e1b940d2d128273aa7a8330cfb49736296ae52965fd7d66d55720eeadfc2be586db65699050bce175c56056a537942b3dcc3fb364ca2cdd33416f2ad78e92cd50081c59c5c9f67c9a64829c9022ffe17973176b934cf5ab04186591c97b2b86f290de9dace84dac6fe2b4867e964c967126699e34e7e3114292eca3140a6f0a94e76e39c047b064bfdbc6bbe6ff949d4637004478a9fabda865dafcaf474d48bdb1272595513cf92290917392ff58ca8bea591ae6a5ea278d90592e0518fbf2e83f41507486fe57e8e4ffbe152f13250df696bf2488cae3f7046f8b04aec217a09358db22d8ae36f883d1ccae9382edca79c54ee498f1adbe88c58bc9dabf487437b8d191a78fbb3d8cfe19a4c1759ae232b4f496130e35228422970057745ef4b92d285434c25187c44110922554d0ae04067844f29b39d6e4f509d5d41834db4fd6a831ccca33bb46185a5ad01f278958133775f0b42f9d291c4ff4e57f403893e0ca18fdc64f0723e0f29b6aeed834db1ac24ce129d69c69971497c556d9eeec0de8c1dd9cc4b0750be9fffd9ec3226ce7a3f3321bf48aed89100db44b3080f3f350d10b6de213527b19ad57bdd1cd47576a724c8bf4c8459625190ae18b2fc1d9353d2d3b34c80d4d4fbcd48258c9a11c97062b2371de9dfad15931a1e72c46afe492ad697447680ea43300ed516bcc2742b23ca0a83b0367755e2c53c1f7ed9e6d372c220ae0f344082cf5d52c402878939b1b446dd599fd5dab08e83738b92651d8aaa7be072db313d237c68ce1094ea1a03c962c184055ccbf7a42c9a13a0d4c38125535a830832a6fff3029d6deada3df5d9e1e3a220d2429f9064adecb86ecae916619c93e17d237b5972692e558fd2d6315b7a91d62bd31e4738259f56f58075bd14ee2f1e2625738f506a756417626b1d48ab8c3f0707bd5afdf4a3ef757abc9b6a0be75b8a3cecbcd5994473a72f897c92aca8d6ef46a41a3a50aff0527bd09be029355d28c2360ec9cb309b1aef80ff7cbcad8c465278a59588a3a0d000cc3130e96fb56d257229c1a50d931257a84f42433ecd9352e2ffd8bdc8556c87ec93697cf4c4873d4ab51d2b85c44c100c03e0af90a26d0a4bb4b243f99b2d361de2412d82f357f6224eceb2f19c142e0a8f77abd726e928580656d7ab49dc276603e936e04b9caf53a2a27338e3cd1e376ebd2f0c93013cf6c856fb76e7b60e64a300a9a4b839844074cac4da42b8d5fcc77f29cfdb51aac9fff250e1ee7607457ce5a280e946150931d793272593aad34b2dce6a7136584c5ffea74c66e5613593dddac9eb666ff6a6aef423869683d1afa6b931fea014211bb6b08d9508389dd0a9c47a25670ca110bcc8ce8ead1df427b938f6ef07cd67da1ab11ad8fb4e6b0a97c03325c1fc8b1c3b0c4b8f7f48c3d435fdb6ee44e26155c116a86f4dc2b54b05becb08777a63e1d1ad7c3cbc211671f5bd2856de1b4925ee0b82f9cda6179db132c9930431d26f0ccdbb8a82219dcd3ac59669e10420b36d4e588206ae123a0c8ae64b20e1ede697efc55629165542a8b2c1bca8d78d6517357853c1d54f6b53f04a8327f28ae2d5d022c55974abc07c197a08f42"; let mut serialized = Vec::new(); s.encode(&mut serialized).unwrap(); diff --git a/sia/src/signing.rs b/sia/src/signing.rs index e6aa891..5a41db7 100644 --- a/sia/src/signing.rs +++ b/sia/src/signing.rs @@ -16,10 +16,7 @@ impl PublicKey { impl Serialize for PublicKey { fn serialize(&self, serializer: S) -> Result { - String::serialize( - &format!("{}{}", Self::PREFIX, &self.to_string()), - serializer, - ) + String::serialize(&self.to_string(), serializer) } } @@ -41,7 +38,7 @@ impl<'de> Deserialize<'de> for PublicKey { impl fmt::Display for PublicKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - hex::encode(self.0).fmt(f) + write!(f, "{}{}", Self::PREFIX, hex::encode(self.0)) } } diff --git a/sia/src/types/common.rs b/sia/src/types/common.rs index c999aa5..de8e37f 100644 --- a/sia/src/types/common.rs +++ b/sia/src/types/common.rs @@ -12,13 +12,139 @@ use crate::macros::impl_hash_id; use crate::types::currency::Currency; use crate::types::v1; +use super::{specifier, Specifier}; + impl_hash_id!(Hash256); -impl_hash_id!(BlockID); impl_hash_id!(SiacoinOutputID); +impl_hash_id!(AttestationID); + impl_hash_id!(SiafundOutputID); -impl_hash_id!(FileContractID); + +impl SiafundOutputID { + /// claim_output_id returns the SiacoinOutputID for the claim output of the siafund output + pub fn claim_output_id(&self) -> SiacoinOutputID { + let mut state = Params::new().hash_length(32).to_state(); + state.update(self.as_ref()); + state.finalize().into() + } + + pub fn v2_claim_output_id(&self) -> SiacoinOutputID { + let mut state = Params::new().hash_length(32).to_state(); + state.update(b"sia/id/v2siacoinclaimoutput|"); + state.update(self.as_ref()); + state.finalize().into() + } +} + +impl_hash_id!(BlockID); + +impl BlockID { + const FOUNDATION_OUTPUT_ID_PREFIX: Specifier = specifier!("foundation"); + + pub fn foundation_output_id(&self) -> SiacoinOutputID { + let mut state = Params::new().hash_length(32).to_state(); + state.update(self.as_ref()); + state.update(Self::FOUNDATION_OUTPUT_ID_PREFIX.as_bytes()); + state.finalize().into() + } + + pub fn miner_output_id(&self, i: usize) -> SiacoinOutputID { + let mut state = Params::new().hash_length(32).to_state(); + state.update(self.as_ref()); + state.update(&(i as u64).to_le_bytes()); + state.finalize().into() + } +} + impl_hash_id!(TransactionID); -impl_hash_id!(AttestationID); + +impl TransactionID { + const V2_SIACOIN_OUTPUT_PREFIX: &[u8] = b"sia/id/siacoinoutput|"; + const V2_SIAFUND_OUTPUT_PREFIX: &[u8] = b"sia/id/siafundoutput|"; + const V2_FILE_CONTRACT_PREFIX: &[u8] = b"sia/id/filecontract|"; + const V2_ATTESTATION_PREFIX: &[u8] = b"sia/id/attestation|"; + + fn derive_v2_child_id>(&self, prefix: &[u8], i: usize) -> T { + let mut state = Params::new().hash_length(32).to_state(); + state.update(prefix.as_ref()); + state.update(self.as_ref()); + state.update(&(i as u64).to_le_bytes()); + state.finalize().into() + } + + /// v2_siacoin_output_id returns the SiacoinOutputID for the i-th siacoin output of the V2 transaction + pub fn v2_siacoin_output_id(&self, i: usize) -> SiacoinOutputID { + self.derive_v2_child_id(Self::V2_SIACOIN_OUTPUT_PREFIX, i) + } + + /// v2_siafund_output_id returns the SiafundOutputID for the i-th siafund output of the V2 transaction + pub fn v2_siafund_output_id(&self, i: usize) -> SiafundOutputID { + self.derive_v2_child_id(Self::V2_SIAFUND_OUTPUT_PREFIX, i) + } + + /// v2_file_contract_id returns the FileContractID for the i-th file contract of the V2 transaction + pub fn v2_file_contract_id(&self, i: usize) -> FileContractID { + self.derive_v2_child_id(Self::V2_FILE_CONTRACT_PREFIX, i) + } + + /// v2_attestation_id returns the AttestationID for the i-th attestation of the V2 transaction + pub fn v2_attestation_id(&self, i: usize) -> AttestationID { + self.derive_v2_child_id(Self::V2_ATTESTATION_PREFIX, i) + } +} + +impl_hash_id!(FileContractID); + +impl FileContractID { + const PROOF_OUTPUT_ID_PREFIX: Specifier = specifier!("storage proof"); + const V2_PROOF_OUTPUT_ID_PREFIX: &'static str = "id/v2filecontractoutput"; + const V2_FILE_CONTRACT_RENEWAL_PREFIX: &'static str = "id/v2filecontractrenewal"; + + fn derive_proof_output_id>(&self, valid: bool, i: usize) -> T { + let mut state = Params::new().hash_length(32).to_state(); + state.update(Self::PROOF_OUTPUT_ID_PREFIX.as_bytes()); + state.update(self.as_ref()); + state.update(&(valid as u8).to_le_bytes()); + state.update(&(i as u64).to_le_bytes()); + state.finalize().into() + } + + fn derive_v2_proof_output_id>(&self, i: usize) -> T { + let mut state = Params::new().hash_length(32).to_state(); + state.update(Self::V2_PROOF_OUTPUT_ID_PREFIX.as_ref()); + state.update(self.as_ref()); + state.update(&(i as u64).to_le_bytes()); + state.finalize().into() + } + + /// valid_output_id returns the SiacoinOutputID for the i-th valid output of the contract + pub fn valid_output_id(&self, i: usize) -> SiacoinOutputID { + self.derive_proof_output_id(true, i) + } + + /// missed_output_id returns the SiacoinOutputID for the i-th missed output of the contract + pub fn missed_output_id(&self, i: usize) -> SiacoinOutputID { + self.derive_proof_output_id(false, i) + } + + /// v2_renter_output_id returns the SiacoinOutputID for the renter output of a V2 file contract + pub fn v2_renter_output_id(&self) -> SiacoinOutputID { + self.derive_v2_proof_output_id(0) + } + + /// v2_host_output_id returns the SiacoinOutputID for the host output of a V2 file contract + pub fn v2_host_output_id(&self) -> SiacoinOutputID { + self.derive_v2_proof_output_id(1) + } + + /// v2_renewal_id returns the ID of the new contract created by renewing a V2 contract + pub fn v2_renewal_id(&self) -> FileContractID { + let mut state = Params::new().hash_length(32).to_state(); + state.update(Self::V2_FILE_CONTRACT_RENEWAL_PREFIX.as_ref()); + state.update(self.as_ref()); + state.finalize().into() + } +} #[derive(Debug, PartialEq, SiaEncode, SiaDecode, Serialize, Deserialize)] pub struct ChainIndex { @@ -270,7 +396,9 @@ pub struct StateElement { #[cfg(test)] mod tests { - use crate::{address, block_id, public_key, siacoin_id}; + use crate::{ + address, block_id, contract_id, public_key, siacoin_id, siafund_id, transaction_id, + }; use super::*; @@ -353,17 +481,131 @@ mod tests { ], }; - const BINARY_STR: &'static str = "8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c90dc120000000000000000000000000001000000000000000700000000000000cb563bafbb55c90000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000008fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c000000000000000001000000000000006564323535313900000000000000000020000000000000008fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c010000000000000001000000000000000700000000000000f11318f74d10cf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + const BINARY_STR: &str = "8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c90dc120000000000000000000000000001000000000000000700000000000000cb563bafbb55c90000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000008fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c000000000000000001000000000000006564323535313900000000000000000020000000000000008fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c010000000000000001000000000000000700000000000000f11318f74d10cf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; let mut serialized = Vec::new(); b.encode_v1(&mut serialized).unwrap(); assert_eq!(serialized, hex::decode(BINARY_STR).unwrap()); let deserialized = Block::decode_v1(&mut &serialized[..]).unwrap(); assert_eq!(deserialized, b); - const JSON_STR: &'static str = "{\"parentID\":\"8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c\",\"nonce\":1236112,\"timestamp\":\"1970-01-01T00:00:00Z\",\"minerPayouts\":[{\"value\":\"57234234623612361\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"}],\"transactions\":[{\"siacoinInputs\":[{\"parentID\":\"8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c\",\"unlockConditions\":{\"timelock\":0,\"publicKeys\":[\"ed25519:8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c\"],\"signaturesRequired\":1}}],\"siacoinOutputs\":[{\"value\":\"67856467336433871\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"}]}]}"; + const JSON_STR: &str = "{\"parentID\":\"8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c\",\"nonce\":1236112,\"timestamp\":\"1970-01-01T00:00:00Z\",\"minerPayouts\":[{\"value\":\"57234234623612361\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"}],\"transactions\":[{\"siacoinInputs\":[{\"parentID\":\"8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c\",\"unlockConditions\":{\"timelock\":0,\"publicKeys\":[\"ed25519:8fb49ccf17dfdcc9526dec6ee8a5cca20ff8247302053d3777410b9b0494ba8c\"],\"signaturesRequired\":1}}],\"siacoinOutputs\":[{\"value\":\"67856467336433871\",\"address\":\"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69\"}]}]}"; let serialized = serde_json::to_string(&b).unwrap(); assert_eq!(serialized, JSON_STR); let deserialized: Block = serde_json::from_str(&serialized).unwrap(); assert_eq!(deserialized, b); } + + #[test] + fn test_transaction_derive() { + const TXN_JSON: &str = r#"{"siacoinInputs":[{"parentID":"750d22eff727689d1d8d1c83e513a30bb68ee7f9125a4dafc882459e34c2069d","unlockConditions":{"timelock":0,"publicKeys":["ed25519:800ed6c2760e3e4ba1ff00128585c8cf8fed2e3dc1e3da1eb92d49f405bd6360"],"signaturesRequired":6312611591377486220}}],"siacoinOutputs":[{"value":"890415399000000000000000000000000","address":"480a064b5fca13002a7fe575845154bbf0b3af4cc4f147cbed387d43cce3568ae2497366eaa7"}],"fileContracts":[{"filesize":0,"fileMerkleRoot":"0000000000000000000000000000000000000000000000000000000000000000","windowStart":10536451586783908586,"windowEnd":9324702155635244357,"payout":"0","validProofOutputs":[{"value":"1933513214000000000000000000000000","address":"944524fff2c49c401e748db37cfda7569fa6df35b704fe716394f2ac3f40ce87b4506e9906f0"}],"missedProofOutputs":[{"value":"2469287901000000000000000000000000","address":"1df67838262d7109ffcd9018f183b1eb33f05659a274b89ea6b52ff3617d34a770e9dd071d2e"}],"unlockHash":"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69","revisionNumber":9657412421282982780}],"fileContractRevisions":[{"parentID":"e4e26d93771d3bbb3d9dd306105d77cfb3a6254d1cc3495903af6e013442c63c","unlockConditions":{"timelock":0,"publicKeys":["ed25519:e6b9cde4eb058f8ecbb083d99779cb0f6d518d5386f019af6ead09fa52de8567"],"signaturesRequired":206644730660526450},"revisionNumber":10595710523108536025,"filesize":0,"fileMerkleRoot":"0000000000000000000000000000000000000000000000000000000000000000","windowStart":4348934140507359445,"windowEnd":14012366839994454386,"validProofOutputs":[{"value":"2435858510000000000000000000000000","address":"543bc0eda69f728d0a0fbce08e5bfc5ed7b961300e0af226949e135f7d12e32f0544e5262d6f"}],"missedProofOutputs":[{"value":"880343701000000000000000000000000","address":"7b7f9aee981fe0d93bb3f49c6233cf847ebdd39d7dc5253f7fc330df2167073b35f035703237"}],"unlockHash":"000000000000000000000000000000000000000000000000000000000000000089eb0d6a8a69"}],"storageProofs":[{"parentID":"c0b9e98c9e03a2740c75d673871c1ee91f36d1bb329ff3ddbf1dfa8c6e1a64eb","leaf":"b78fa521dc62d9ced82bc3b61e0aa5a5c221d6cca5db63d94c9879543fb98c0a971094a89cd4408487ae32902248d321b545f9a051729aa0bb1725b848e3d453","proof":["fe08c0a061475e7e5dec19e717cf98792fa7b555d0b5d3540a05db09f59ab8de"]}],"minerFees":["241119475000000000000000000000000"],"arbitraryData":["2shzIHEUJYwuNHz6c/gPz+aTEWZRTpDTmemX9yYAKlY="],"signatures":[{"parentID":"06d1fca03c5ddd9b09116db1b97c5451f7dc792b05362969f83e3e8dc1007f46","publicKeyIndex":6088345341283457116,"timelock":2014247885072555224,"coveredFields":{"wholeTransaction":true},"signature":"2XNEKGZrl9RhMa2JmGsvcmqQWAIX/uxtMwLnPI6VJPcXqub6qYIuoAThYp9NAwadk+1GG6CXC66g4rOjFYuNSA=="}]}"#; + + const EXPECTED_TRANSACTION_ID: TransactionID = + transaction_id!("71a10d363f4af09c3fbce499b725067b0b19afe2bc9a8236704e85256f3244a6"); + const EXPECTED_SIACOIN_OUTPUT_ID: SiacoinOutputID = + siacoin_id!("ea315efdd5914c54e8082d0de90b5afa9d4b92103d60661ec86b2a095413d836"); + const EXPECTED_SIAFUND_OUTPUT_ID: SiafundOutputID = + siafund_id!("a8190ea7b4d41e08f45f27653b882faf8ff9fd57bb098d7022f105ef142279ec"); + const EXPECTED_FILE_CONTRACT_ID: FileContractID = + contract_id!("ff7102bb111a64c7ff8a3cd68dbc962a03a8943065c3852a359662c8935fa979"); + + let txn: v1::Transaction = + serde_json::from_str(TXN_JSON).expect("transaction to deserialize"); + + assert_eq!(txn.id(), EXPECTED_TRANSACTION_ID, "transaction id"); + + assert_eq!( + txn.siacoin_output_id(678569214627704587), + EXPECTED_SIACOIN_OUTPUT_ID, + "siacoin output id" + ); + + assert_eq!( + txn.siafund_output_id(8940170890223196046), + EXPECTED_SIAFUND_OUTPUT_ID, + "siafund output id" + ); + + assert_eq!( + txn.file_contract_id(3470616158951613631), + EXPECTED_FILE_CONTRACT_ID, + "file contract id" + ); + } + + #[test] + fn test_transaction_id_v2_derive() { + const EXPECTED_V2_SIACOIN_OUTPUT_ID: SiacoinOutputID = + siacoin_id!("f74e0d8eae89ec820184c9bacfcad0181c781c02020f8a3fcbc82fd4ebf2fcf0"); + const EXPECTED_V2_SIAFUND_OUTPUT_ID: SiafundOutputID = + siafund_id!("f7d9ad77bfe9a102ef9590f97024f3aa8f54877d10447c128b52d5ca18cca983"); + const EXPECTED_V2_FILE_CONTRACT_ID: FileContractID = + contract_id!("c67764bc06df3dd933e0d4e93c6f7cbe5b56670d1baae156b578d417f08e65cf"); + + let txn_id = + transaction_id!("168ecf3133ae713c26f90fe1790fb7536f12cc2a492985627856b77c6ad99070"); + + assert_eq!( + txn_id.v2_siacoin_output_id(3543556734851495409), + EXPECTED_V2_SIACOIN_OUTPUT_ID, + "v2 siacoin output id" + ); + + assert_eq!( + txn_id.v2_siafund_output_id(4957302981402025980), + EXPECTED_V2_SIAFUND_OUTPUT_ID, + "v2 siafund output id" + ); + + assert_eq!( + txn_id.v2_file_contract_id(5375460735837768427), + EXPECTED_V2_FILE_CONTRACT_ID, + "v2 file contract id" + ); + } + + #[test] + fn test_block_id_derive() { + const EXPECTED_FOUNDATION_OUTPUT_ID: SiacoinOutputID = + siacoin_id!("159e2c4159a112ea9a70242d541a26f49fce41b6126f9105eab9b68dba4cfafb"); + const EXPECTED_MINER_OUTPUT_ID: SiacoinOutputID = + siacoin_id!("69e68779991392663d808276e6661d94628632354e258d8ab6724de1d9ca6208"); + + let block_id = + block_id!("c56d879b07b27fab3bdd06b833dbd1ad7eb167058851f543a517308b634a80a1"); + + assert_eq!( + block_id.foundation_output_id(), + EXPECTED_FOUNDATION_OUTPUT_ID, + "foundation output id" + ); + + assert_eq!( + block_id.miner_output_id(3072616177397065894), + EXPECTED_MINER_OUTPUT_ID, + "miner output id" + ); + } + + #[test] + fn test_siafund_output_id_derive() { + const EXPECTED_CLAIM_ID: SiacoinOutputID = + siacoin_id!("8eec57722c2ac040e34322ba77cb6b488ac8081f856d93bea1bf1bef42aeaabb"); + const EXPECTED_V2_CLAIM_ID: SiacoinOutputID = + siacoin_id!("b949006c65c70b5973da46cc783981d701dd854316e7efb1947c0b5f2fdc8db4"); + + let siafund_output_id = + siafund_id!("58ea19fd87ae5e10f928035e1021c3d9ee091fb3c0bbd5a1a6af41eea12e0f85"); + + assert_eq!( + siafund_output_id.claim_output_id(), + EXPECTED_CLAIM_ID, + "claim output id" + ); + + assert_eq!( + siafund_output_id.v2_claim_output_id(), + EXPECTED_V2_CLAIM_ID, + "v2 claim output id" + ); + } } diff --git a/sia/src/types/spendpolicy.rs b/sia/src/types/spendpolicy.rs index 0a76172..3b36001 100644 --- a/sia/src/types/spendpolicy.rs +++ b/sia/src/types/spendpolicy.rs @@ -687,7 +687,7 @@ mod tests { // json let serialized = serde_json::to_string(&tc.policy).unwrap(); assert_eq!(serialized, tc.json, "json serialization failed"); - let deserialized: SatisfiedPolicy = serde_json::from_str(&tc.json).unwrap(); + let deserialized: SatisfiedPolicy = serde_json::from_str(tc.json).unwrap(); assert_eq!(deserialized, tc.policy, "json deserialization failed"); } } diff --git a/sia/src/types/v1.rs b/sia/src/types/v1.rs index eb69311..9759c1d 100644 --- a/sia/src/types/v1.rs +++ b/sia/src/types/v1.rs @@ -304,9 +304,6 @@ pub struct Transaction { } impl Transaction { - const SIACOIN_OUTPUT_ID_PREFIX: Specifier = specifier!("siacoin output"); - const SIAFUND_OUTPUT_ID_PREFIX: Specifier = specifier!("siafund output"); - pub fn encode_no_sigs(&self, w: &mut W) -> Result<(), encoding::Error> { self.siacoin_inputs.encode_v1(w)?; self.siacoin_outputs.encode_v1(w)?; @@ -500,28 +497,37 @@ impl Transaction { pub fn id(&self) -> TransactionID { let mut state = Params::new().hash_length(32).to_state(); self.encode_no_sigs(&mut state).unwrap(); - let hash = state.finalize(); - hash.into() + + state.finalize().into() } - pub fn siacoin_output_id(&self, i: usize) -> SiacoinOutputID { + fn derive_child_id>(&self, prefix: &Specifier, i: usize) -> T { let mut state = Params::new().hash_length(32).to_state(); - - state.update(Self::SIACOIN_OUTPUT_ID_PREFIX.as_bytes()); + state.update(prefix.as_bytes()); self.encode_no_sigs(&mut state).unwrap(); + state.update(&(i as u64).to_le_bytes()); + state.finalize().into() + } - let h = state.update(&i.to_le_bytes()).finalize(); - SiacoinOutputID::from(h) + /// siacoin_output_id returns the SiacoinOutputID for the i-th siacoin output of the transaction + pub fn siacoin_output_id(&self, i: usize) -> SiacoinOutputID { + const SIACOIN_OUTPUT_ID_PREFIX: Specifier = specifier!("siacoin output"); + + self.derive_child_id(&SIACOIN_OUTPUT_ID_PREFIX, i) } + /// siafund_output_id returns the SiafundOutputID for the i-th siafund output of the transaction pub fn siafund_output_id(&self, i: usize) -> SiafundOutputID { - let mut state = Params::new().hash_length(32).to_state(); + const SIAFUND_OUTPUT_ID_PREFIX: Specifier = specifier!("siafund output"); - state.update(Self::SIAFUND_OUTPUT_ID_PREFIX.as_bytes()); - self.encode_no_sigs(&mut state).unwrap(); + self.derive_child_id(&SIAFUND_OUTPUT_ID_PREFIX, i) + } + + /// file_contract_id returns the FileContractID for the i-th file contract of the transaction + pub fn file_contract_id(&self, i: usize) -> FileContractID { + const FILE_CONTRACT_ID_PREFIX: Specifier = specifier!("file contract"); - let h = state.update(&i.to_le_bytes()).finalize(); - SiafundOutputID::from(h) + self.derive_child_id(&FILE_CONTRACT_ID_PREFIX, i) } } @@ -1252,7 +1258,7 @@ mod tests { ]; for (expected_str, public_key) in test_cases { - let expected = Address::parse_string(&expected_str).unwrap(); + let expected = Address::parse_string(expected_str).unwrap(); let public_key = PublicKey::new(public_key.as_slice().try_into().unwrap()); let addr = UnlockConditions::standard_unlock_conditions(public_key).address(); diff --git a/sia/src/types/v2.rs b/sia/src/types/v2.rs index bee8152..4405adb 100644 --- a/sia/src/types/v2.rs +++ b/sia/src/types/v2.rs @@ -13,7 +13,7 @@ use crate::types::common::BlockID; use super::{ Address, AttestationID, ChainIndex, Currency, FileContractID, Hash256, Leaf, SiacoinOutput, - SiacoinOutputID, SiafundOutput, SiafundOutputID, StateElement, + SiacoinOutputID, SiafundOutput, SiafundOutputID, StateElement, TransactionID, }; // expose spend policies @@ -511,6 +511,12 @@ impl Transaction { Ok(()) } + pub fn id(&self) -> TransactionID { + let mut state = Params::new().hash_length(32).to_state(); + self.encode_semantics(&mut state).unwrap(); + state.finalize().into() + } + pub fn input_sig_hash(&self, cs: &ChainState) -> Hash256 { let mut state = Params::new().hash_length(32).to_state(); state.update("sia/sig/input|".as_bytes());