From 0ac1dd635252922c77fbb0584d883b255c1d3dc1 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Tue, 4 Nov 2025 05:20:18 -0300 Subject: [PATCH 01/20] add command for creating ship --- runtime/src/genesis.rs | 57 ++++++- wallet/src/cli.rs | 41 +++++ wallet/src/game.rs | 336 +++++++++++++++++++++++++++++++++++++++++ wallet/src/main.rs | 10 +- wallet/src/sync.rs | 82 +++++++--- 5 files changed, 494 insertions(+), 32 deletions(-) create mode 100644 wallet/src/game.rs diff --git a/runtime/src/genesis.rs b/runtime/src/genesis.rs index adcfbb3..6920a8a 100644 --- a/runtime/src/genesis.rs +++ b/runtime/src/genesis.rs @@ -20,20 +20,69 @@ pub const GENESIS_DEFAULT_JSON: &str = r#" { "policy": "0298aa99f95e2fe0a0132a6bb794261fb7e7b0d988215da2f2de2005", "assets": [ ["tokenA", 271000000], ["tokenB", 1123581321] ] + }, + { + "policy": "7ba97fb6e48018ef131dd08916939350c0ce7050534f8e51b5e0e3a4", + "assets": [ ["PILOT0", 1], ["PILOT1", 1] ] } ], "datum": "820080" }, { - "address": "61547932e40a24e2b7deb41f31af21ed57acd125f4ed8a72b626b3d7f6", + "address": "70bac1753d5f7e3609c92776371fd0eafa753889e5712858f48fb83981", + "coin": 500000000, + "value": [ + { + "policy": "516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d28", + "assets": [ ["asteriaAdmin", 1] ] + } + ], + "datum": "D8799F02581C7BA97FB6E48018EF131DD08916939350C0CE7050534F8E51B5E0E3A4FF" + }, + { + "address": "707ba97fb6e48018ef131dd08916939350c0ce7050534f8e51b5e0e3a4", "coin": 314150000, "value": [ { - "policy": "0298aa99f95e2fe0a0132a6bb794261fb7e7b0d988215da2f2de2005", - "assets": [ ["tokenA", 300000000], ["tokenB", 2000000000] ] + "policy": "6a25ad5476105ac4a3784769cb93f92fd67a11932ef9a65a61abd1d6", + "assets": [ ["FUEL", 30] ] + }, + { + "policy": "7ba97fb6e48018ef131dd08916939350c0ce7050534f8e51b5e0e3a4", + "assets": [ ["SHIP0", 1] ] } ], - "datum": "820080" + "datum": "D8799F27034553484950304650494C4F54301B0000018AE4FFE838FF" + }, + { + "address": "707ba97fb6e48018ef131dd08916939350c0ce7050534f8e51b5e0e3a4", + "coin": 2000, + "value": [ + { + "policy": "6a25ad5476105ac4a3784769cb93f92fd67a11932ef9a65a61abd1d6", + "assets": [ ["FUEL", 25] ] + }, + { + "policy": "7ba97fb6e48018ef131dd08916939350c0ce7050534f8e51b5e0e3a4", + "assets": [ ["SHIP1", 1] ] + } + ], + "datum": "D8799F00004553484950314650494C4F54311B00000196C625FAE0FF" + }, + { + "address": "706a25ad5476105ac4a3784769cb93f92fd67a11932ef9a65a61abd1d6", + "coin": 2000, + "value": [ + { + "policy": "6a25ad5476105ac4a3784769cb93f92fd67a11932ef9a65a61abd1d6", + "assets": [ ["FUEL", 80] ] + }, + { + "policy": "516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d28", + "assets": [ ["asteriaAdmin", 1] ] + } + ], + "datum": "d8799f2703581c7ba97fb6e48018ef131dd08916939350c0ce7050534f8e51b5e0e3a4ff" }, { "address": "0000000000000000000000000000000000000000000000000000000000", diff --git a/wallet/src/cli.rs b/wallet/src/cli.rs index eecdc20..0d687f0 100644 --- a/wallet/src/cli.rs +++ b/wallet/src/cli.rs @@ -105,6 +105,8 @@ pub enum Command { /// Build a complete Griffin transaction from a JSON file containing all the necessary information. BuildTx(BuildTxArgs), + + CreateShip(CreateShipArgs), } /// Arguments for building a complete Griffin transaction. @@ -184,6 +186,45 @@ pub struct SpendValueArgs { pub token_amount: Vec, } +#[derive(Debug, Args)] +pub struct CreateShipArgs { + /// An input to be consumed by this transaction. This argument may be specified multiple times. + #[arg(long, short, verbatim_doc_comment, value_parser = input_from_string, required = true, value_name = "WALLET_OUTPUT_REF")] + pub input: Input, + + /// 32-byte H256 public key of an input owner. + /// Their pk/sk pair must be registered in the wallet's keystore. + #[arg(long, short, verbatim_doc_comment, value_parser = h256_from_string, default_value = SHAWN_PUB_KEY, value_name = "PUBLIC_KEY")] + pub witness: H256, + + #[arg( + long, + short, + verbatim_doc_comment, + required = true, + value_name = "POS_X" + )] + pub pos_x: i16, + + #[arg( + long, + short, + verbatim_doc_comment, + required = true, + value_name = "POS_Y" + )] + pub pos_y: i16, + + #[arg( + long, + short, + verbatim_doc_comment, + required = true, + value_name = "TIME_TO_LIVE" + )] + pub ttl: u64, +} + #[derive(Debug, Args)] pub struct ShowOutputsAtArgs { /// 29-byte hash-address. diff --git a/wallet/src/game.rs b/wallet/src/game.rs new file mode 100644 index 0000000..b5e1f08 --- /dev/null +++ b/wallet/src/game.rs @@ -0,0 +1,336 @@ +use crate::{ + cli::{CreateShipArgs, ShowOutputsAtArgs}, + sync, H224, +}; +use anyhow::anyhow; +use griffin_core::{ + checks_interface::{babbage_minted_tx_from_cbor, babbage_tx_to_cbor}, + pallas_codec::{ + minicbor, + utils::{Int, MaybeIndefArray::Indef}, + }, + pallas_crypto::hash::Hash as PallasHash, + pallas_primitives::babbage::{ + BigInt, BoundedBytes, Constr, MintedTx, PlutusData as PallasPlutusData, + Tx as PallasTransaction, + }, + pallas_traverse::OriginalHash, + types::{ + compute_plutus_v2_script_hash, Address, AssetName, Coin, Datum, Input, Multiasset, Output, + PlutusData, PlutusScript, PolicyId, Redeemer, RedeemerTag, Transaction, VKeyWitness, Value, + }, +}; +use jsonrpsee::{core::client::ClientT, http_client::HttpClient, rpc_params}; +use parity_scale_codec::Encode; +use sc_keystore::LocalKeystore; +use sled::Db; +use sp_core::ed25519::Public; +use sp_runtime::traits::{BlakeTwo256, Hash}; + +const SHIP_FEE: Coin = 3000000; + +const ASTERIA_SCRIPT_HEX: &str = "590d3c01000033332323232323232323232323232322232232232323232232323232253330163232323232323232533301e300c3020375400e264646464a666044602a60486ea80044c8c8c8c8c8c8c94ccc0a4c0700184c94ccc0b800454cc0ac094584c94ccc0bcc0c80084c94ccc0b0c064c0b8dd500089919191919192999819299981919baf300b303537540106e98cc894ccc0d0c09c0b040044c8c8cc00400400c894ccc0ec0044cc0f0cdd8261014000374c00697adef6c60132323232533303b3375e66012911000024c103d879800013304033760981014000374c00e00a2a66607666e3d22100002132533303c302f303e375400226608266ec13010140003042303f3754002008200864a666078a66608000229445280a6103d87a80001301d33041374c00297ae03233001001002225333041001133042337609801014000375006a97adef6c6013232323253330413375e6601e911000024c103d879800013304633760981014000375007200a2a66608266e3d22100002132533304230353044375400226608e66ec1301014000304830453754002008200864a666084606a002298103d87a80001302333047375000297ae03370000207226608c66ec0dd48011ba800133006006003375a60860066eb8c104008c114008c10c0044cc100cdd81ba9002374c0026600c00c0066eacc0f400cdd7181d801181f801181e8009919001191980080080111299981d8008a4c264a66607800229309919299981d1816981e1baa33008375c607860800086eb8c0f00084cc014014cc0fc00800454cc0ed2401326b65797320696e206173736f63696174697665206c697374206172656e277420696e20617363656e64696e67206f7264657200163040002303e001303e0013303933760981014000375005897adef6c60225333034337200040022980103d8798000153330343371e0040022980103d87a800014c103d87b800037566016606a6ea8c02cc0d4dd50080a511533033491146d7573745f6164645f666565203f2046616c73650014a02a666064a666064006294454cc0cd2411d6d7573745f686f6c645f61646d696e5f746f6b656e203f2046616c73650014a02a666064a666064004294454cc0cd2411e6d7573745f696e6372656d656e745f636f756e746572203f2046616c73650014a02a666064002294454cc0cd2401256d7573745f70726573657276655f73686970796172645f706f6c696379203f2046616c73650014a029405280a503371e6eb8c028c0d0dd500200a19b87375a602460666ea800ccdc000a2400466e21200033300a3756601060646ea8014dd7180898191baa029375c601060646ea80a4cc0800040ad4cccccc0d4004400454cc0b80a85854cc0b80a85854cc0b80a85854cc0b80a858c0c8c0bcdd50008a998168140b180298171baa001153302c0261630300013300100f23375e6018605a6ea8004c030c0b4dd5180198169baa008132533302a3018007132533302f001153302c0261613253330303033002132533302d301a302f375400226464646464a666064604a60686ea80044c8c8c94ccc0d54ccc0d40145288a9981b24811d6d7573745f696e7075745f736869705f746f6b656e203f2046616c73650014a02a66606aa66606a004294454cc0d92411f6d7573745f726573706563745f6d61785f6d696e696e67203f2046616c73650014a02a66606a002294454cc0d924011b6d7573745f70726573657276655f646174756d203f2046616c73650014a0294052819baf0280063232323371266e08dd6981e0009bad303c303d002337046eb4c0f0008dd6981e181e800981c1baa323230183303c375066e08dd6981e8011bad303d0013303c375066e08dd6981e981f0011bad303d303e0014bd70181c9baa32323232301b3303f375066e04cdc11bad3040004001337046eb4c10000800ccc0fcdd419b820030014bd701bad303f3040001303b3754607c60766ea801cdd6981e981f000981c9baa300348008c0e0dd5180118019bab300e30383754601c60706ea804cc0dcdd5180098011bab300d303737540124602a660726ea0004cc0e530010101004bd701199807000a450048810015330334913f65787065637420536f6d652870657263656e7461676529203d20726174696f6e616c2e6e6577286d61785f617374657269615f6d696e696e672c20313030290016533303130244832004530103d87a80001533303133710906400a4000260246606c60246606c6ea0cdc0a400004e6606c6ea0cdc024000906380a5eb812f5c0260246606c60246606c6ea009ccc0d9301021864004bd7025eb80c01ccc04005c8c8cc004004c8cc004004c94ccc0d0c088c0d8dd50008a5eb7bdb1804dd5981d181b9baa0013300f37566018606c6ea8c030c0d8dd500180b11299981c0008a5eb804cc0e4c0d8c0e8004cc008008c0ec004894ccc0dc004528099299981a19b8f33371890001b8d489045348495000375c607400491104534849500014a2266006006002607400266042002058a66666606c00220022a6605e0562c2a6605e0562c2a6605e0562c2a6605e0562c606660606ea800454cc0b80a458c018c0bcdd50008a998168138b181880099801008119baf300d302e3754002601a605c6ea8c010c0b8dd50048a99981518009980500892999815999815a999815980f18169baa300d302e3754601a605c6ea8c010c0b8dd50008a5014a294128899b8848000ccc018dd5980218171baa3004302e37540026eb8c034c0b8dd50129bae3004302e375404a29405288a99815a481296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a04a666054603a60586ea80045288a5022323300100100322533303000114bd70099192999817180280109981980119802002000899802002000981a00118190009181718178009181698171817000911192999814980b98159baa0011480004dd6981798161baa0013253330293017302b3754002298103d87a80001323300100137566060605a6ea8008894ccc0bc004530103d87a80001323232533302e3371e00e6eb8c0c000c4c03ccc0ccdd4000a5eb804cc014014008dd6981800118198011818800998020018011119198008008019129998160008a60103d87a80001323232533302b3371e00c6eb8c0b400c4c030cc0c0dd3000a5eb804cc014014008dd598168011818001181700098129baa0123028302537540022a6604692013c65787065637420536f6d6528617374657269615f696e70757429203d2066696e645f696e70757428696e707574732c20617374657269615f726566290016323300200923375e600a604c6ea8004008c09cc090dd50051119198008008019129998140008a60103d87a80001323253330263005002130073302b0024bd70099802002000981600118150009ba5480008c09400454cc07d24123657870656374205370656e6428617374657269615f72656629203d20707572706f73650016375c604660480046eb4c088004c078dd50079bac3020302130210023758603e00260366ea8c078008c074c078004c064dd50008a4c2a6602e9211856616c696461746f722072657475726e65642066616c73650013656325333015300800115333019301837540082930a9980b0098b0a99980a98018008a99980c980c1baa004149854cc05804c5854ccc054c00800454ccc064c060dd50020a4c2a6602c0262c2a6602c0262c602c6ea800cdc3a40086e1d200253333330190011001153301200f16153301200f16153301200f16153301200f163300100300e225333010300330123754004264a66602a0022a660240042c26464a66602e0022a660280082c264a66603060360042930a9980a8028b19299999980e0008a9980a8028b0a9980a8028b0a9980a8028b0a9980a8028b09bae0013019001301900232533333301a0011533013003161533013003161533013003161375a0022a660260062c602e00260266ea800854cc04400458dc3a4000a66666602800220022a6601a0162c2a6601a0162c2a6601a0162c2a6601a0162c6eb4004dd6800a499c657870656374205b617374657269615f6f75747075745d203d0a202020202020202020206c6973742e66696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d20617374657269615f696e7075742e6f75747075742e61646472657373207d2c0a20202020202020202020290049013f65787065637420496e6c696e65446174756d28617374657269615f6f75747075745f646174756d29203d20617374657269615f6f75747075742e646174756d0049014065787065637420617374657269615f6f75747075745f646174756d3a2041737465726961446174756d203d20617374657269615f6f75747075745f646174756d0049011972656465656d65723a204173746572696152656465656d657200490113646174756d3a2041737465726961446174756d005734ae7155ceaab9e5573eae815d0aba257489812fd8799f581c516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d284c6173746572696141646d696eff004c01051a002dc6c0004c010218320001"; +const SHIP_SCRIPT_HEX: &str = "592e3101000033333333323232323232323232323232323232323232323232323223223222232232232232223253333330280021532323232323232323330283001302a37540142a660529211c52756e6e696e672032206172672076616c696461746f72206d696e740013232533302a3232323232323232325333033300c303537540102646464a66606c601e60706ea80384c8c8c94ccc0e4c048c0ecdd500089919191919299981f180c98201baa0011323232325333046001153304303e161325333047304a0021325333044301f30463754002264646464a666090604860946ea80044c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c94ccc16d4ccc16c0805288a9982e24811d6d7573745f62655f76616c69645f61737465726961203f2046616c73650014a02a6660b6a6660b6010294454cc171241206d7573745f6d696e745f65787065637465645f76616c7565203f2046616c73650014a02a6660b6a6660b600e294454cc171241216d7573745f726573706563745f6d696e5f64697374616e6365203f2046616c73650014a02a6660b6a6660b600c294454cc1712411b6d7573745f686176655f736869705f6e616d65203f2046616c73650014a02a6660b6a6660b600a294454cc1712411c6d7573745f686176655f70696c6f745f6e616d65203f2046616c73650014a02a6660b6a6660b6008294454cc1712411d6d7573745f686176655f6c61746573745f74696d65203f2046616c73650014a02a6660b6a6660b6006294454cc1712411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660b6a6660b6004294454cc1712411e6d7573745f686f6c645f696e697469616c5f6675656c203f2046616c73650014a02a6660b6002294454cc17124011a6d7573745f686f6c645f335f617373657473203f2046616c73650014a029405280a5014a029405280a5014a06068664600200244a6660c0002290000981d99801001183180099198008009bab3025305e375403244a6660c0002297ae01323332223233001001003225333066001100313233068374e660d06ea4018cc1a0dd49bae30650013306837506eb4c1980052f5c06600600660d400460d00026eb8c17c004dd59830000998018019832001183100099b8733301f3756604660b86ea805c1252201044655454c0003f303433301e3756604460b66ea805809401ccdc39bad305d305e305e305e305e305a37540246eb4c174c168dd500819b8f375c60b860ba60ba60ba60b26ea8044010cdc79bae30193058375402000866e240e0c8cdc018009bad301e3058375402060026eb4c07cc160dd50081299982a99b88001480004c0cc0044004cdd79ba601f374c64646466660026666002a6660ac606490000a5eb7bdb1804c8c8cc0040052f5bded8c044a6660ba0022660bc66ec0dd48131ba60034bd6f7b630099191919299982e98049980501500109983119bb037520546e9801c01454ccc174cdc781500109983119bb037520546e9801c00c4cc188cdd81ba9002374c0026600c00c0066eacc17c00cdd7182e8011830801182f8009919800800a5eb7bdb180894ccc1700044cc174cdd81ba90074c010101004bd6f7b630099191919299982e18041980480580109983099bb037520169810101000051533305c3371e0160042660c266ec0dd4805a61010100003133061337606ea4008dd4000998030030019bad305e003375c60b800460c000460bc0020460089001023245044655454c0003c22225333059303200110041323233001001006225333060001133061337606ea4018dd3001a5eb7bdb1804c8c8c8c94ccc180c030cc0340280084cc194cdd81ba900a374c00e00a2a6660c066e3c0280084c94ccc184c0e8c18cdd500089983319bb0375201660ce60c86ea80040104010c94ccc1854ccc1940045288a5014c0103d87a80001303e33066374c00297ae03233001001002225333066001133067337606ea402cdd400525eb7bdb1804c8c8c8c94ccc198c048cc04c03c0084cc1accdd81ba900f375001c00a2a6660cc66e3c03c0084c94ccc19cc100c1a4dd500089983619bb0375202060da60d46ea80040104010c94ccc19cc1000045300103d87a8000130443306c375000297ae03370000201c2660d666ec0dd48011ba800133006006003375a60d00066eb8c198008c1a8008c1a00044cc194cdd81ba9002374c0026600c00c0066eacc18800cdd7183000118320011831000991900119198008008011129998300008a4c264a6660c200229309919299982f981c18309baa3300c375c60c260ca0086eb8c1840084cc014014cc19000800454cc1812401326b65797320696e206173736f63696174697665206c697374206172656e277420696e20617363656e64696e67206f7264657200163065002306300130630013305e337606ea4008dd4000a5eb7bdb180dd7a60103d879800022533305533720004002298103d8798000153330553371e0040022980103d87a800014c103d87b8000330024890550494c4f540030033004375a603660aa6ea804ccc005220104534849500030023003375a603460a86ea804888cdc500100091b9800123732660046ea00052201003001001222533333305700213232323232323300b0020013371491010128000025333053337100069007099b80483c80400c54ccc14ccdc4001a410004266e00cdc0241002800690068a9982a24929576861742061726520796f7520646f696e673f204e6f2049206d65616e2c20736572696f75736c792e001653330560011337149101035b5d2900004133714911035b5f2000375c60aa66600e00266ec1300102415d00375266e292210129000042233760980103422c2000375266601001000466e28dd7182b0009bae3057001375860a80046eb4c148004c8cdd81ba83052001374e60a60026ea80084c94ccc1500044cdc5245027b7d00002133714911037b5f2000375c60a664646600200200644a6660ae00220062664466ec130103422c2000375266601201260ae00466e29221023a20003330090093058002337146eb8c15c004dd7182c000982c80099801001182d00099bb04c10342207d0037520046eac0084c94ccc1500044cdc52441025b5d00002133714911035b5f2000375c60a666600a00266ec1300102415d0037520044466ec1300103422c2000375266600c00c00466e28dd7182a0009bae3055001375800426600a6eb40080044c8c8cdc524410268270000132333001001337006e3400920013371491101270000322253330533371000490000800899191919980300319b8000548004cdc599b80002533305633710004900a0a40c02903719b8b33700002a6660ac66e2000520141481805206e0043370c004901019b8300148080cdc70020011bae00222232330010010042253330540011004133003305600133002002305700122323300100100322533304e30270011337149110130000031533304e337100029000099b8a489012d0033002002302c00113300533708002900a19b8b3370066e1400520144818000cc0040048894ccc12ccdc4801240002002266600600666e1000920143371666e00cdc28012402890300008a9982481f0b180818251baa3011304a375402aa66608c603e60906ea80044c94ccc12c00454cc120110584c8c94ccc13400454cc128118584c8c94ccc13c00454cc130120584c8c94ccc14400454cc138128584c8c94ccc14c00454cc140130584c94ccc150c15c008526153305104d16325333333058001153305104d16153305104d16153305104d161375a0022a660a209a2c60aa00260aa00464a6666660ac0022a6609e0962c2a6609e0962c2a6609e0962c2a6609e0962c26eb8004c14c004c14c008c94cccccc15000454cc1341245854cc1341245854cc1341245854cc134124584dd7000982880098288011929999998290008a998258238b0a998258238b0a998258238b09bad001153304b04716304f001304f0023253333330500011533049045161533049045161533049045161375a0022a6609208a2c609a00260926ea800454cc11c10c594cccccc134004400454cc1181085854cc1181085854cc1181085854cc11810858c128c11cdd50008a99822a493165787065637420496e6c696e65446174756d28736869705f646174756d29203d20736869705f73746174652e646174756d00163007304637540022a6608807e2c6090002646600200202644a66608e002297ae0132325333045325333046302230483754002266e3c04cdd7182618249baa00114a0601c60906ea8c038c120dd50010998250011980200200089980200200098258011824800a999820180c98211baa0011325333045001153304203c16132325333047001153304403e161325333048304b002149854cc1140fc58c94cccccc13000454cc1140fc5854cc1140fc5854cc1140fc5854cc1140fc584dd7000982480098248011929999998250008a9982181e8b0a9982181e8b0a9982181e8b09bad001153304303d163047001304337540022a660820762ca66666608e00220022a660800742c2a660800742c2a660800742c2a660800742c608860826ea800454cc0fd2413e65787065637420496e6c696e65446174756d28617374657269615f646174756d29203d20617374657269615f696e7075742e6f75747075742e646174756d0016300130403754600e60806ea80108c10cc110c110004c06cccc004dd59802981f1baa3005303e37540046eb8c010c0f8dd50141bae3005303e375405044464a66607c603460806ea8004520001375a608860826ea8004c94ccc0f8c068c100dd50008a60103d87a8000132330010013756608a60846ea8008894ccc110004530103d87a8000132323253330433371e00e6eb8c11400c4c080cc120dd4000a5eb804cc014014008dd698228011824001182300099804001801181f981e1baa001153303a03116323300100100c22533303e00114c103d87a800013232533303c32533303d3016303f375400229404cdc79bae304330403754002056600a607e6ea8c014c0fcdd51803181f9baa00213019330410024bd70099802002000982100118200009181f0009181e981f000899299981d8008a9981c01a8b099299981e181f8010a99981c19b8748004dd6981d8008a51153303903616153303903616303d001325333037301330393754002297adef6c6013756607a60746ea8004cc00400800c88c8cc00400400c894ccc0f40045300103d87a80001323232533303c3371e00c6eb8c0f800c4c064cc104dd3000a5eb804cc014014008dd5981f0011820801181f800991980080080211299981d0008a5eb7bdb1804c8c8c8c94ccc0e8cdc7a44100002100313303f337606ea4008dd3000998030030019bab303c003375c6074004607c00460780026eb8c0e4c0d8dd50040a9981a24926657870656374204d696e742873686970796172645f706f6c69637929203d20707572706f7365001630383039303930390023756606e002606e606e0046eb0c0d4004c0d4c0d4008dd6181980098179baa303200230313032001302d37540182930a99815a4811856616c696461746f722072657475726e65642066616c7365001365632533302a30030011533302e302d37540042930a998158148b0a99981518030008a99981718169baa002149854cc0ac0a45854cc0ac0a458c0acdd5000a99999981800588058a998148138b0a998148138b0a998148138b0a998148138b0a99814a491d52756e6e696e672033206172672076616c696461746f72207370656e640013323232232322533302f323232323232323232323232323232323232323232325333045301e30473754002264a66608c604460906ea80584c8c94ccc120c084c128dd5000899192999825181318261baa001132323232323232323232323232325323233305a303300d1323232325333062001153305f05016132533306330660021325333060303b30623754002264646464a6660c8608060cc6ea80044c8c94ccc198c108c1a0dd50008991919192999835182198361baa001132323232323232323232323253330765333076305230263301f044230293035307a3754606c60f46ea80045288a9983ba481236d7573745f7370656e645f6f6e655f7363726970745f696e707574203f2046616c73650014a02a6660eca6660ec054294454cc1dd241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660eca6660ec008294454cc1dd2411d6d7573745f686176655f656e6f7567685f6675656c203f2046616c73650014a02a6660eca6660ec00c294454cc1dd2411e6d7573745f726573706563745f6d61785f7370656564203f2046616c73650014a02a6660eca6660ec00a294454cc1dd241206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a02a6660eca6660ec004294454cc1dd241216d7573745f73756274726163745f6675656c5f746f6b656e73203f2046616c73650014a02a6660eca6660ec010294454cc1dd2411c6d7573745f6275726e5f7370656e745f6675656c203f2046616c73650014a02a6660eca6660ec014294454cc1dd241156d7573745f7570646174655f78203f2046616c73650014a02a6660eca6660ec012294454cc1dd241156d7573745f7570646174655f79203f2046616c73650014a02a6660eca6660ec00e294454cc1dd2411f6d7573745f7570646174655f75707065725f626f756e64203f2046616c73650014a02a6660eca6660ec016294454cc1dd241216d7573745f70726573657276655f70696c6f745f746f6b656e203f2046616c73650014a02a6660eca6660ec006294454cc1dd2411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660ec002294454cc1dd24011a6d7573745f686f6c645f335f617373657473203f2046616c73650014a029405280a5014a029405280a5014a029405280a5014a0609e604460486eacc0d0c1e0dd500b99b8733301f3756606660ee6ea80581912201044655454c0033702014018609e66603c6eacc0c8c1d8dd500a81481b19b8900a008301900d32323371266e08dd6983c0011bad30783079001337046eb4c1e0004dd6983c183c801183a1baa02c3073375460ec60e66ea801ccdc39bad307530763076307630763072375401c012602a609800c66e1cdd6981618381baa00c3370006402266e1cdd6981518379baa00b3370006602266e3c0b0dd7183898391839183918371baa00a3330153756605260da6ea8c0a4c1b4dd501102d2441044655454c00153306b4915865787065637420536f6d6528737065656429203d0a20202020202020202020726174696f6e616c2e6e65772864697374616e63652c2074785f6c61746573745f74696d65202d2074785f6561726c696573745f74696d65290016330260023370200600a66e08004140c8cdc0180080698008061299983419b88001480004c1180044004dd6983618349baa001153306705c16302330683754604860d06ea80b8dd6983518339baa001153306505916302130663754604260cc6ea80b0cc0e40041594cccccc1a4004400454cc1881545854cc1881545854cc1881545854cc18815458c198c18cdd50008a998308298b180498311baa00115330600511630640013300602923375e603860c26ea8004c070c184dd5180e98309baa016375a60c460c60046eb4c184004c174dd50170a99982d181b0068991929998300008a9982e8270b09929998309832001099299982f181c98301baa0011323232325333062303b306437540022646464a6660ca608060ce6ea80044c8c8c8c94ccc1a4c114c1acdd5000899191919191919191929998392999839182698111980d820118129818983b1baa303230763754002294454cc1cd2401246d7573745f7370656e645f74776f5f7363726970745f696e70757473203f2046616c73650014a02a6660e4a6660e401e294454cc1cd2411c6d7573745f62655f76616c69645f70656c6c6574203f2046616c73650014a02a6660e4a6660e404c294454cc1cd241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660e4a6660e4010294454cc1cd241216d7573745f686176655f70656c6c65745f706f736974696f6e203f2046616c73650014a02a6660e4a6660e4006294454cc1cd2411c6d7573745f6164645f6675656c5f746f6b656e73203f2046616c73650014a02a6660e4a6660e400e294454cc1cd241206d7573745f6e6f745f6578636565645f6361706163697479203f2046616c73650014a02a6660e4a6660e400a294454cc1cd241206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a02a6660e4a6660e400c294454cc1cd2411b6d7573745f70726573657276655f646174756d203f2046616c73650014a02a6660e4a6660e4008294454cc1cd2411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660e4a6660e4004294454cc1cd2411a6d7573745f686f6c645f335f617373657473203f2046616c73650014a02a6660e4002294454cc1cd24011c6d7573745f6e6f745f6d696e745f746f6b656e73203f2046616c73650014a029405280a5014a029405280a5014a0294052819baf374c603a07698101a000304a301d301f3756605e60e66ea8050cdc399980d1bab302e307237540260be911044655454c003370000c02a60946660326eacc0b4c1c4dd5009012018980a9bad30733070375400a66ebc034110cdc499b80002011055533306a3370e0626eb4c0a0c1b4dd5002099b8702f375a605260da6ea801052819980a1bab3028306c3754605060d86ea8084165221044655454c00153306a05e163026306b3754604c60d66ea80c54ccc19cc100c1a4dd500089929998360008a9983482f8b0991929998370008a998358308b0991929998380008a998368318b0992999838983a0010a4c2a660dc0c82c64a6666660ea0022a660dc0c82c2a660dc0c82c2a660dc0c82c2a660dc0c82c26eb8004c1c8004c1c8008c94cccccc1cc00454cc1b01885854cc1b01885854cc1b0188584dd68008a998360310b183800098380011929999998388008a998350300b0a998350300b0a998350300b09bad001153306a06016306e001306a37540022a660d00bc2ca6666660dc00220022a660ce0ba2c2a660ce0ba2c2a660ce0ba2c2a660ce0ba2c60d660d06ea800454cc1992413c65787065637420496e6c696e65446174756d2870656c6c65745f646174756d29203d2070656c6c65745f696e7075742e6f75747075742e646174756d0016300e30673754604660ce6ea8008c10cccc038dd5981118331baa3022306637540026eb8c084c198dd50281bae3022306637540a060d060ca6ea800454cc18d2401ff65787065637420536f6d652870656c6c65745f696e70757429203d0a202020202020202020206c6973742e66696e64280a202020202020202020202020696e707574732c0a202020202020202020202020666e28696e70757429207b0a20202020202020202020202020207768656e20696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c206973207b0a20202020202020202020202020202020566572696669636174696f6e4b657943726564656e7469616c285f29202d3e2046616c73650a2020202020202020202020202020202053637269707443726564656e7469616c28616464725f7061796d656e6b7429202d3e0a202020202020202020202020202020202020616464725f7061796d656e74203d3d2070656c6c65745f76616c696461746f725f616464726573730a20202020202020202020202020207d0a2020202020202020202020207d2c0a202020202020202020202900163301b02f2325333063303c3065375400229404cdc79bae3069306637540020a6604060ca6ea8c080c194dd5181098329baa00133037001054533333306700110011533060053161533060053161533060053161533060053163064306137540022a660be0a22c600e60c06ea800454cc17813c58c188004cc01009c8cdd7980d182f9baa001301a305f3754603660be6ea8050dd69830182e9baa02e1533305a303500d132533305b3034305d375400226464a6660ba607260be6ea80044c8c8c8c94ccc1854ccc184c0f0c044cc0280bc8c050c080c194dd5181098329baa00114a22a660c49201246d7573745f7370656e645f74776f5f7363726970745f696e70757473203f2046616c73650014a02a6660c2a6660c200c294454cc1892411d6d7573745f62655f76616c69645f61737465726961203f2046616c73650014a02a6660c2a6660c202a294454cc189241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660c2a6660c2008294454cc189241226d7573745f686176655f617374657269615f706f736974696f6e203f2046616c73650014a02a6660c2a6660c2006294454cc1892411c6d7573745f6275726e5f736869705f746f6b656e203f2046616c73650014a02a6660c2a6660c2002294454cc1892411d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a02a6660c2004294454cc1892401206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a029405280a5014a029405281803981f1998059bab301f30633754603e60c66ea80601412201044655454c003007375a60ca60c46ea800ccdc4199804980501400a010a400066ebcdd31983119bb037500486ea00892f5bded8c06e98cc1892f7b6301010000010100004bd6f7b6300a9982f0290b180d182f9baa301a305f375404a607666600c6eacc068c178dd5180d182f1baa3061305e37540026eb8c064c178dd50241bae301a305e37540902a660b80a62c66028050464a6660b8606a60bc6ea8004528099b8f375c60c460be6ea8004128c064c178dd5180c982f1baa301a305e375400226464a6660b8a6660b8607060186600a0544601e603660c06ea8c070c180dd50008a51153305d491236d7573745f7370656e645f6f6e655f7363726970745f696e707574203f2046616c73650014a02a6660b8a6660b8020294454cc175241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660b8a6660b8004294454cc1752411c6d7573745f6275726e5f736869705f746f6b656e203f2046616c73650014a02a6660b8002294454cc17524011d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a029405280a50300230393330063756603460bc6ea8c068c178dd5009825a441044655454c003371066600a600c04802003a90001b8733300430050230494881044655454c00371203044646600200200644a6660be002297ae013232533305d300500213306200233004004001133004004001306300230610012305d305e305e0012223253330593035305b37540022900009bad305f305c375400264a6660b2606a60b66ea80045300103d87a800013233001001375660c060ba6ea8008894ccc17c004530103d87a80001323232533305e3371e00e6eb8c18000c4c0eccc18cdd4000a5eb804cc014014008dd6983000118318011830800998068018011191980080080111299982d8008a5eb7bdb1804c8c8c8c94ccc16ccdc7a441000021003133060337606ea4008dd3000998030030019bab305d003375c60b600460be00460ba002600200244a6660b0002290000981999801001182d8009191980080080111299982c0008a5eb804c8ccc888c8cc00400400c894ccc178004400c4c8cc180dd3998301ba90063306037526eb8c174004cc180dd41bad305e0014bd7019801801983100118300009bae3057001375660b00026600600660b800460b4002600200244a6660aa002290000981819801001182c00092999827981418289baa300d30523754002294052898279baa021533304c3025304e37546600c03446466002002646600200264a6660a0605860a46ea800452f5bded8c026eacc158c14cdd5000998021bab300e30523754601c60a46ea800c014894ccc15000452f5c02660aa60a460ac0026600400460ae00244a6660a600229404c94ccc140cdc79bae305600201114a226600600600260ac00229445281119198008008019129998298008a60103d87a8000132323253330523371e00c6eb8c15000c4c0bccc15cdd3000a5eb804cc014014008dd5982a001182b801182a8009bae3050304d37540022a660969215d6578706563742053637269707443726564656e7469616c2873686970796172645f706f6c69637929203d0a202020202020736869705f696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c00163007304c3754600e60986ea8c020c130dd5000982718259baa001153304949013665787065637420536f6d6528736869705f696e70757429203d2066696e645f696e70757428696e707574732c20736869705f726566290016323300201623375e600e60986ea8004008c134c128dd500b9119198008008019129998270008a60103d87a800013232533304c300500213029330510024bd70099802002000982900118280008a99823a48120657870656374205370656e6428736869705f72656629203d20707572706f73650016304b304837540022a6608c92015865787065637420536f6d65286d61785f73706565645f726174696f6e616c29203d0a202020202020726174696f6e616c2e6e6577286d61785f73706565642e64697374616e63652c206d61785f73706565642e74696d6529001633001375a6004608e6ea80c0dd6980198239baa030225333045301e00114c103d87a80001533304533710002900009811198251811198251ba830230023304a3750604600297ae04bd7009811198251811198251ba80023304a375000297ae04bd70118248009182418248009bad30463047002375c608a002608a0046eb8c10c004c10c008dd6982080098208011bad303f001303b3754020607a607c607c607c0046eacc0f0004c0f0c0f0008dd6181d000981d181d0011bac303800130343754606e004606c606e00260646ea8004526153303049011856616c696461746f722072657475726e65642066616c7365001365632533302e30070011325333033001153303002816132325333035001153303202a1613253330363039002149854cc0cc0ac58c94cccccc0e800454cc0cc0ac5854cc0cc0ac5854cc0cc0ac584dd68008a998198158b181b800981b80119299999981c0008a998188148b0a998188148b0a998188148b09bad0011533031029163035001303137540042a66605c6014002264a6660660022a660600502c264a666068606e0042930a998188148b19299999981c0008a998188148b0a998188148b0a998188148b09bad0011533031029163035001303137540042a66605c60120022a66606460626ea8008526153302f027161533302e300800115333032303137540042930a998178138b0a998178138b18179baa00153333330340011001153302d02516153302d02516153302d02516153302d025163300100202422533302b3004302d3754004264a6660600022a6605a0042c26464a6660640022a6605e0082c26464a6660680022a6606200c2c26464a66606c0022a660660102c26464a6660700022a6606a0142c264a66607260780042930a9981b0058b19299999981e8008a9981b0058b0a9981b0058b0a9981b0058b09bad001153303600b16303a001303a00232533333303b0011533034009161533034009161533034009161533034009161375c0026070002607000464a6666660720022a6606400e2c2a6606400e2c2a6606400e2c2a6606400e2c26eb8004c0d8004c0d8008c94cccccc0dc00454cc0c00145854cc0c00145854cc0c0014584dd68008a998180028b181a000981a00119299999981a8008a998170018b0a998170018b0a998170018b09bad001153302e003163032001302e37540042a660580022ca66666606001620162a660520442c2a660520442c2a660520442c2a660520442c605c60566ea8028dc3a40006e1d2006370e90021b8748008dd2a40006e052000370090011b884800054cc0840045854cc0840045854cc0840045854cc08400459240191496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e00375a0026eb4004dd68009bad001375c0026eb800524196657870656374205b736869705f6f75747075745d203d0a202020202020202020206c6973742e66696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d20736869705f696e7075742e6f75747075742e61646472657373207d2c0a20202020202020202020290049013965787065637420496e6c696e65446174756d28736869705f6f75747075745f646174756d29203d20736869705f6f75747075742e646174756d0049013765787065637420736869705f6f75747075745f646174756d3a2053686970446174756d203d20736869705f6f75747075745f646174756d004901476578706563742046696e6974652874785f6561726c696573745f74696d6529203d2076616c69646974795f72616e67652e6c6f7765725f626f756e642e626f756e645f74797065004901456578706563742046696e6974652874785f6c61746573745f74696d6529203d2076616c69646974795f72616e67652e75707065725f626f756e642e626f756e645f747970650049012f6578706563742070656c6c65745f646174756d3a2050656c6c6574446174756d203d2070656c6c65745f646174756d004901ff65787065637420536f6d6528617374657269615f696e70757429203d0a202020202020202020206c6973742e66696e64280a202020202020202020202020696e707574732c0a202020202020202020202020666e28696e70757429207b0a20202020202020202020202020207768656e20696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c206973207b0a20202020202020202020202020202020566572696669636174696f6e4b657943726564656e7469616c285f29202d3e2046616c73650a2020202020202020202020202020202053637269707443726564656e7469616c28616464725f7061796d656d6e7429202d3e0a202020202020202020202020202020202020616464725f7061796d656e74203d3d20617374657269615f76616c696461746f725f616464726573730a20202020202020202020202020207d0a2020202020202020202020207d2c0a20202020202020202020290049011672656465656d65723a205368697052656465656d657200490110646174756d3a2053686970446174756d0049013265787065637420617374657269615f646174756d3a2041737465726961446174756d203d20617374657269615f646174756d00490159657870656374205b736869705f73746174655d203d0a202020202020202020207472616e73616374696f6e2e66696e645f7363726970745f6f757470757473286f7574707574732c2073686970796172645f706f6c696379290049012965787065637420736869705f646174756d3a2053686970446174756d203d20736869705f646174756d00490120657870656374205b285f2c202d31295d203d206d696e7465645f746f6b656e730049011a72656465656d65723a20536869707961726452656465656d6572005734ae7155ceaab9e5573eae815d0aba257489811e581c6a25ad5476105ac4a3784769cb93f92fd67a11932ef9a65a61abd1d6004c011e581cbac1753d5f7e3609c92776371fd0eafa753889e5712858f48fb83981004c012fd8799f581c516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d284c6173746572696141646d696eff004c0108d8799f01197530ff004c01021864004c010101004c0102181e004c01010a0001"; +const PELLET_SCRIPT_HEX: &str = "590d5a01000033232323232323232323232323232222325333333012002153232323233300e30013010375400c2a6601e9211c52756e6e696e672032206172672076616c696461746f72206d696e7400132325333010323232323253330153008301737540082646464a666030601660346ea80284c94ccc0654ccc0654ccc064c030c06cdd5191980080080391299980f8008a60103d87a800013232533301d3013323330073756600260426ea8c004c084dd50019bae3024302137540306eb8c004c084dd500c118121812800898091981100125eb804cc010010004c08c008c0840045288a5014a22a660349201296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a02a666032002294454cc06924011d6d7573745f6d696e745f6675656c5f746f6b656e73203f2046616c73650014a02940c038ccc00400800d2201044655454c001533301833710666002004006911044655454c00480005288a9980ca491d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a044464a666036601e603a6ea8004520001375a6042603c6ea8004c94ccc06cc03cc074dd50008a60103d87a80001323300100137566044603e6ea8008894ccc084004530103d87a8000132323253330203371e00e6eb8c08800c4c054cc094dd4000a5eb804cc014014008dd698110011812801181180099198008008021129998100008a6103d87a80001323232533301f3371e00e6eb8c08400c4c050cc090dd3000a5eb804cc014014008dd5981080118120011811000991980080080191299980e0008a5eb7bdb1804c8c8c8c94ccc070cdc7a441000021003133021337606ea4008dd3000998030030019bab301e003375c60380046040004603c0026eb8c06cc060dd50020a9980b24922657870656374204d696e74286675656c5f706f6c69637929203d20707572706f736500163756603460366036603660360046eb0c064004c054dd5180c001180b980c00098099baa008149854cc0452411856616c696461746f722072657475726e65642066616c73650013656325333010300300115333014301337540042930a998088078b0a99980818020008a99980a18099baa002149854cc04403c5854cc04403c58c044dd5000a99999980b00388038a998078068b0a998078068b0a998078068b0a998078068b0a99807a491d52756e6e696e672033206172672076616c696461746f72207370656e64001332323223232253330153232323232533301a300e301c37540082646464a66603a6020603e6ea80044c8c8c94ccc080c050c088dd5000899191919192999812980c18139baa0131323232533302c001153302902316132533302d3030002132533302a3370e900218161baa00113232323232323253330315333031300d33016019232330010013233001001325333035302930373754002297adef6c6013756607660706ea8004cc04cdd5980b181b9baa30163037375400601c44a666072002297ae013303a3037303b00133002002303c00122533303800114a0264a66606a66e3cccdc6240006e35221045348495000375c607600491104534849500014a22660060060026076002294454cc0c924011d6d7573745f696e7075745f736869705f746f6b656e203f2046616c73650014a02a666062a666062006294454cc0c92411d6d7573745f686f6c645f61646d696e5f746f6b656e203f2046616c73650014a02a666062a666062008294454cc0c92411d6d7573745f686176655f656e6f7567685f6675656c203f2046616c73650014a02a666062a666062004294454cc0c9241206d7573745f70726f766964655f6675656c5f616d6f756e74203f2046616c73650014a02a666062002294454cc0c924011b6d7573745f70726573657276655f646174756d203f2046616c73650014a029405280a5014a066ebc014088cdc39998069bab30113032375400e01e9101044655454c003370201801460446660186eacc040c0c4dd50031bae3014303137540506eb8c040c0c4dd501419b8900800a3301d00102853333330330011001153302c02716153302c02716153302c02716153302c027163030302d37540022a660569213365787065637420496e6c696e65446174756d286f75745f646174756d29203d2070656c6c65745f6f75747075742e646174756d0016302f30303030302c37540022a660540482c605c002646600200201e44a66605a002297ae013232533302b3375e6022605c6ea8008c044c0b8dd5180698171baa00e133030002330040040011330040040013031002302f001375c6058605a605a60526ea8060dd6981598141baa0131533302530013300a00d253330263330265333026301930283754601860526ea8c030c0a4dd5180418149baa00114a02945282511301c3330043756601060526ea8c020c0a4dd50009bae300c302937540406eb8c020c0a4dd50100a5014a22a6604c921296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a04a66604a6030604e6ea80045288a503330013756600a604c6ea8c014c098dd5003001a45044655454c00222325333026301a302837540022900009bad302c3029375400264a66604c603460506ea8004530103d87a8000132330010013756605a60546ea8008894ccc0b0004530103d87a80001323232533302b3371e00e6eb8c0b400c4c080cc0c0dd4000a5eb804cc014014008dd6981680118180011817000998020018011119198008008019129998148008a60103d87a8000132323253330283371e00c6eb8c0a800c4c074cc0b4dd3000a5eb804cc014014008dd59815001181680118158009bae3026302337540022a660429215b6578706563742053637269707443726564656e7469616c286675656c5f706f6c69637929203d0a20202020202070656c6c65745f696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c0016300530223754600a60446ea8c004c088dd5001118129813000981198101baa001153301e49013a65787065637420536f6d652870656c6c65745f696e70757429203d2066696e645f696e70757428696e707574732c2070656c6c65745f726566290016323300200523375e600860426ea8004008c088c07cdd50031119198008008019129998118008a60103d87a8000132325333021300500213016330260024bd7009980200200098138011812800918108008a9980da48122657870656374205370656e642870656c6c65745f72656629203d20707572706f736500163758603e604060400046eb0c078004c068dd5180e801180e180e800980c1baa001149854cc0592411856616c696461746f722072657475726e65642066616c7365001365632533301430070011325333019001153301601216132533301a301d002149854cc05c04c58c94cccccc07800454cc05c04c5854cc05c04c5854cc05c04c584dd68008a9980b8098b180d800980b9baa00215333014300800115333018301737540042930a9980a8088b0a9980a8088b180a9baa001533333301a0011001153301300f16153301300f16153301300f16153301300f163300100200e225333011300430133754004264a66602c0022a660260042c26464a6660300022a6602a0082c26464a6660340022a6602e00c2c264a666036603c0042930a9980c0038b19299999980f8008a9980c0038b0a9980c0038b0a9980c0038b0a9980c0038b09bae001301c001301c00232533333301d0011533016005161533016005161533016005161375a0022a6602c00a2c6034002603400464a6666660360022a660280062c2a660280062c2a660280062c26eb400454cc05000c58c060004c050dd50010a998090008b299999980b00388038a998078060b0a998078060b0a998078060b0a998078060b180a18089baa006370e90001b8748008dd2a40006e212000153300b00116153300b00116153300b00116153300b0011649191496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e00490195657870656374205b70656c6c65745f6f75747075745d203d0a2020202020202020202066696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d2070656c6c65745f696e7075742e6f75747075742e61646472657373207d2c0a202020202020202020202900490129657870656374206f75745f646174756d3a2050656c6c6574446174756d203d206f75745f646174756d0049011872656465656d65723a2050656c6c657452656465656d657200490112646174756d3a2050656c6c6574446174756d0049011672656465656d65723a204675656c52656465656d6572005734ae7155ceaab9e5573eae815d0aba257489812fd8799f581c516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d284c6173746572696141646d696eff0001"; + +pub async fn create_ship( + db: &Db, + client: &HttpClient, + keystore: &LocalKeystore, + args: CreateShipArgs, +) -> anyhow::Result<()> { + log::debug!("The args are:: {:?}", args); + + let asteria_script: PlutusScript = PlutusScript(hex::decode(ASTERIA_SCRIPT_HEX).unwrap()); + let asteria_hash: PolicyId = compute_plutus_v2_script_hash(asteria_script.clone()); + let asteria_address: Address = + Address(hex::decode("70".to_owned() + &hex::encode(asteria_hash)).unwrap()); + + let spacetime_script: PlutusScript = PlutusScript(hex::decode(SHIP_SCRIPT_HEX).unwrap()); + let spacetime_hash: PolicyId = compute_plutus_v2_script_hash(spacetime_script.clone()); + let spacetime_address: Address = + Address(hex::decode("70".to_owned() + &hex::encode(spacetime_hash)).unwrap()); + + let pellet_script: PlutusScript = PlutusScript(hex::decode(PELLET_SCRIPT_HEX).unwrap()); + let pellet_policy: PolicyId = compute_plutus_v2_script_hash(pellet_script.clone()); + + // Construct a template Transaction to push coins into later + let mut transaction = Transaction::from((Vec::new(), Vec::new())); + + if let Some((owner_pubkey, owner_value, _)) = sync::get_unspent(db, &args.input)? { + let asterias = sync::get_outputs_at( + db, + ShowOutputsAtArgs { + address: asteria_address.clone(), + }, + )?; + + if asterias.len() != 1 { + Err(anyhow!( + "There must be exactly one Asteria UTxO, but found {}", + asterias.len() + ))?; + } + let asteria_input = &asterias[0]; + let asteria_datum_option = asteria_input + .datum_option + .clone() + .map(|d| AsteriaDatum::from(d)); + + if let Some(AsteriaDatum::Ok { + ship_counter, + shipyard_policy, + }) = asteria_datum_option + { + // Asset Names + let ship_name = AssetName::from("SHIP".to_string() + &ship_counter.to_string()); + let pilot_name = AssetName::from("PILOT".to_string() + &ship_counter.to_string()); + let fuel_name = AssetName::from("FUEL".to_string()); + + // MINTS + let mint = Some( + Multiasset::from((spacetime_hash, ship_name.clone(), 1)) + + Multiasset::from((spacetime_hash, pilot_name.clone(), 1)) + + Multiasset::from((pellet_policy, fuel_name.clone(), 30)), + ); + + let mut inputs = vec![asteria_input.input.clone(), args.input]; + let ordered_inputs: Vec = { + // Lexicographically order inputs by tx_hash and index + inputs.sort_by(|a, b| { + if a.tx_hash == b.tx_hash { + a.index.cmp(&b.index) + } else { + a.tx_hash.cmp(&b.tx_hash) + } + }); + inputs.clone() + }; + + // BUILD REDEEMERS + let asteria_redeemer = Redeemer { + tag: RedeemerTag::Spend, + index: ordered_inputs + .iter() + .position(|i| *i == asteria_input.input) + .unwrap() as u32, + data: PlutusData::from(PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef([].to_vec()), + })), + }; + let ship_mint_redeemer = Redeemer { + tag: RedeemerTag::Mint, + index: 0, + data: PlutusData::from(PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef([].to_vec()), + })), + }; + let pellet_mint_redeemer = Redeemer { + tag: RedeemerTag::Mint, + index: 1, + data: PlutusData::from(PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef([].to_vec()), + })), + }; + + // BUILD DATUMS + let asteria_output_datum = PallasPlutusData::from(AsteriaDatum::Ok { + ship_counter: ship_counter + 1, + shipyard_policy, + }); + + let ship_datum = PallasPlutusData::from(PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef( + [ + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + args.pos_x, + )))), + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + args.pos_y, + )))), + PallasPlutusData::BoundedBytes(BoundedBytes(ship_name.0.clone().into())), + PallasPlutusData::BoundedBytes(BoundedBytes(pilot_name.0.clone().into())), + PallasPlutusData::BigInt(BigInt::BigUInt(BoundedBytes( + 1747081220000_u64.to_be_bytes().to_vec(), + ))), + ] + .to_vec(), + ), + })); + + transaction.transaction_body.inputs = inputs; + + let outputs = vec![ + Output { + address: owner_pubkey, + value: owner_value - Value::Coin(SHIP_FEE) - Value::Coin(10) + + Value::from((spacetime_hash, pilot_name.clone(), 1)), + datum_option: None, + }, + Output { + address: asteria_address, + value: asteria_input.value.clone() + Value::Coin(SHIP_FEE), + datum_option: Some(Datum(PlutusData::from(asteria_output_datum.clone()).0)), + }, + Output { + address: spacetime_address, + value: Value::Coin(10) + + Value::from((spacetime_hash, ship_name.clone(), 1)) + + Value::from((pellet_policy, fuel_name.clone(), 30)), + datum_option: Some(Datum(PlutusData::from(ship_datum.clone()).0)), + }, + ]; + + for output in outputs { + transaction.transaction_body.outputs.push(output.clone()); + } + + transaction.transaction_body.mint = mint; + transaction.transaction_body.ttl = Some(args.ttl); + + let pallas_tx: PallasTransaction = <_>::from(transaction.clone()); + let cbor_bytes: Vec = babbage_tx_to_cbor(&pallas_tx); + let mtx: MintedTx = babbage_minted_tx_from_cbor(&cbor_bytes); + let tx_hash: &Vec = &Vec::from(mtx.transaction_body.original_hash().as_ref()); + log::debug!("Original tx_body hash is: {:#x?}", tx_hash); + + let vkey: Vec = Vec::from(args.witness.0); + let public = Public::from_h256(args.witness); + let signature: Vec = + Vec::from(crate::keystore::sign_with(keystore, &public, tx_hash)?.0); + transaction.transaction_witness_set = + <_>::from(vec![VKeyWitness::from((vkey, signature))]); + + transaction.transaction_witness_set.redeemer = Some(vec![ + asteria_redeemer, + ship_mint_redeemer, + pellet_mint_redeemer, + ]); + transaction.transaction_witness_set.plutus_script = + Some(vec![asteria_script, spacetime_script, pellet_script]); + + log::debug!("Griffin transaction is: {:#x?}", transaction); + let pallas_tx: PallasTransaction = <_>::from(transaction.clone()); + log::debug!("Babbage transaction is: {:#x?}", pallas_tx); + + // Send the transaction + let genesis_spend_hex = hex::encode(Encode::encode(&transaction)); + let params = rpc_params![genesis_spend_hex]; + let genesis_spend_response: Result = + client.request("author_submitExtrinsic", params).await; + log::info!( + "Node's response to spend transaction: {:?}", + genesis_spend_response + ); + if let Err(_) = genesis_spend_response { + Err(anyhow!("Node did not accept the transaction"))?; + } else { + println!( + "Transaction queued. When accepted, the following UTxOs will become available:" + ); + // Print new output refs for user to check later + let tx_hash = ::hash_of(&Encode::encode(&transaction)); + for (i, output) in transaction.transaction_body.outputs.iter().enumerate() { + let new_value_ref = Input { + tx_hash, + index: i as u32, + }; + let amount = &output.value; + + println!( + "{:?} worth {amount:?}.", + hex::encode(Encode::encode(&new_value_ref)) + ); + } + } + + Ok(()) + } else { + Err(anyhow!("Malformed Asteria Datum"))? + } + } else { + Err(anyhow!( + "Warning: User-specified utxo {:x?} not found in wallet database", + args.input + )) + } +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum AsteriaDatum { + Ok { + ship_counter: u16, + shipyard_policy: PolicyId, + }, + MalformedAsteriaDatum, +} + +impl From for Datum { + fn from(order_datum: AsteriaDatum) -> Self { + Datum(PlutusData::from(PallasPlutusData::from(order_datum)).0) + } +} + +impl From for AsteriaDatum { + fn from(datum: Datum) -> Self { + <_>::from(PallasPlutusData::from(PlutusData(datum.0))) + } +} + +impl From for PallasPlutusData { + fn from(order_datum: AsteriaDatum) -> Self { + match order_datum { + AsteriaDatum::Ok { + ship_counter, + shipyard_policy, + } => PallasPlutusData::from(PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef( + [ + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + ship_counter, + )))), + PallasPlutusData::BoundedBytes(BoundedBytes(shipyard_policy.0.to_vec())), + ] + .to_vec(), + ), + })), + AsteriaDatum::MalformedAsteriaDatum => { + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from(-1)))) + } + } + } +} + +impl From for AsteriaDatum { + fn from(data: PallasPlutusData) -> Self { + if let PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef(asteria_datum), + }) = data + { + if let [PallasPlutusData::BigInt(BigInt::Int(Int(ship_counter))), PallasPlutusData::BoundedBytes(BoundedBytes(shipyard_policy_vec))] = + &asteria_datum[..] + { + AsteriaDatum::Ok { + ship_counter: TryFrom::::try_from(*ship_counter).unwrap(), + shipyard_policy: H224::from(PallasHash::from(shipyard_policy_vec.as_slice())), + } + } else { + AsteriaDatum::MalformedAsteriaDatum + } + } else { + AsteriaDatum::MalformedAsteriaDatum + } + } +} diff --git a/wallet/src/main.rs b/wallet/src/main.rs index 9919a10..e2ac6ae 100644 --- a/wallet/src/main.rs +++ b/wallet/src/main.rs @@ -37,6 +37,7 @@ use std::path::PathBuf; mod cli; mod command; +mod game; mod keystore; mod order_book; mod rpc; @@ -190,7 +191,7 @@ async fn main() -> anyhow::Result<()> { } Some(Command::ShowAllOutputs) => { println!("###### Unspent outputs ###########"); - sync::print_unspent_tree(&db)?; + sync::show_outputs(sync::print_unspent_tree(&db)?); println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); Ok(()) } @@ -199,7 +200,7 @@ async fn main() -> anyhow::Result<()> { "###### Unspent outputs at address {} ###########", args.address ); - sync::show_outputs_at(&db, args)?; + sync::show_outputs(sync::get_outputs_at(&db, args)?); println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); Ok(()) } @@ -208,7 +209,7 @@ async fn main() -> anyhow::Result<()> { "###### Unspent outputs containing asset with name {} and policy ID {} ###########", args.name, args.policy ); - sync::show_outputs_with_asset(&db, args)?; + sync::show_outputs(sync::get_outputs_with_asset(&db, args)?); println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); Ok(()) } @@ -218,6 +219,9 @@ async fn main() -> anyhow::Result<()> { Ok(()) } Some(cli::Command::BuildTx(args)) => command::build_tx(&db, &client, &keystore, args).await, + Some(cli::Command::CreateShip(args)) => { + game::create_ship(&db, &client, &keystore, args).await + } None => { log::info!("No Wallet Command invoked. Exiting."); Ok(()) diff --git a/wallet/src/sync.rs b/wallet/src/sync.rs index 58e04c9..dc19919 100644 --- a/wallet/src/sync.rs +++ b/wallet/src/sync.rs @@ -377,27 +377,27 @@ pub(crate) fn height(db: &Db) -> anyhow::Result> { } /// Debugging use. Print the entire unspent outputs tree. -pub(crate) fn print_unspent_tree(db: &Db) -> anyhow::Result<()> { - show_outputs_by(|_, _| true, db)?; - Ok(()) +pub(crate) fn print_unspent_tree(db: &Db) -> anyhow::Result> { + get_outputs_by(|_, _| true, db) } /// Print the unspent outputs at a specific address. -pub(crate) fn show_outputs_at(db: &Db, args: crate::cli::ShowOutputsAtArgs) -> anyhow::Result<()> { - show_outputs_by(|owner, _| *owner == args.address, db)?; - Ok(()) +pub(crate) fn get_outputs_at( + db: &Db, + args: crate::cli::ShowOutputsAtArgs, +) -> anyhow::Result> { + get_outputs_by(|owner, _| *owner == args.address, db) } /// Print the unspent outputs with a specific asset. -pub(crate) fn show_outputs_with_asset( +pub(crate) fn get_outputs_with_asset( db: &Db, args: crate::cli::ShowOutputsWithAssetArgs, -) -> anyhow::Result<()> { - show_outputs_by( +) -> anyhow::Result> { + get_outputs_by( |_, amount| amount.contains_asset(&AssetName::from(args.name.clone()), &args.policy), db, - )?; - Ok(()) + ) } /// Print the available orders. @@ -470,31 +470,45 @@ pub(crate) fn get_balances(db: &Db) -> anyhow::Result(f: F, db: &Db) -> anyhow::Result<()> +/// Print the unspent outputs info. +pub fn show_outputs(outputs_info: Vec) { + for x in outputs_info.iter() { + let input_string = hex::encode(x.input.encode()); + let datum_option_hex = x.datum_option.clone().map(|datum| hex::encode(datum.0)); + + println!( + "{}:\n address: {},\n datum: {:?},\n amount: {}", + input_string.bold(), + color_address(&x.address), + datum_option_hex, + x.value.normalize(), + ); + } +} + +/// Get the unspent outputs that satisfy the predicate `f`. +fn get_outputs_by(f: F, db: &Db) -> anyhow::Result> where F: Fn(&Address, &Value) -> bool, { - let wallet_unspent_tree = db.open_tree(UNSPENT)?; - for x in wallet_unspent_tree.iter() { + let mut result = Vec::new(); + for x in db.open_tree(UNSPENT)?.iter() { let (input_ivec, owner_amount_datum_ivec) = x?; - let input = hex::encode(input_ivec); + let input = ::decode(&mut &input_ivec[..])?; let (owner_pubkey, amount, datum_option) = <(Address, Value, Option)>::decode(&mut &owner_amount_datum_ivec[..])?; - let datum_option_hex = datum_option.map(|datum| hex::encode(datum.0)); if f(&owner_pubkey, &amount) { - println!( - "{}:\n address: {},\n datum: {:?},\n amount: {}", - input.bold(), - color_address(&owner_pubkey), - datum_option_hex, - amount.normalize(), - ); + result.push(ResolvedInputInfo::from(( + input, + owner_pubkey, + amount, + datum_option, + ))) } } - Ok(()) + Ok(result) } /// Color the address red if it's a script address (starts with "70"), green otherwise @@ -505,3 +519,21 @@ fn color_address(address: &Address) -> colored::ColoredString { address.to_string().green() } } + +pub struct ResolvedInputInfo { + pub input: Input, + pub address: Address, + pub value: Value, + pub datum_option: Option, +} + +impl From<(Input, Address, Value, Option)> for ResolvedInputInfo { + fn from((input, address, value, datum_option): (Input, Address, Value, Option)) -> Self { + Self { + input, + address, + value, + datum_option, + } + } +} From 17acce5851633e2281a89cd4d9093a524bdb3d71 Mon Sep 17 00:00:00 2001 From: Lola Aimar Date: Thu, 6 Nov 2025 21:28:45 -0300 Subject: [PATCH 02/20] wip: wallet refactor and new game module --- Cargo.lock | 21 ++++ Cargo.toml | 3 + game/Cargo.toml | 22 ++++ {wallet => game}/src/game.rs | 9 +- game/src/lib.rs | 65 ++++++++++++ node/Cargo.toml | 2 + node/src/cli.rs | 4 + node/src/command.rs | 5 + wallet/src/cli.rs | 50 +-------- wallet/src/command.rs | 5 +- wallet/src/context.rs | 119 ++++++++++++++++++++++ wallet/src/lib.rs | 8 ++ wallet/src/main.rs | 189 +++-------------------------------- wallet/src/rpc.rs | 2 +- wallet/src/sync.rs | 4 +- wallet/src/utils.rs | 66 ++++++++++++ 16 files changed, 344 insertions(+), 230 deletions(-) create mode 100644 game/Cargo.toml rename {wallet => game}/src/game.rs (99%) create mode 100644 game/src/lib.rs create mode 100644 wallet/src/context.rs create mode 100644 wallet/src/lib.rs create mode 100644 wallet/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 024a773..d4ca0bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3321,6 +3321,25 @@ dependencies = [ "byteorder", ] +[[package]] +name = "game" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "griffin-core", + "griffin-wallet", + "hex", + "jsonrpsee", + "log", + "parity-scale-codec", + "sc-cli", + "sc-keystore", + "sled", + "sp-core", + "sp-runtime", +] + [[package]] name = "generic-array" version = "0.12.4" @@ -3544,6 +3563,7 @@ dependencies = [ "docify", "futures", "futures-timer", + "game", "griffin-core", "griffin-partner-chains-runtime", "griffin-rpc", @@ -3570,6 +3590,7 @@ dependencies = [ "sp-runtime", "sp-timestamp", "substrate-build-script-utils", + "tokio", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 9e6d424..7e12abf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ members = [ "node", "runtime", "wallet", + "game", "toolkit/partner-chains-cli", "toolkit/cli/commands", "toolkit/cli/node-commands", @@ -76,6 +77,8 @@ zero-prefixed-literal = { level = "allow", priority = 2 } # 00_1000_0 griffin-core = { default-features = false, path = "griffin-core" } griffin-partner-chains-runtime = { path = "./runtime", default-features = false } griffin-rpc = { default-features = false, path = "griffin-rpc" } +griffin-wallet = { default-features = false, path = "wallet" } +game = { default-features = false, path = "game" } clap = { version = "4.5.13" } derive-new = { version = "0.7.0" } docify = { version = "0.2.9" } diff --git a/game/Cargo.toml b/game/Cargo.toml new file mode 100644 index 0000000..c725625 --- /dev/null +++ b/game/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "game" +description = "Game implementation" +version = "0.1.0" +repository.workspace = true +edition.workspace = true + +[dependencies] +anyhow = { workspace = true } +clap = { features = ["derive"], workspace = true } +griffin-core = { workspace = true } +griffin-wallet = { workspace = true } +hex = { workspace = true } +jsonrpsee = { workspace = true } +log = { workspace = true } +parity-scale-codec = { workspace = true } +sc-cli = { workspace = true } +sc-keystore = { workspace = true } +sp-core ={ workspace = true } +sp-runtime ={ workspace = true } + +sled = "0.34.7" \ No newline at end of file diff --git a/wallet/src/game.rs b/game/src/game.rs similarity index 99% rename from wallet/src/game.rs rename to game/src/game.rs index b5e1f08..5430434 100644 --- a/wallet/src/game.rs +++ b/game/src/game.rs @@ -1,7 +1,3 @@ -use crate::{ - cli::{CreateShipArgs, ShowOutputsAtArgs}, - sync, H224, -}; use anyhow::anyhow; use griffin_core::{ checks_interface::{babbage_minted_tx_from_cbor, babbage_tx_to_cbor}, @@ -9,6 +5,7 @@ use griffin_core::{ minicbor, utils::{Int, MaybeIndefArray::Indef}, }, + h224::H224, pallas_crypto::hash::Hash as PallasHash, pallas_primitives::babbage::{ BigInt, BoundedBytes, Constr, MintedTx, PlutusData as PallasPlutusData, @@ -20,12 +17,14 @@ use griffin_core::{ PlutusData, PlutusScript, PolicyId, Redeemer, RedeemerTag, Transaction, VKeyWitness, Value, }, }; +use griffin_wallet::{cli::ShowOutputsAtArgs, keystore, sync}; use jsonrpsee::{core::client::ClientT, http_client::HttpClient, rpc_params}; use parity_scale_codec::Encode; use sc_keystore::LocalKeystore; use sled::Db; use sp_core::ed25519::Public; use sp_runtime::traits::{BlakeTwo256, Hash}; +use crate::CreateShipArgs; const SHIP_FEE: Coin = 3000000; @@ -205,7 +204,7 @@ pub async fn create_ship( let vkey: Vec = Vec::from(args.witness.0); let public = Public::from_h256(args.witness); let signature: Vec = - Vec::from(crate::keystore::sign_with(keystore, &public, tx_hash)?.0); + Vec::from(keystore::sign_with(keystore, &public, tx_hash)?.0); transaction.transaction_witness_set = <_>::from(vec![VKeyWitness::from((vkey, signature))]); diff --git a/game/src/lib.rs b/game/src/lib.rs new file mode 100644 index 0000000..82bb953 --- /dev/null +++ b/game/src/lib.rs @@ -0,0 +1,65 @@ +mod game; + +use clap::{Subcommand, Args}; +use griffin_core::types::Input; +use griffin_wallet::{context::Context, keystore, utils}; +use sp_core::H256; + +#[derive(Debug, Subcommand)] +pub enum GameCommand { + /// Create a ship to play the Asteria game + CreateShip(CreateShipArgs), +} + +impl GameCommand { + pub async fn run(&self) -> sc_cli::Result<()> { + let Context {cli, client, db, keystore, .. } = Context::::load_context().await.unwrap(); + match cli.command { + Some(GameCommand::CreateShip(args)) => { + let _ = game::create_ship(&db, &client, &keystore, args).await; + Ok(()) + } + None => { + log::info!("No Wallet Command invoked. Exiting."); + Ok(()) + } + } + } +} + +#[derive(Debug, Args)] +pub struct CreateShipArgs { + /// An input to be consumed by this transaction. This argument may be specified multiple times. + #[arg(long, short, verbatim_doc_comment, value_parser = utils::input_from_string, required = true, value_name = "WALLET_OUTPUT_REF")] + pub input: Input, + + /// 32-byte H256 public key of an input owner. + /// Their pk/sk pair must be registered in the wallet's keystore. + #[arg(long, verbatim_doc_comment, value_parser = utils::h256_from_string, default_value = keystore::SHAWN_PUB_KEY, value_name = "PUBLIC_KEY")] + pub witness: H256, + + #[arg( + long, + verbatim_doc_comment, + required = true, + value_name = "POS_X" + )] + pub pos_x: i16, + + #[arg( + long, + verbatim_doc_comment, + required = true, + value_name = "POS_Y" + )] + pub pos_y: i16, + + #[arg( + long, + short, + verbatim_doc_comment, + required = true, + value_name = "TIME_TO_LIVE" + )] + pub ttl: u64, +} \ No newline at end of file diff --git a/node/Cargo.toml b/node/Cargo.toml index b71e9e1..c7503c1 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -21,6 +21,7 @@ futures-timer = { workspace = true } griffin-core = { workspace = true } griffin-partner-chains-runtime = { workspace = true } griffin-rpc = { workspace = true } +game = { workspace = true } jsonrpsee = { features = ["server"], workspace = true } sc-basic-authorship = { workspace = true } sc-cli = { workspace = true } @@ -41,6 +42,7 @@ sp-genesis-builder = { workspace = true } sp-io = { workspace = true } sp-timestamp = { workspace = true } sp-runtime = { workspace = true } +tokio = { workspace = true } partner-chains-node-commands = { workspace = true } partner-chains-cli = { workspace = true } diff --git a/node/src/cli.rs b/node/src/cli.rs index f9e929d..7000262 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -1,6 +1,7 @@ use griffin_partner_chains_runtime::opaque::SessionKeys; use partner_chains_cli::{KeyDefinition, AURA, GRANDPA}; use partner_chains_node_commands::{PartnerChainRuntime, PartnerChainsSubcommand}; +use game::GameCommand; #[derive(Debug, Clone)] pub enum Consensus { @@ -103,6 +104,9 @@ pub enum Subcommand { /// Key management cli utilities #[command(subcommand)] Key(sc_cli::KeySubcommand), + + #[command(subcommand)] + Game(GameCommand), #[clap(flatten)] PartnerChains(PartnerChainsSubcommand), diff --git a/node/src/command.rs b/node/src/command.rs index 2c3d5eb..8e82d7b 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -5,6 +5,7 @@ use crate::{ }; use sc_cli::SubstrateCli; use sc_service::PartialComponents; +use tokio::runtime::Runtime; impl SubstrateCli for Cli { fn impl_name() -> String { @@ -50,6 +51,10 @@ pub fn run() -> sc_cli::Result<()> { match &cli.subcommand { Some(Subcommand::Key(cmd)) => cmd.run(&cli), + Some(Subcommand::Game(cmd)) => { + let rt = Runtime::new().unwrap(); + rt.block_on(cmd.run()) + }, Some(Subcommand::PartnerChains(cmd)) => { partner_chains_node_commands::run::< // _, diff --git a/wallet/src/cli.rs b/wallet/src/cli.rs index 0d687f0..36b9b30 100644 --- a/wallet/src/cli.rs +++ b/wallet/src/cli.rs @@ -3,17 +3,18 @@ use std::path::PathBuf; use crate::{ - address_from_string, h224_from_string, h256_from_string, input_from_string, + utils::{address_from_string, h224_from_string, h256_from_string, input_from_string}, keystore::{SHAWN_ADDRESS, SHAWN_PUB_KEY}, - DEFAULT_ENDPOINT, H256, + context::DEFAULT_ENDPOINT, }; use clap::{ArgAction::Append, Args, Parser, Subcommand}; use griffin_core::types::{Address, Coin, Input, PolicyId}; +use sp_core::H256; /// The wallet's main CLI struct #[derive(Debug, Parser)] #[command(about, version)] -pub struct Cli { +pub struct Cli { #[arg(long, short, default_value_t = DEFAULT_ENDPOINT.to_string())] /// RPC endpoint of the node that this wallet will connect to. pub endpoint: String, @@ -42,7 +43,7 @@ pub struct Cli { pub purge_db: bool, #[command(subcommand)] - pub command: Option, + pub command: Option, } /// The tasks supported by the wallet @@ -105,8 +106,6 @@ pub enum Command { /// Build a complete Griffin transaction from a JSON file containing all the necessary information. BuildTx(BuildTxArgs), - - CreateShip(CreateShipArgs), } /// Arguments for building a complete Griffin transaction. @@ -186,45 +185,6 @@ pub struct SpendValueArgs { pub token_amount: Vec, } -#[derive(Debug, Args)] -pub struct CreateShipArgs { - /// An input to be consumed by this transaction. This argument may be specified multiple times. - #[arg(long, short, verbatim_doc_comment, value_parser = input_from_string, required = true, value_name = "WALLET_OUTPUT_REF")] - pub input: Input, - - /// 32-byte H256 public key of an input owner. - /// Their pk/sk pair must be registered in the wallet's keystore. - #[arg(long, short, verbatim_doc_comment, value_parser = h256_from_string, default_value = SHAWN_PUB_KEY, value_name = "PUBLIC_KEY")] - pub witness: H256, - - #[arg( - long, - short, - verbatim_doc_comment, - required = true, - value_name = "POS_X" - )] - pub pos_x: i16, - - #[arg( - long, - short, - verbatim_doc_comment, - required = true, - value_name = "POS_Y" - )] - pub pos_y: i16, - - #[arg( - long, - short, - verbatim_doc_comment, - required = true, - value_name = "TIME_TO_LIVE" - )] - pub ttl: u64, -} - #[derive(Debug, Args)] pub struct ShowOutputsAtArgs { /// 29-byte hash-address. diff --git a/wallet/src/command.rs b/wallet/src/command.rs index 67ef579..67c79ef 100644 --- a/wallet/src/command.rs +++ b/wallet/src/command.rs @@ -1,7 +1,7 @@ use crate::{ cli::{BuildTxArgs, SpendValueArgs}, keystore::SHAWN_ADDRESS, - sync, H224, H256, + sync, }; use anyhow::anyhow; use griffin_core::{ @@ -9,6 +9,7 @@ use griffin_core::{ genesis::config_builder::{ transp_to_multiasset, transp_to_output, TransparentMultiasset, TransparentOutput, }, + h224::H224, pallas_primitives::babbage::{MintedTx, Tx as PallasTransaction}, pallas_traverse::OriginalHash, types::{ @@ -22,7 +23,7 @@ use parity_scale_codec::Encode; use sc_keystore::LocalKeystore; use serde::{Deserialize, Serialize}; use sled::Db; -use sp_core::ed25519::Public; +use sp_core::{H256, ed25519::Public}; use sp_runtime::traits::{BlakeTwo256, Hash}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] diff --git a/wallet/src/context.rs b/wallet/src/context.rs new file mode 100644 index 0000000..4476069 --- /dev/null +++ b/wallet/src/context.rs @@ -0,0 +1,119 @@ +use crate::{sync, rpc, cli::Cli}; +use clap::Parser; +use jsonrpsee::http_client::{HttpClient, HttpClientBuilder}; +use std::path::PathBuf; + +/// The default RPC endpoint for the wallet to connect to +pub const DEFAULT_ENDPOINT: &str = "http://localhost:9944"; + +pub struct Context { + pub cli: Cli, + pub client: HttpClient, + pub db: sled::Db, + pub keystore: sc_keystore::LocalKeystore, + pub data_path: PathBuf, + pub keystore_path: PathBuf, +} + +impl Context { + pub async fn load_context() -> anyhow::Result> { + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); + + // Parse command line args + let cli = Cli::::parse(); + + // If the user specified --tmp or --dev, then use a temporary directory. + let tmp = cli.tmp || cli.dev; + + // Setup the data paths. + let data_path = match tmp { + true => temp_dir(), + _ => cli.base_path.clone().unwrap_or_else(default_data_path), + }; + let keystore_path = data_path.join("keystore"); + let db_path = data_path.join("wallet_database"); + + // Setup the keystore + let keystore = sc_keystore::LocalKeystore::open(keystore_path.clone(), None)?; + + if cli.dev { + // Insert the example Shawn key so example transactions can be signed. + crate::keystore::insert_development_key_for_this_session(&keystore)?; + } + + // Setup jsonrpsee and endpoint-related information. + // https://github.com/paritytech/jsonrpsee/blob/master/examples/examples/http.rs + let client = HttpClientBuilder::default().build(&cli.endpoint)?; + + // Read node's genesis block. + let node_genesis_hash = rpc::node_get_block_hash(0, &client) + .await? + .expect("node should be able to return some genesis hash"); + let node_genesis_block = rpc::node_get_block(node_genesis_hash, &client) + .await? + .expect("node should be able to return some genesis block"); + log::debug!("Node's Genesis block::{:?}", node_genesis_hash); + + if cli.purge_db { + std::fs::remove_dir_all(db_path.clone()).map_err(|e| { + log::warn!( + "Unable to remove database directory at {}\nPlease remove it manually.", + db_path.to_string_lossy() + ); + e + })?; + } + + // Open the local database + let db = sync::open_db(db_path, node_genesis_hash, node_genesis_block.clone())?; + + let num_blocks = + sync::height(&db)?.expect("db should be initialized automatically when opening."); + log::info!("Number of blocks in the db: {num_blocks}"); + + if !sled::Db::was_recovered(&db) { + sync::apply_block(&db, node_genesis_block, node_genesis_hash).await?; + } + + // Synchronize the wallet with attached node unless instructed otherwise. + if cli.no_sync { + log::warn!("Skipping sync with node. Using previously synced information.") + } else { + sync::synchronize(&db, &client).await?; + + log::info!( + "Wallet database synchronized with node to height {:?}", + sync::height(&db)?.expect("We just synced, so there is a height available") + ); + }; + + Ok(Context { + cli, client, db, keystore, data_path, keystore_path + }) + } +} + +/// Generate a plaform-specific temporary directory for the wallet +fn temp_dir() -> PathBuf { + // Since it is only used for testing purpose, we don't need a secure temp dir, just a unique one. + std::env::temp_dir().join(format!( + "griffin-wallet-{}", + std::time::UNIX_EPOCH.elapsed().unwrap().as_millis(), + )) +} + +/// Generate the platform-specific default data path for the wallet +fn default_data_path() -> PathBuf { + // This uses the directories crate. + // https://docs.rs/directories/latest/directories/struct.ProjectDirs.html + + // Application developers may want to put actual qualifiers or organization here + let qualifier = ""; + let organization = ""; + let application = env!("CARGO_PKG_NAME"); + + directories::ProjectDirs::from(qualifier, organization, application) + .expect("app directories exist on all supported platforms; qed") + .data_dir() + .into() +} \ No newline at end of file diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs new file mode 100644 index 0000000..b3abac1 --- /dev/null +++ b/wallet/src/lib.rs @@ -0,0 +1,8 @@ +pub mod sync; +pub mod command; +pub mod cli; +pub mod context; +pub mod rpc; +pub mod keystore; +pub mod utils; +pub mod order_book; \ No newline at end of file diff --git a/wallet/src/main.rs b/wallet/src/main.rs index e2ac6ae..5325cc9 100644 --- a/wallet/src/main.rs +++ b/wallet/src/main.rs @@ -22,111 +22,36 @@ extern crate alloc; -use alloc::{string::String, vec::Vec}; -use clap::Parser; +use alloc::{string::String}; use griffin_core::{ - h224::H224, pallas_crypto::hash::Hasher as PallasHasher, - types::{Address, Input, Value}, + types::Value, }; use hex::FromHex; -use jsonrpsee::http_client::{HttpClient, HttpClientBuilder}; -use parity_scale_codec::{Decode, Encode}; -use sp_core::H256; -use std::path::PathBuf; +use parity_scale_codec::{Encode}; mod cli; mod command; -mod game; mod keystore; mod order_book; mod rpc; mod sync; +mod context; +mod utils; -use cli::{Cli, Command}; - -/// The default RPC endpoint for the wallet to connect to -const DEFAULT_ENDPOINT: &str = "http://localhost:9944"; +use cli::{Command}; +use context::{Context}; #[tokio::main] async fn main() -> anyhow::Result<()> { - env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); - - // Parse command line args - let cli = Cli::parse(); - - // If the user specified --tmp or --dev, then use a temporary directory. - let tmp = cli.tmp || cli.dev; - - // Setup the data paths. - let data_path = match tmp { - true => temp_dir(), - _ => cli.base_path.unwrap_or_else(default_data_path), - }; - let keystore_path = data_path.join("keystore"); - let db_path = data_path.join("wallet_database"); - - // Setup the keystore - let keystore = sc_keystore::LocalKeystore::open(keystore_path.clone(), None)?; - - if cli.dev { - // Insert the example Shawn key so example transactions can be signed. - crate::keystore::insert_development_key_for_this_session(&keystore)?; - } - - // Setup jsonrpsee and endpoint-related information. - // https://github.com/paritytech/jsonrpsee/blob/master/examples/examples/http.rs - let client = HttpClientBuilder::default().build(cli.endpoint)?; - - // Read node's genesis block. - let node_genesis_hash = rpc::node_get_block_hash(0, &client) - .await? - .expect("node should be able to return some genesis hash"); - let node_genesis_block = rpc::node_get_block(node_genesis_hash, &client) - .await? - .expect("node should be able to return some genesis block"); - log::debug!("Node's Genesis block::{:?}", node_genesis_hash); - - if cli.purge_db { - std::fs::remove_dir_all(db_path.clone()).map_err(|e| { - log::warn!( - "Unable to remove database directory at {}\nPlease remove it manually.", - db_path.to_string_lossy() - ); - e - })?; - } - - // Open the local database - let db = sync::open_db(db_path, node_genesis_hash, node_genesis_block.clone())?; - - let num_blocks = - sync::height(&db)?.expect("db should be initialized automatically when opening."); - log::info!("Number of blocks in the db: {num_blocks}"); - - if !sled::Db::was_recovered(&db) { - sync::apply_block(&db, node_genesis_block, node_genesis_hash).await?; - } - - // Synchronize the wallet with attached node unless instructed otherwise. - if cli.no_sync { - log::warn!("Skipping sync with node. Using previously synced information.") - } else { - sync::synchronize(&db, &client).await?; - - log::info!( - "Wallet database synchronized with node to height {:?}", - sync::height(&db)?.expect("We just synced, so there is a height available") - ); - } - + let Context {cli, client, db, keystore, data_path, keystore_path } = Context::::load_context().await.unwrap(); // Dispatch to proper subcommand match cli.command { Some(Command::VerifyUtxo { input }) => { println!("Details of coin {}:", hex::encode(input.encode())); // Print the details from storage - let coin_from_storage = get_coin_from_storage(&input, &client).await?; + let coin_from_storage = utils::get_coin_from_storage(&input, &client).await?; print!("Found in storage. Value: {:?}, ", coin_from_storage); // Print the details from the local db @@ -144,13 +69,13 @@ async fn main() -> anyhow::Result<()> { Some(cli::Command::SpendValue(args)) => { command::spend_value(&db, &client, &keystore, args).await } - Some(Command::InsertKey { seed }) => crate::keystore::insert_key(&keystore, &seed), + Some(Command::InsertKey { seed }) => keystore::insert_key(&keystore, &seed), Some(Command::GenerateKey { password }) => { - crate::keystore::generate_key(&keystore, password)?; + keystore::generate_key(&keystore, password)?; Ok(()) } Some(Command::ShowKeys) => { - crate::keystore::get_keys(&keystore)?.for_each(|pubkey| { + keystore::get_keys(&keystore)?.for_each(|pubkey| { let pk_str: &str = &hex::encode(pubkey); let hash: String = PallasHasher::<224>::hash(&<[u8; 32]>::from_hex(pk_str).unwrap()).to_string(); @@ -170,7 +95,7 @@ async fn main() -> anyhow::Result<()> { .expect("Failed to read line"); if confirmation.trim() == "proceed" { - crate::keystore::remove_key(&keystore_path, &pub_key) + keystore::remove_key(&keystore_path, &pub_key) } else { println!("Deletion aborted. That was close."); Ok(()) @@ -219,16 +144,13 @@ async fn main() -> anyhow::Result<()> { Ok(()) } Some(cli::Command::BuildTx(args)) => command::build_tx(&db, &client, &keystore, args).await, - Some(cli::Command::CreateShip(args)) => { - game::create_ship(&db, &client, &keystore, args).await - } None => { log::info!("No Wallet Command invoked. Exiting."); Ok(()) } }?; - if tmp { + if cli.tmp || cli.dev { // Cleanup the temporary directory. std::fs::remove_dir_all(data_path.clone()).map_err(|e| { log::warn!( @@ -241,86 +163,3 @@ async fn main() -> anyhow::Result<()> { Ok(()) } - -/// Parse a string into an H256 that represents a public key -pub(crate) fn h256_from_string(s: &str) -> anyhow::Result { - let s = strip_0x_prefix(s); - - let mut bytes: [u8; 32] = [0; 32]; - hex::decode_to_slice(s, &mut bytes as &mut [u8]) - .map_err(|_| clap::Error::new(clap::error::ErrorKind::ValueValidation))?; - Ok(H256::from(bytes)) -} - -/// Parse a string into an H224 that represents a policy ID. -pub(crate) fn h224_from_string(s: &str) -> anyhow::Result { - let s = strip_0x_prefix(s); - - let mut bytes: [u8; 28] = [0; 28]; - hex::decode_to_slice(s, &mut bytes as &mut [u8]) - .map_err(|_| clap::Error::new(clap::error::ErrorKind::ValueValidation))?; - Ok(H224::from(bytes)) -} - -/// Parse a string into an Address that represents a public key -pub(crate) fn address_from_string(s: &str) -> anyhow::Result
{ - let s = strip_0x_prefix(s); - - let mut bytes: [u8; 29] = [0; 29]; - hex::decode_to_slice(s, &mut bytes as &mut [u8]) - .map_err(|_| clap::Error::new(clap::error::ErrorKind::ValueValidation))?; - Ok(Address(Vec::from(bytes))) -} - -/// Parse an output ref from a string -fn input_from_string(s: &str) -> Result { - let s = strip_0x_prefix(s); - let bytes = - hex::decode(s).map_err(|_| clap::Error::new(clap::error::ErrorKind::ValueValidation))?; - - Input::decode(&mut &bytes[..]) - .map_err(|_| clap::Error::new(clap::error::ErrorKind::ValueValidation)) -} - -/// Takes a string and checks for a 0x prefix. Returns a string without a 0x prefix. -fn strip_0x_prefix(s: &str) -> &str { - if &s[..2] == "0x" { - &s[2..] - } else { - s - } -} - -/// Generate a plaform-specific temporary directory for the wallet -fn temp_dir() -> PathBuf { - // Since it is only used for testing purpose, we don't need a secure temp dir, just a unique one. - std::env::temp_dir().join(format!( - "griffin-wallet-{}", - std::time::UNIX_EPOCH.elapsed().unwrap().as_millis(), - )) -} - -/// Generate the platform-specific default data path for the wallet -fn default_data_path() -> PathBuf { - // This uses the directories crate. - // https://docs.rs/directories/latest/directories/struct.ProjectDirs.html - - // Application developers may want to put actual qualifiers or organization here - let qualifier = ""; - let organization = ""; - let application = env!("CARGO_PKG_NAME"); - - directories::ProjectDirs::from(qualifier, organization, application) - .expect("app directories exist on all supported platforms; qed") - .data_dir() - .into() -} - -/// Given an output ref, fetch the details about its value from the node's -/// storage. -async fn get_coin_from_storage(input: &Input, client: &HttpClient) -> anyhow::Result { - let utxo = rpc::fetch_storage(input, client).await?; - let coin_in_storage: Value = utxo.value; - - Ok(coin_in_storage) -} diff --git a/wallet/src/rpc.rs b/wallet/src/rpc.rs index 77235ce..5637315 100644 --- a/wallet/src/rpc.rs +++ b/wallet/src/rpc.rs @@ -9,7 +9,7 @@ use sp_core::H256; pub async fn node_get_block_hash(height: u32, client: &HttpClient) -> anyhow::Result> { let params = rpc_params![Some(height)]; let rpc_response: Option = client.request("chain_getBlockHash", params).await?; - let maybe_hash = rpc_response.map(|s| crate::h256_from_string(&s).unwrap()); + let maybe_hash = rpc_response.map(|s| crate::utils::h256_from_string(&s).unwrap()); Ok(maybe_hash) } diff --git a/wallet/src/sync.rs b/wallet/src/sync.rs index dc19919..8ce5c30 100644 --- a/wallet/src/sync.rs +++ b/wallet/src/sync.rs @@ -167,7 +167,7 @@ pub(crate) async fn synchronize_helper(db: &Db, client: &HttpClient) -> anyhow:: /// Gets the owner and amount associated with an input from the unspent table /// /// Some if the input exists, None if it doesn't -pub(crate) fn get_unspent( +pub fn get_unspent( db: &Db, input: &Input, ) -> anyhow::Result)>> { @@ -382,7 +382,7 @@ pub(crate) fn print_unspent_tree(db: &Db) -> anyhow::Result anyhow::Result> { diff --git a/wallet/src/utils.rs b/wallet/src/utils.rs new file mode 100644 index 0000000..ceb95fc --- /dev/null +++ b/wallet/src/utils.rs @@ -0,0 +1,66 @@ +use griffin_core::{ + h224::H224, + types::{Address, Input, Value}, +}; +use parity_scale_codec::{Decode}; +use sp_core::H256; + +use crate::rpc; + +/// Parse a string into an H256 that represents a public key +pub fn h256_from_string(s: &str) -> anyhow::Result { + let s = strip_0x_prefix(s); + + let mut bytes: [u8; 32] = [0; 32]; + hex::decode_to_slice(s, &mut bytes as &mut [u8]) + .map_err(|_| clap::Error::new(clap::error::ErrorKind::ValueValidation))?; + Ok(H256::from(bytes)) +} + +/// Parse a string into an H224 that represents a policy ID. +pub(crate) fn h224_from_string(s: &str) -> anyhow::Result { + let s = strip_0x_prefix(s); + + let mut bytes: [u8; 28] = [0; 28]; + hex::decode_to_slice(s, &mut bytes as &mut [u8]) + .map_err(|_| clap::Error::new(clap::error::ErrorKind::ValueValidation))?; + Ok(H224::from(bytes)) +} + +/// Parse a string into an Address that represents a public key +pub(crate) fn address_from_string(s: &str) -> anyhow::Result
{ + let s = strip_0x_prefix(s); + + let mut bytes: [u8; 29] = [0; 29]; + hex::decode_to_slice(s, &mut bytes as &mut [u8]) + .map_err(|_| clap::Error::new(clap::error::ErrorKind::ValueValidation))?; + Ok(Address(Vec::from(bytes))) +} + +/// Parse an output ref from a string +pub fn input_from_string(s: &str) -> Result { + let s = strip_0x_prefix(s); + let bytes = + hex::decode(s).map_err(|_| clap::Error::new(clap::error::ErrorKind::ValueValidation))?; + + Input::decode(&mut &bytes[..]) + .map_err(|_| clap::Error::new(clap::error::ErrorKind::ValueValidation)) +} + +/// Takes a string and checks for a 0x prefix. Returns a string without a 0x prefix. +fn strip_0x_prefix(s: &str) -> &str { + if &s[..2] == "0x" { + &s[2..] + } else { + s + } +} + +/// Given an output ref, fetch the details about its value from the node's +/// storage. +pub async fn get_coin_from_storage(input: &Input, client: &jsonrpsee::http_client::HttpClient) -> anyhow::Result { + let utxo = rpc::fetch_storage(input, client).await?; + let coin_in_storage: Value = utxo.value; + + Ok(coin_in_storage) +} From d5f2e31b6907224b6938f0229e584f1711eacf26 Mon Sep 17 00:00:00 2001 From: Lola Aimar Date: Fri, 7 Nov 2025 14:38:58 -0300 Subject: [PATCH 03/20] fixes command --- game/src/lib.rs | 4 ++-- node/src/cli.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/game/src/lib.rs b/game/src/lib.rs index 82bb953..7ebef94 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -5,7 +5,7 @@ use griffin_core::types::Input; use griffin_wallet::{context::Context, keystore, utils}; use sp_core::H256; -#[derive(Debug, Subcommand)] +#[derive(Clone, Debug, Subcommand)] pub enum GameCommand { /// Create a ship to play the Asteria game CreateShip(CreateShipArgs), @@ -27,7 +27,7 @@ impl GameCommand { } } -#[derive(Debug, Args)] +#[derive(Debug, Args, Clone)] pub struct CreateShipArgs { /// An input to be consumed by this transaction. This argument may be specified multiple times. #[arg(long, short, verbatim_doc_comment, value_parser = utils::input_from_string, required = true, value_name = "WALLET_OUTPUT_REF")] diff --git a/node/src/cli.rs b/node/src/cli.rs index 7000262..33c3394 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -104,8 +104,8 @@ pub enum Subcommand { /// Key management cli utilities #[command(subcommand)] Key(sc_cli::KeySubcommand), - - #[command(subcommand)] + + #[clap(flatten)] Game(GameCommand), #[clap(flatten)] From f5b2e5818a5a04c0aabba2a8eab22c57e881aae1 Mon Sep 17 00:00:00 2001 From: Lola Aimar Date: Mon, 10 Nov 2025 18:39:17 -0300 Subject: [PATCH 04/20] groups commands and adds wallet cmd to node --- Cargo.lock | 2 + game/src/lib.rs | 20 ++++-- node/Cargo.toml | 1 + node/src/cli.rs | 7 +- node/src/command.rs | 8 ++- wallet/Cargo.toml | 1 + wallet/src/cli.rs | 156 ++++++++++++++++++++++++++++++++++++++++++-- wallet/src/main.rs | 132 +------------------------------------ 8 files changed, 181 insertions(+), 146 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d4ca0bb..b0b0d84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3567,6 +3567,7 @@ dependencies = [ "griffin-core", "griffin-partner-chains-runtime", "griffin-rpc", + "griffin-wallet", "jsonrpsee", "partner-chains-cli", "partner-chains-node-commands", @@ -3660,6 +3661,7 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", + "sc-cli", "sc-keystore", "serde", "serde_json", diff --git a/game/src/lib.rs b/game/src/lib.rs index 7ebef94..04461fa 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -7,7 +7,13 @@ use sp_core::H256; #[derive(Clone, Debug, Subcommand)] pub enum GameCommand { - /// Create a ship to play the Asteria game + #[command(subcommand)] + Game(Command), +} + +#[derive(Clone, Debug, Subcommand)] +pub enum Command { + /// Create a ship to enter the game CreateShip(CreateShipArgs), } @@ -15,12 +21,14 @@ impl GameCommand { pub async fn run(&self) -> sc_cli::Result<()> { let Context {cli, client, db, keystore, .. } = Context::::load_context().await.unwrap(); match cli.command { - Some(GameCommand::CreateShip(args)) => { - let _ = game::create_ship(&db, &client, &keystore, args).await; - Ok(()) - } + Some(GameCommand::Game(cmd)) => match cmd { + Command::CreateShip(args) => { + let _ = game::create_ship(&db, &client, &keystore, args).await; + Ok(()) + } + }, None => { - log::info!("No Wallet Command invoked. Exiting."); + log::info!(" Asteria game"); Ok(()) } } diff --git a/node/Cargo.toml b/node/Cargo.toml index c7503c1..a939a52 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -21,6 +21,7 @@ futures-timer = { workspace = true } griffin-core = { workspace = true } griffin-partner-chains-runtime = { workspace = true } griffin-rpc = { workspace = true } +griffin-wallet = { workspace = true } game = { workspace = true } jsonrpsee = { features = ["server"], workspace = true } sc-basic-authorship = { workspace = true } diff --git a/node/src/cli.rs b/node/src/cli.rs index 33c3394..91333f9 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -2,6 +2,7 @@ use griffin_partner_chains_runtime::opaque::SessionKeys; use partner_chains_cli::{KeyDefinition, AURA, GRANDPA}; use partner_chains_node_commands::{PartnerChainRuntime, PartnerChainsSubcommand}; use game::GameCommand; +use griffin_wallet::cli::WalletCommand; #[derive(Debug, Clone)] pub enum Consensus { @@ -104,7 +105,11 @@ pub enum Subcommand { /// Key management cli utilities #[command(subcommand)] Key(sc_cli::KeySubcommand), - + + #[clap(flatten)] + Wallet(WalletCommand), + + /// Commands to play the Asteria game #[clap(flatten)] Game(GameCommand), diff --git a/node/src/command.rs b/node/src/command.rs index 8e82d7b..c53869b 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -51,9 +51,15 @@ pub fn run() -> sc_cli::Result<()> { match &cli.subcommand { Some(Subcommand::Key(cmd)) => cmd.run(&cli), + Some(Subcommand::Wallet(cmd)) => { + let rt = Runtime::new().unwrap(); + let _ = rt.block_on(cmd.run()); + Ok(()) + }, Some(Subcommand::Game(cmd)) => { let rt = Runtime::new().unwrap(); - rt.block_on(cmd.run()) + let _ = rt.block_on(cmd.run()); + Ok(()) }, Some(Subcommand::PartnerChains(cmd)) => { partner_chains_node_commands::run::< diff --git a/wallet/Cargo.toml b/wallet/Cargo.toml index c7de19c..8ac9d70 100644 --- a/wallet/Cargo.toml +++ b/wallet/Cargo.toml @@ -17,6 +17,7 @@ parity-scale-codec = { workspace = true } serde_json = { workspace = true } serde = { workspace = true } +sc-cli = { workspace = true } sp-core = { workspace = true } sp-runtime = { workspace = true } diff --git a/wallet/src/cli.rs b/wallet/src/cli.rs index 36b9b30..3393ab3 100644 --- a/wallet/src/cli.rs +++ b/wallet/src/cli.rs @@ -1,14 +1,23 @@ //! Test Wallet's Command Line Interface. +extern crate alloc; + use std::path::PathBuf; use crate::{ utils::{address_from_string, h224_from_string, h256_from_string, input_from_string}, keystore::{SHAWN_ADDRESS, SHAWN_PUB_KEY}, - context::DEFAULT_ENDPOINT, + context::{DEFAULT_ENDPOINT, Context}, + command, sync, keystore, utils }; +use alloc::{string::String}; use clap::{ArgAction::Append, Args, Parser, Subcommand}; -use griffin_core::types::{Address, Coin, Input, PolicyId}; +use griffin_core::{ + pallas_crypto::hash::Hasher as PallasHasher, + types::{Address, Coin, Input, Value, PolicyId}, +}; +use hex::FromHex; +use parity_scale_codec::{Encode}; use sp_core::H256; /// The wallet's main CLI struct @@ -47,7 +56,140 @@ pub struct Cli { } /// The tasks supported by the wallet -#[derive(Debug, Subcommand)] +#[derive(Clone, Debug, Subcommand)] +pub enum WalletCommand { + #[command(subcommand)] + Wallet(Command) +} + +impl WalletCommand { + pub async fn run(&self) -> anyhow::Result<()> { + let Context {cli, client, db, keystore, data_path, keystore_path } = Context::::load_context().await.unwrap(); + // Dispatch to proper subcommand + match cli.command { + Some(WalletCommand::Wallet(cmd)) => + match cmd { + Command::VerifyUtxo { input } => { + println!("Details of coin {}:", hex::encode(input.encode())); + + // Print the details from storage + let coin_from_storage = utils::get_coin_from_storage(&input, &client).await?; + print!("Found in storage. Value: {:?}, ", coin_from_storage); + + // Print the details from the local db + match sync::get_unspent(&db, &input)? { + Some((owner, amount, _)) => { + println!("Found in local db. Value: {amount:?}, owned by {owner}"); + } + None => { + println!("Not found in local db"); + } + } + + Ok(()) + } + Command::SpendValue(args) => { + command::spend_value(&db, &client, &keystore, args).await + } + Command::InsertKey { seed } => keystore::insert_key(&keystore, &seed), + Command::GenerateKey { password } => { + keystore::generate_key(&keystore, password)?; + Ok(()) + } + Command::ShowKeys => { + keystore::get_keys(&keystore)?.for_each(|pubkey| { + let pk_str: &str = &hex::encode(pubkey); + let hash: String = + PallasHasher::<224>::hash(&<[u8; 32]>::from_hex(pk_str).unwrap()).to_string(); + println!("key: 0x{}; addr: 0x61{}", pk_str, hash); + }); + + Ok(()) + } + Command::RemoveKey { pub_key } => { + println!( + "CAUTION!!! About permanently remove {pub_key}. This action CANNOT BE REVERSED. Type \"proceed\" to confirm deletion." + ); + + let mut confirmation = String::new(); + std::io::stdin() + .read_line(&mut confirmation) + .expect("Failed to read line"); + + if confirmation.trim() == "proceed" { + keystore::remove_key(&keystore_path, &pub_key) + } else { + println!("Deletion aborted. That was close."); + Ok(()) + } + } + Command::ShowBalance => { + println!("Balance Summary"); + let mut total = Value::Coin(0); + let balances = sync::get_balances(&db)?; + for (account, balance) in balances { + total += balance.clone(); + println!("{account}: {balance}"); + } + println!("{:-<58}", ""); + println!("Total: {}", total.normalize()); + + Ok(()) + } + Command::ShowAllOutputs => { + println!("###### Unspent outputs ###########"); + sync::show_outputs(sync::print_unspent_tree(&db)?); + println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); + Ok(()) + } + Command::ShowOutputsAt(args) => { + println!( + "###### Unspent outputs at address {} ###########", + args.address + ); + sync::show_outputs(sync::get_outputs_at(&db, args)?); + println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); + Ok(()) + } + Command::ShowOutputsWithAsset(args) => { + println!( + "###### Unspent outputs containing asset with name {} and policy ID {} ###########", + args.name, args.policy + ); + sync::show_outputs(sync::get_outputs_with_asset(&db, args)?); + println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); + Ok(()) + } + Command::ShowAllOrders => { + println!("###### Available Orders ###########"); + sync::print_orders(&db)?; + Ok(()) + }, + Command::BuildTx(args) => command::build_tx(&db, &client, &keystore, args).await, + + }, + None => { + log::info!("No Wallet Command invoked. Exiting."); + Ok(()) + } + }?; + + if cli.tmp || cli.dev { + // Cleanup the temporary directory. + std::fs::remove_dir_all(data_path.clone()).map_err(|e| { + log::warn!( + "Unable to remove temporary data directory at {}\nPlease remove it manually.", + data_path.to_string_lossy() + ); + e + })?; + } + + Ok(()) + } +} + +#[derive(Clone, Debug, Subcommand)] pub enum Command { /// Verify that a particular output ref exists. /// Show its value and owner address from both chain storage and the local database. @@ -109,7 +251,7 @@ pub enum Command { } /// Arguments for building a complete Griffin transaction. -#[derive(Debug, Args)] +#[derive(Clone, Debug, Args)] pub struct BuildTxArgs { /// Path to the file containing all the transaction information in JSON format. /// There are example contracts and json files for testing this command in the `eutxo_examples` directory. @@ -153,7 +295,7 @@ pub struct BuildTxArgs { } /// Arguments for spending wallet inputs only. -#[derive(Debug, Args)] +#[derive(Clone, Debug, Args)] pub struct SpendValueArgs { /// An input to be consumed by this transaction. This argument may be specified multiple times. #[arg(long, short, verbatim_doc_comment, value_parser = input_from_string, required = true, value_name = "OUTPUT_REF")] @@ -185,14 +327,14 @@ pub struct SpendValueArgs { pub token_amount: Vec, } -#[derive(Debug, Args)] +#[derive(Clone, Debug, Args)] pub struct ShowOutputsAtArgs { /// 29-byte hash-address. #[arg(long, short, verbatim_doc_comment, value_parser = address_from_string, required = true, value_name = "ADDRESS")] pub address: Address, } -#[derive(Debug, Args)] +#[derive(Clone, Debug, Args)] pub struct ShowOutputsWithAssetArgs { /// Policy ID of the asset. #[arg(long, short, verbatim_doc_comment, value_parser = h224_from_string, required = true, value_name = "POLICY_ID")] diff --git a/wallet/src/main.rs b/wallet/src/main.rs index 5325cc9..ee2290d 100644 --- a/wallet/src/main.rs +++ b/wallet/src/main.rs @@ -20,16 +20,6 @@ //! ./target/release/griffin-wallet show-all-outputs //! ``` -extern crate alloc; - -use alloc::{string::String}; -use griffin_core::{ - pallas_crypto::hash::Hasher as PallasHasher, - types::Value, -}; -use hex::FromHex; -use parity_scale_codec::{Encode}; - mod cli; mod command; mod keystore; @@ -39,127 +29,7 @@ mod sync; mod context; mod utils; -use cli::{Command}; -use context::{Context}; - #[tokio::main] async fn main() -> anyhow::Result<()> { - let Context {cli, client, db, keystore, data_path, keystore_path } = Context::::load_context().await.unwrap(); - // Dispatch to proper subcommand - match cli.command { - Some(Command::VerifyUtxo { input }) => { - println!("Details of coin {}:", hex::encode(input.encode())); - - // Print the details from storage - let coin_from_storage = utils::get_coin_from_storage(&input, &client).await?; - print!("Found in storage. Value: {:?}, ", coin_from_storage); - - // Print the details from the local db - match sync::get_unspent(&db, &input)? { - Some((owner, amount, _)) => { - println!("Found in local db. Value: {amount:?}, owned by {owner}"); - } - None => { - println!("Not found in local db"); - } - } - - Ok(()) - } - Some(cli::Command::SpendValue(args)) => { - command::spend_value(&db, &client, &keystore, args).await - } - Some(Command::InsertKey { seed }) => keystore::insert_key(&keystore, &seed), - Some(Command::GenerateKey { password }) => { - keystore::generate_key(&keystore, password)?; - Ok(()) - } - Some(Command::ShowKeys) => { - keystore::get_keys(&keystore)?.for_each(|pubkey| { - let pk_str: &str = &hex::encode(pubkey); - let hash: String = - PallasHasher::<224>::hash(&<[u8; 32]>::from_hex(pk_str).unwrap()).to_string(); - println!("key: 0x{}; addr: 0x61{}", pk_str, hash); - }); - - Ok(()) - } - Some(Command::RemoveKey { pub_key }) => { - println!( - "CAUTION!!! About permanently remove {pub_key}. This action CANNOT BE REVERSED. Type \"proceed\" to confirm deletion." - ); - - let mut confirmation = String::new(); - std::io::stdin() - .read_line(&mut confirmation) - .expect("Failed to read line"); - - if confirmation.trim() == "proceed" { - keystore::remove_key(&keystore_path, &pub_key) - } else { - println!("Deletion aborted. That was close."); - Ok(()) - } - } - Some(Command::ShowBalance) => { - println!("Balance Summary"); - let mut total = Value::Coin(0); - let balances = sync::get_balances(&db)?; - for (account, balance) in balances { - total += balance.clone(); - println!("{account}: {balance}"); - } - println!("{:-<58}", ""); - println!("Total: {}", total.normalize()); - - Ok(()) - } - Some(Command::ShowAllOutputs) => { - println!("###### Unspent outputs ###########"); - sync::show_outputs(sync::print_unspent_tree(&db)?); - println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); - Ok(()) - } - Some(Command::ShowOutputsAt(args)) => { - println!( - "###### Unspent outputs at address {} ###########", - args.address - ); - sync::show_outputs(sync::get_outputs_at(&db, args)?); - println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); - Ok(()) - } - Some(Command::ShowOutputsWithAsset(args)) => { - println!( - "###### Unspent outputs containing asset with name {} and policy ID {} ###########", - args.name, args.policy - ); - sync::show_outputs(sync::get_outputs_with_asset(&db, args)?); - println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); - Ok(()) - } - Some(Command::ShowAllOrders) => { - println!("###### Available Orders ###########"); - sync::print_orders(&db)?; - Ok(()) - } - Some(cli::Command::BuildTx(args)) => command::build_tx(&db, &client, &keystore, args).await, - None => { - log::info!("No Wallet Command invoked. Exiting."); - Ok(()) - } - }?; - - if cli.tmp || cli.dev { - // Cleanup the temporary directory. - std::fs::remove_dir_all(data_path.clone()).map_err(|e| { - log::warn!( - "Unable to remove temporary data directory at {}\nPlease remove it manually.", - data_path.to_string_lossy() - ); - e - })?; - } - - Ok(()) + cli::WalletCommand::run().await } From 2265430c8a8dacf68e75be7914efa095ebdef7e1 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Tue, 11 Nov 2025 17:12:01 -0300 Subject: [PATCH 05/20] include `SLOT_LENGTH` in genesis config --- griffin-core/src/executive.rs | 11 +++++++++-- griffin-core/src/genesis/config_builder.rs | 4 +++- griffin-core/src/lib.rs | 2 +- runtime/src/genesis.rs | 1 + runtime/src/lib.rs | 3 +-- wallet/src/eutxo_examples/vesting/README.md | 4 ++-- 6 files changed, 17 insertions(+), 8 deletions(-) diff --git a/griffin-core/src/executive.rs b/griffin-core/src/executive.rs index 293f2a3..5594668 100644 --- a/griffin-core/src/executive.rs +++ b/griffin-core/src/executive.rs @@ -35,7 +35,7 @@ use crate::{ utxo_set::TransparentUtxoSet, EXTRINSIC_KEY, HEADER_KEY, HEIGHT_KEY, LOG_TARGET, }; -use crate::{MILLI_SECS_PER_SLOT, ZERO_SLOT, ZERO_TIME}; +use crate::{SLOT_LENGTH, ZERO_SLOT, ZERO_TIME}; use alloc::{collections::btree_set::BTreeSet, string::String, vec::Vec}; use log::debug; use parity_scale_codec::{Decode, Encode}; @@ -107,7 +107,7 @@ where let slot_config = SlotConfig { zero_time: Self::zero_time(), zero_slot: Self::zero_slot(), - slot_length: MILLI_SECS_PER_SLOT, + slot_length: Self::slot_length(), }; let phase_two_result = eval_phase_two( &conway_mtx, @@ -321,6 +321,13 @@ where .expect("Failed to read ZERO_SLOT from storage.") } + /// A helper function that allows griffin runtimes to read the millisecs per slot + pub fn slot_length() -> u32 { + sp_io::storage::get(SLOT_LENGTH) + .and_then(|d| u32::decode(&mut &*d).ok()) + .expect("Failed to read SLOT_LENGTH from storage.") + } + // These next three methods are for the block authoring workflow. // Open the block, apply zero or more extrinsics, close the block diff --git a/griffin-core/src/genesis/config_builder.rs b/griffin-core/src/genesis/config_builder.rs index 807e2b9..79ab3f7 100644 --- a/griffin-core/src/genesis/config_builder.rs +++ b/griffin-core/src/genesis/config_builder.rs @@ -7,7 +7,7 @@ use crate::{ types::{ address_from_hex, AssetName, Coin, EncapBTree, Input, Multiasset, Output, Transaction, }, - EXTRINSIC_KEY, UTXO_SET, ZERO_SLOT, ZERO_TIME, + EXTRINSIC_KEY, SLOT_LENGTH, UTXO_SET, ZERO_SLOT, ZERO_TIME, }; use alloc::{collections::BTreeMap, string::String, vec, vec::Vec}; @@ -40,6 +40,7 @@ pub struct TransparentOutput { pub struct GenesisConfig { pub zero_slot: u64, pub zero_time: u64, + pub slot_length: u32, pub outputs: Vec, } @@ -65,6 +66,7 @@ where sp_io::storage::set(EXTRINSIC_KEY, &transactions.encode()); sp_io::storage::set(ZERO_SLOT, &genesis_config.zero_slot.encode()); sp_io::storage::set(ZERO_TIME, &genesis_config.zero_time.encode()); + sp_io::storage::set(SLOT_LENGTH, &genesis_config.slot_length.encode()); for tx in transactions.into_iter() { // Enforce that transactions do not have any inputs. diff --git a/griffin-core/src/lib.rs b/griffin-core/src/lib.rs index dbdb216..fcc1b67 100644 --- a/griffin-core/src/lib.rs +++ b/griffin-core/src/lib.rs @@ -37,7 +37,7 @@ pub mod utxo_set; pub use executive::Executive; /// The Aura slot duration. When things are working well, this will also be the block time. -pub const MILLI_SECS_PER_SLOT: u32 = 3000; +pub const SLOT_LENGTH: &[u8] = b"slot-length"; /// A storage key that will store the slot number of the first block in the chain. pub const ZERO_SLOT: &[u8] = b"zero-slot"; diff --git a/runtime/src/genesis.rs b/runtime/src/genesis.rs index 6920a8a..4d01854 100644 --- a/runtime/src/genesis.rs +++ b/runtime/src/genesis.rs @@ -12,6 +12,7 @@ pub const GENESIS_DEFAULT_JSON: &str = r#" { "zero_time": 1747081100000, "zero_slot": 0, + "slot_length": 3000, "outputs": [ { "address": "6101e6301758a6badfab05035cffc8e3438b3aff2a4edc6544b47329c4", diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 56a9f8e..4846350 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -14,7 +14,6 @@ use alloc::{string::ToString, vec, vec::Vec}; use griffin_core::genesis::config_builder::GenesisConfig; use griffin_core::types::{Address, AssetName, Input, PolicyId}; use griffin_core::utxo_set::TransparentUtxoSet; -use griffin_core::MILLI_SECS_PER_SLOT; pub use opaque::SessionKeys; use parity_scale_codec::{Decode, Encode}; @@ -253,7 +252,7 @@ impl_runtime_apis! { impl apis::AuraApi for Runtime { fn slot_duration() -> sp_consensus_aura::SlotDuration { - sp_consensus_aura::SlotDuration::from_millis(MILLI_SECS_PER_SLOT.into()) + sp_consensus_aura::SlotDuration::from_millis(griffin_core::Executive::slot_length() as u64) } fn authorities() -> Vec { diff --git a/wallet/src/eutxo_examples/vesting/README.md b/wallet/src/eutxo_examples/vesting/README.md index 23cc2d9..731da8c 100644 --- a/wallet/src/eutxo_examples/vesting/README.md +++ b/wallet/src/eutxo_examples/vesting/README.md @@ -4,5 +4,5 @@ This contract allows an "owner" (indicated in the datum via a public key hash) t Keep in mind that: - the `validity_interval_start` is expressed in slots. -- the initial POSIX time of a slot can be obtained as `(slot_number - zero_slot) * MILLI_SECS_PER_SLOT + zero_time`, where `zero_slot` and `zero_time` are genesis configuration parameters and the constant `MILLI_SECS_PER_SLOT` is set in the `griffin_core` crate. -- with the actual configuration, `zero_slot = 0`, `zero_time = 1747081100000` (i.e., 2025-06-12 14:51:40 UTC), `MILLI_SECS_PER_SLOT = 3000` and a deadline set in the datum of `1747081220000` (i.e., 2025-06-12 14:53:40 UTC), the `validity_interval_start` must be at least `(1747081220000 - 1747081100000) / 3000 = 40`, which means that the owner will be able to unlock the funds 40 slots after the genesis. +- the initial POSIX time of a slot can be obtained as `(slot_number - zero_slot) * slot_length + zero_time`, where `zero_slot`, `zero_time` and `slot_length` are genesis configuration parameters. +- with the actual configuration, `zero_slot = 0`, `zero_time = 1747081100000` (i.e., 2025-06-12 14:51:40 UTC), `slot_length = 3000` and a deadline set in the datum of `1747081220000` (i.e., 2025-06-12 14:53:40 UTC), the `validity_interval_start` must be at least `(1747081220000 - 1747081100000) / 3000 = 40`, which means that the owner will be able to unlock the funds 40 slots after the genesis. From 127439ec5315435bcf551f3b23c666e9b9759fa8 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Tue, 11 Nov 2025 17:18:27 -0300 Subject: [PATCH 06/20] rpc calls for retrieving slot config --- wallet/src/cli.rs | 2 +- wallet/src/context.rs | 19 ++++++++++++++++++- wallet/src/rpc.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/wallet/src/cli.rs b/wallet/src/cli.rs index 3393ab3..6376304 100644 --- a/wallet/src/cli.rs +++ b/wallet/src/cli.rs @@ -64,7 +64,7 @@ pub enum WalletCommand { impl WalletCommand { pub async fn run(&self) -> anyhow::Result<()> { - let Context {cli, client, db, keystore, data_path, keystore_path } = Context::::load_context().await.unwrap(); + let Context {cli, client, db, keystore, data_path, keystore_path, slot_config: _ } = Context::::load_context().await.unwrap(); // Dispatch to proper subcommand match cli.command { Some(WalletCommand::Wallet(cmd)) => diff --git a/wallet/src/context.rs b/wallet/src/context.rs index 4476069..878eb6a 100644 --- a/wallet/src/context.rs +++ b/wallet/src/context.rs @@ -1,5 +1,6 @@ use crate::{sync, rpc, cli::Cli}; use clap::Parser; +use griffin_core::uplc::tx::SlotConfig; use jsonrpsee::http_client::{HttpClient, HttpClientBuilder}; use std::path::PathBuf; @@ -13,6 +14,7 @@ pub struct Context { pub keystore: sc_keystore::LocalKeystore, pub data_path: PathBuf, pub keystore_path: PathBuf, + pub slot_config: SlotConfig, } impl Context { @@ -53,6 +55,21 @@ impl Context { .await? .expect("node should be able to return some genesis block"); log::debug!("Node's Genesis block::{:?}", node_genesis_hash); + + let zero_time = rpc::node_get_zero_time(&client) + .await? + .expect("node should be able to return zero time"); + let zero_slot = rpc::node_get_zero_slot(&client) + .await? + .expect("node should be able to return zero slot"); + let slot_length = rpc::node_get_slot_length(&client) + .await? + .expect("node should be able to return slot length"); + let slot_config = SlotConfig { + zero_time, + zero_slot, + slot_length, + }; if cli.purge_db { std::fs::remove_dir_all(db_path.clone()).map_err(|e| { @@ -88,7 +105,7 @@ impl Context { }; Ok(Context { - cli, client, db, keystore, data_path, keystore_path + cli, client, db, keystore, data_path, keystore_path, slot_config }) } } diff --git a/wallet/src/rpc.rs b/wallet/src/rpc.rs index 5637315..8e924a2 100644 --- a/wallet/src/rpc.rs +++ b/wallet/src/rpc.rs @@ -1,6 +1,7 @@ //! Helper functions for communicating with the Node's RPC endpoint. use griffin_core::types::{Input, OpaqueBlock, Output}; +use griffin_core::{SLOT_LENGTH, ZERO_SLOT, ZERO_TIME}; use jsonrpsee::{core::client::ClientT, http_client::HttpClient, rpc_params}; use parity_scale_codec::Encode; use sp_core::H256; @@ -39,3 +40,30 @@ pub async fn fetch_storage(input: &Input, client: &HttpClient) -> anyhow::Result let utxo = routput?; Ok(utxo) } + +/// Get the Node's initial POSIX time +pub async fn node_get_zero_time(client: &HttpClient) -> anyhow::Result> { + let params = rpc_params![hex::encode(str::from_utf8(ZERO_TIME).unwrap())]; + let rpc_response: Option = client.request("state_getStorage", params).await?; + let time_bytes: [u8; 8] = hex::decode(rpc_response.unwrap().strip_prefix("0x").unwrap()).unwrap().try_into().unwrap(); + let time = u64::from_le_bytes(time_bytes); + Ok(Some(time)) +} + +/// Get the Node's zero slot +pub async fn node_get_zero_slot(client: &HttpClient) -> anyhow::Result> { + let params = rpc_params![hex::encode(str::from_utf8(ZERO_SLOT).unwrap())]; + let rpc_response: Option = client.request("state_getStorage", params).await?; + let slot_bytes: [u8; 8] = hex::decode(rpc_response.unwrap().strip_prefix("0x").unwrap()).unwrap().try_into().unwrap(); + let slot = u64::from_le_bytes(slot_bytes); + Ok(Some(slot)) +} + +/// Get the Node's slot length +pub async fn node_get_slot_length(client: &HttpClient) -> anyhow::Result> { + let params = rpc_params![hex::encode(str::from_utf8(SLOT_LENGTH).unwrap())]; + let rpc_response: Option = client.request("state_getStorage", params).await?; + let slot_length_bytes: [u8; 4] = hex::decode(rpc_response.unwrap().strip_prefix("0x").unwrap()).unwrap().try_into().unwrap(); + let slot_length = u32::from_le_bytes(slot_length_bytes); + Ok(Some(slot_length)) +} From 25fe2f9b784f8154ff490ad2144ec734bb16fbbd Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Tue, 11 Nov 2025 17:19:48 -0300 Subject: [PATCH 07/20] fix wallet `main` function --- wallet/src/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wallet/src/main.rs b/wallet/src/main.rs index ee2290d..b1eff41 100644 --- a/wallet/src/main.rs +++ b/wallet/src/main.rs @@ -31,5 +31,6 @@ mod utils; #[tokio::main] async fn main() -> anyhow::Result<()> { - cli::WalletCommand::run().await + let cmd = cli::WalletCommand::Wallet(cli::Command::ShowAllOutputs); + cmd.run().await } From 220ae254a47cafa6c4740849c59b689894ee0ae9 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Tue, 11 Nov 2025 17:22:51 -0300 Subject: [PATCH 08/20] fix hardcoded POSIX time in game `create_ship` command --- game/src/game.rs | 4 +++- game/src/lib.rs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/game/src/game.rs b/game/src/game.rs index 5430434..fe90665 100644 --- a/game/src/game.rs +++ b/game/src/game.rs @@ -16,6 +16,7 @@ use griffin_core::{ compute_plutus_v2_script_hash, Address, AssetName, Coin, Datum, Input, Multiasset, Output, PlutusData, PlutusScript, PolicyId, Redeemer, RedeemerTag, Transaction, VKeyWitness, Value, }, + uplc::tx::SlotConfig }; use griffin_wallet::{cli::ShowOutputsAtArgs, keystore, sync}; use jsonrpsee::{core::client::ClientT, http_client::HttpClient, rpc_params}; @@ -36,6 +37,7 @@ pub async fn create_ship( db: &Db, client: &HttpClient, keystore: &LocalKeystore, + slot_config: SlotConfig, args: CreateShipArgs, ) -> anyhow::Result<()> { log::debug!("The args are:: {:?}", args); @@ -158,7 +160,7 @@ pub async fn create_ship( PallasPlutusData::BoundedBytes(BoundedBytes(ship_name.0.clone().into())), PallasPlutusData::BoundedBytes(BoundedBytes(pilot_name.0.clone().into())), PallasPlutusData::BigInt(BigInt::BigUInt(BoundedBytes( - 1747081220000_u64.to_be_bytes().to_vec(), + (slot_config.zero_time + slot_config.slot_length as u64 * args.ttl).to_be_bytes().to_vec(), ))), ] .to_vec(), diff --git a/game/src/lib.rs b/game/src/lib.rs index 04461fa..4f94224 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -19,11 +19,11 @@ pub enum Command { impl GameCommand { pub async fn run(&self) -> sc_cli::Result<()> { - let Context {cli, client, db, keystore, .. } = Context::::load_context().await.unwrap(); + let Context {cli, client, db, keystore, slot_config, .. } = Context::::load_context().await.unwrap(); match cli.command { Some(GameCommand::Game(cmd)) => match cmd { Command::CreateShip(args) => { - let _ = game::create_ship(&db, &client, &keystore, args).await; + let _ = game::create_ship(&db, &client, &keystore, slot_config, args).await; Ok(()) } }, From 6e225bc5dc6ff78f71c1594aa34cb746209d08e2 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Tue, 11 Nov 2025 17:30:28 -0300 Subject: [PATCH 09/20] apply `cargo fmt` --- game/src/game.rs | 13 +-- game/src/lib.rs | 27 +++--- node/src/cli.rs | 8 +- node/src/command.rs | 4 +- wallet/src/cli.rs | 207 ++++++++++++++++++++++-------------------- wallet/src/command.rs | 2 +- wallet/src/context.rs | 42 +++++---- wallet/src/lib.rs | 8 +- wallet/src/main.rs | 2 +- wallet/src/rpc.rs | 15 ++- wallet/src/utils.rs | 7 +- 11 files changed, 180 insertions(+), 155 deletions(-) diff --git a/game/src/game.rs b/game/src/game.rs index fe90665..0d41842 100644 --- a/game/src/game.rs +++ b/game/src/game.rs @@ -1,11 +1,12 @@ +use crate::CreateShipArgs; use anyhow::anyhow; use griffin_core::{ checks_interface::{babbage_minted_tx_from_cbor, babbage_tx_to_cbor}, + h224::H224, pallas_codec::{ minicbor, utils::{Int, MaybeIndefArray::Indef}, }, - h224::H224, pallas_crypto::hash::Hash as PallasHash, pallas_primitives::babbage::{ BigInt, BoundedBytes, Constr, MintedTx, PlutusData as PallasPlutusData, @@ -16,7 +17,7 @@ use griffin_core::{ compute_plutus_v2_script_hash, Address, AssetName, Coin, Datum, Input, Multiasset, Output, PlutusData, PlutusScript, PolicyId, Redeemer, RedeemerTag, Transaction, VKeyWitness, Value, }, - uplc::tx::SlotConfig + uplc::tx::SlotConfig, }; use griffin_wallet::{cli::ShowOutputsAtArgs, keystore, sync}; use jsonrpsee::{core::client::ClientT, http_client::HttpClient, rpc_params}; @@ -25,7 +26,6 @@ use sc_keystore::LocalKeystore; use sled::Db; use sp_core::ed25519::Public; use sp_runtime::traits::{BlakeTwo256, Hash}; -use crate::CreateShipArgs; const SHIP_FEE: Coin = 3000000; @@ -160,7 +160,9 @@ pub async fn create_ship( PallasPlutusData::BoundedBytes(BoundedBytes(ship_name.0.clone().into())), PallasPlutusData::BoundedBytes(BoundedBytes(pilot_name.0.clone().into())), PallasPlutusData::BigInt(BigInt::BigUInt(BoundedBytes( - (slot_config.zero_time + slot_config.slot_length as u64 * args.ttl).to_be_bytes().to_vec(), + (slot_config.zero_time + slot_config.slot_length as u64 * args.ttl) + .to_be_bytes() + .to_vec(), ))), ] .to_vec(), @@ -205,8 +207,7 @@ pub async fn create_ship( let vkey: Vec = Vec::from(args.witness.0); let public = Public::from_h256(args.witness); - let signature: Vec = - Vec::from(keystore::sign_with(keystore, &public, tx_hash)?.0); + let signature: Vec = Vec::from(keystore::sign_with(keystore, &public, tx_hash)?.0); transaction.transaction_witness_set = <_>::from(vec![VKeyWitness::from((vkey, signature))]); diff --git a/game/src/lib.rs b/game/src/lib.rs index 4f94224..bedc321 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -1,6 +1,6 @@ mod game; -use clap::{Subcommand, Args}; +use clap::{Args, Subcommand}; use griffin_core::types::Input; use griffin_wallet::{context::Context, keystore, utils}; use sp_core::H256; @@ -19,7 +19,14 @@ pub enum Command { impl GameCommand { pub async fn run(&self) -> sc_cli::Result<()> { - let Context {cli, client, db, keystore, slot_config, .. } = Context::::load_context().await.unwrap(); + let Context { + cli, + client, + db, + keystore, + slot_config, + .. + } = Context::::load_context().await.unwrap(); match cli.command { Some(GameCommand::Game(cmd)) => match cmd { Command::CreateShip(args) => { @@ -46,20 +53,10 @@ pub struct CreateShipArgs { #[arg(long, verbatim_doc_comment, value_parser = utils::h256_from_string, default_value = keystore::SHAWN_PUB_KEY, value_name = "PUBLIC_KEY")] pub witness: H256, - #[arg( - long, - verbatim_doc_comment, - required = true, - value_name = "POS_X" - )] + #[arg(long, verbatim_doc_comment, required = true, value_name = "POS_X")] pub pos_x: i16, - #[arg( - long, - verbatim_doc_comment, - required = true, - value_name = "POS_Y" - )] + #[arg(long, verbatim_doc_comment, required = true, value_name = "POS_Y")] pub pos_y: i16, #[arg( @@ -70,4 +67,4 @@ pub struct CreateShipArgs { value_name = "TIME_TO_LIVE" )] pub ttl: u64, -} \ No newline at end of file +} diff --git a/node/src/cli.rs b/node/src/cli.rs index 91333f9..5e9cd8e 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -1,8 +1,8 @@ +use game::GameCommand; use griffin_partner_chains_runtime::opaque::SessionKeys; +use griffin_wallet::cli::WalletCommand; use partner_chains_cli::{KeyDefinition, AURA, GRANDPA}; use partner_chains_node_commands::{PartnerChainRuntime, PartnerChainsSubcommand}; -use game::GameCommand; -use griffin_wallet::cli::WalletCommand; #[derive(Debug, Clone)] pub enum Consensus { @@ -105,10 +105,10 @@ pub enum Subcommand { /// Key management cli utilities #[command(subcommand)] Key(sc_cli::KeySubcommand), - + #[clap(flatten)] Wallet(WalletCommand), - + /// Commands to play the Asteria game #[clap(flatten)] Game(GameCommand), diff --git a/node/src/command.rs b/node/src/command.rs index c53869b..b07b78e 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -55,12 +55,12 @@ pub fn run() -> sc_cli::Result<()> { let rt = Runtime::new().unwrap(); let _ = rt.block_on(cmd.run()); Ok(()) - }, + } Some(Subcommand::Game(cmd)) => { let rt = Runtime::new().unwrap(); let _ = rt.block_on(cmd.run()); Ok(()) - }, + } Some(Subcommand::PartnerChains(cmd)) => { partner_chains_node_commands::run::< // _, diff --git a/wallet/src/cli.rs b/wallet/src/cli.rs index 6376304..32f9d73 100644 --- a/wallet/src/cli.rs +++ b/wallet/src/cli.rs @@ -5,19 +5,21 @@ extern crate alloc; use std::path::PathBuf; use crate::{ - utils::{address_from_string, h224_from_string, h256_from_string, input_from_string}, + command, + context::{Context, DEFAULT_ENDPOINT}, + keystore, keystore::{SHAWN_ADDRESS, SHAWN_PUB_KEY}, - context::{DEFAULT_ENDPOINT, Context}, - command, sync, keystore, utils + sync, utils, + utils::{address_from_string, h224_from_string, h256_from_string, input_from_string}, }; -use alloc::{string::String}; +use alloc::string::String; use clap::{ArgAction::Append, Args, Parser, Subcommand}; use griffin_core::{ pallas_crypto::hash::Hasher as PallasHasher, - types::{Address, Coin, Input, Value, PolicyId}, + types::{Address, Coin, Input, PolicyId, Value}, }; use hex::FromHex; -use parity_scale_codec::{Encode}; +use parity_scale_codec::Encode; use sp_core::H256; /// The wallet's main CLI struct @@ -59,115 +61,122 @@ pub struct Cli { #[derive(Clone, Debug, Subcommand)] pub enum WalletCommand { #[command(subcommand)] - Wallet(Command) + Wallet(Command), } impl WalletCommand { pub async fn run(&self) -> anyhow::Result<()> { - let Context {cli, client, db, keystore, data_path, keystore_path, slot_config: _ } = Context::::load_context().await.unwrap(); + let Context { + cli, + client, + db, + keystore, + data_path, + keystore_path, + slot_config: _, + } = Context::::load_context().await.unwrap(); // Dispatch to proper subcommand match cli.command { - Some(WalletCommand::Wallet(cmd)) => - match cmd { - Command::VerifyUtxo { input } => { - println!("Details of coin {}:", hex::encode(input.encode())); - - // Print the details from storage - let coin_from_storage = utils::get_coin_from_storage(&input, &client).await?; - print!("Found in storage. Value: {:?}, ", coin_from_storage); - - // Print the details from the local db - match sync::get_unspent(&db, &input)? { - Some((owner, amount, _)) => { - println!("Found in local db. Value: {amount:?}, owned by {owner}"); - } - None => { - println!("Not found in local db"); - } + Some(WalletCommand::Wallet(cmd)) => match cmd { + Command::VerifyUtxo { input } => { + println!("Details of coin {}:", hex::encode(input.encode())); + + // Print the details from storage + let coin_from_storage = utils::get_coin_from_storage(&input, &client).await?; + print!("Found in storage. Value: {:?}, ", coin_from_storage); + + // Print the details from the local db + match sync::get_unspent(&db, &input)? { + Some((owner, amount, _)) => { + println!("Found in local db. Value: {amount:?}, owned by {owner}"); + } + None => { + println!("Not found in local db"); } - - Ok(()) - } - Command::SpendValue(args) => { - command::spend_value(&db, &client, &keystore, args).await - } - Command::InsertKey { seed } => keystore::insert_key(&keystore, &seed), - Command::GenerateKey { password } => { - keystore::generate_key(&keystore, password)?; - Ok(()) - } - Command::ShowKeys => { - keystore::get_keys(&keystore)?.for_each(|pubkey| { - let pk_str: &str = &hex::encode(pubkey); - let hash: String = - PallasHasher::<224>::hash(&<[u8; 32]>::from_hex(pk_str).unwrap()).to_string(); - println!("key: 0x{}; addr: 0x61{}", pk_str, hash); - }); - - Ok(()) } - Command::RemoveKey { pub_key } => { - println!( + + Ok(()) + } + Command::SpendValue(args) => { + command::spend_value(&db, &client, &keystore, args).await + } + Command::InsertKey { seed } => keystore::insert_key(&keystore, &seed), + Command::GenerateKey { password } => { + keystore::generate_key(&keystore, password)?; + Ok(()) + } + Command::ShowKeys => { + keystore::get_keys(&keystore)?.for_each(|pubkey| { + let pk_str: &str = &hex::encode(pubkey); + let hash: String = + PallasHasher::<224>::hash(&<[u8; 32]>::from_hex(pk_str).unwrap()) + .to_string(); + println!("key: 0x{}; addr: 0x61{}", pk_str, hash); + }); + + Ok(()) + } + Command::RemoveKey { pub_key } => { + println!( "CAUTION!!! About permanently remove {pub_key}. This action CANNOT BE REVERSED. Type \"proceed\" to confirm deletion." ); - - let mut confirmation = String::new(); - std::io::stdin() - .read_line(&mut confirmation) - .expect("Failed to read line"); - - if confirmation.trim() == "proceed" { - keystore::remove_key(&keystore_path, &pub_key) - } else { - println!("Deletion aborted. That was close."); - Ok(()) - } - } - Command::ShowBalance => { - println!("Balance Summary"); - let mut total = Value::Coin(0); - let balances = sync::get_balances(&db)?; - for (account, balance) in balances { - total += balance.clone(); - println!("{account}: {balance}"); - } - println!("{:-<58}", ""); - println!("Total: {}", total.normalize()); - + + let mut confirmation = String::new(); + std::io::stdin() + .read_line(&mut confirmation) + .expect("Failed to read line"); + + if confirmation.trim() == "proceed" { + keystore::remove_key(&keystore_path, &pub_key) + } else { + println!("Deletion aborted. That was close."); Ok(()) } - Command::ShowAllOutputs => { - println!("###### Unspent outputs ###########"); - sync::show_outputs(sync::print_unspent_tree(&db)?); - println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); - Ok(()) + } + Command::ShowBalance => { + println!("Balance Summary"); + let mut total = Value::Coin(0); + let balances = sync::get_balances(&db)?; + for (account, balance) in balances { + total += balance.clone(); + println!("{account}: {balance}"); } - Command::ShowOutputsAt(args) => { - println!( - "###### Unspent outputs at address {} ###########", - args.address - ); - sync::show_outputs(sync::get_outputs_at(&db, args)?); - println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); - Ok(()) - } - Command::ShowOutputsWithAsset(args) => { - println!( + println!("{:-<58}", ""); + println!("Total: {}", total.normalize()); + + Ok(()) + } + Command::ShowAllOutputs => { + println!("###### Unspent outputs ###########"); + sync::show_outputs(sync::print_unspent_tree(&db)?); + println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); + Ok(()) + } + Command::ShowOutputsAt(args) => { + println!( + "###### Unspent outputs at address {} ###########", + args.address + ); + sync::show_outputs(sync::get_outputs_at(&db, args)?); + println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); + Ok(()) + } + Command::ShowOutputsWithAsset(args) => { + println!( "###### Unspent outputs containing asset with name {} and policy ID {} ###########", args.name, args.policy ); - sync::show_outputs(sync::get_outputs_with_asset(&db, args)?); - println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); - Ok(()) - } - Command::ShowAllOrders => { - println!("###### Available Orders ###########"); - sync::print_orders(&db)?; - Ok(()) - }, - Command::BuildTx(args) => command::build_tx(&db, &client, &keystore, args).await, - - }, + sync::show_outputs(sync::get_outputs_with_asset(&db, args)?); + println!("To see all details of a particular UTxO, invoke the `verify-utxo` command."); + Ok(()) + } + Command::ShowAllOrders => { + println!("###### Available Orders ###########"); + sync::print_orders(&db)?; + Ok(()) + } + Command::BuildTx(args) => command::build_tx(&db, &client, &keystore, args).await, + }, None => { log::info!("No Wallet Command invoked. Exiting."); Ok(()) diff --git a/wallet/src/command.rs b/wallet/src/command.rs index 67c79ef..b144ca7 100644 --- a/wallet/src/command.rs +++ b/wallet/src/command.rs @@ -23,7 +23,7 @@ use parity_scale_codec::Encode; use sc_keystore::LocalKeystore; use serde::{Deserialize, Serialize}; use sled::Db; -use sp_core::{H256, ed25519::Public}; +use sp_core::{ed25519::Public, H256}; use sp_runtime::traits::{BlakeTwo256, Hash}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] diff --git a/wallet/src/context.rs b/wallet/src/context.rs index 878eb6a..50dcc39 100644 --- a/wallet/src/context.rs +++ b/wallet/src/context.rs @@ -1,4 +1,4 @@ -use crate::{sync, rpc, cli::Cli}; +use crate::{cli::Cli, rpc, sync}; use clap::Parser; use griffin_core::uplc::tx::SlotConfig; use jsonrpsee::http_client::{HttpClient, HttpClientBuilder}; @@ -9,7 +9,7 @@ pub const DEFAULT_ENDPOINT: &str = "http://localhost:9944"; pub struct Context { pub cli: Cli, - pub client: HttpClient, + pub client: HttpClient, pub db: sled::Db, pub keystore: sc_keystore::LocalKeystore, pub data_path: PathBuf, @@ -20,13 +20,13 @@ pub struct Context { impl Context { pub async fn load_context() -> anyhow::Result> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); - + // Parse command line args let cli = Cli::::parse(); - + // If the user specified --tmp or --dev, then use a temporary directory. let tmp = cli.tmp || cli.dev; - + // Setup the data paths. let data_path = match tmp { true => temp_dir(), @@ -34,19 +34,19 @@ impl Context { }; let keystore_path = data_path.join("keystore"); let db_path = data_path.join("wallet_database"); - + // Setup the keystore let keystore = sc_keystore::LocalKeystore::open(keystore_path.clone(), None)?; - + if cli.dev { // Insert the example Shawn key so example transactions can be signed. crate::keystore::insert_development_key_for_this_session(&keystore)?; } - + // Setup jsonrpsee and endpoint-related information. // https://github.com/paritytech/jsonrpsee/blob/master/examples/examples/http.rs let client = HttpClientBuilder::default().build(&cli.endpoint)?; - + // Read node's genesis block. let node_genesis_hash = rpc::node_get_block_hash(0, &client) .await? @@ -70,7 +70,7 @@ impl Context { zero_slot, slot_length, }; - + if cli.purge_db { std::fs::remove_dir_all(db_path.clone()).map_err(|e| { log::warn!( @@ -80,32 +80,38 @@ impl Context { e })?; } - + // Open the local database let db = sync::open_db(db_path, node_genesis_hash, node_genesis_block.clone())?; - + let num_blocks = sync::height(&db)?.expect("db should be initialized automatically when opening."); log::info!("Number of blocks in the db: {num_blocks}"); - + if !sled::Db::was_recovered(&db) { sync::apply_block(&db, node_genesis_block, node_genesis_hash).await?; } - + // Synchronize the wallet with attached node unless instructed otherwise. if cli.no_sync { log::warn!("Skipping sync with node. Using previously synced information.") } else { sync::synchronize(&db, &client).await?; - + log::info!( "Wallet database synchronized with node to height {:?}", sync::height(&db)?.expect("We just synced, so there is a height available") ); }; - + Ok(Context { - cli, client, db, keystore, data_path, keystore_path, slot_config + cli, + client, + db, + keystore, + data_path, + keystore_path, + slot_config, }) } } @@ -133,4 +139,4 @@ fn default_data_path() -> PathBuf { .expect("app directories exist on all supported platforms; qed") .data_dir() .into() -} \ No newline at end of file +} diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index b3abac1..50ec60a 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -1,8 +1,8 @@ -pub mod sync; -pub mod command; pub mod cli; +pub mod command; pub mod context; -pub mod rpc; pub mod keystore; +pub mod order_book; +pub mod rpc; +pub mod sync; pub mod utils; -pub mod order_book; \ No newline at end of file diff --git a/wallet/src/main.rs b/wallet/src/main.rs index b1eff41..5f42d78 100644 --- a/wallet/src/main.rs +++ b/wallet/src/main.rs @@ -22,11 +22,11 @@ mod cli; mod command; +mod context; mod keystore; mod order_book; mod rpc; mod sync; -mod context; mod utils; #[tokio::main] diff --git a/wallet/src/rpc.rs b/wallet/src/rpc.rs index 8e924a2..5773f8d 100644 --- a/wallet/src/rpc.rs +++ b/wallet/src/rpc.rs @@ -45,7 +45,10 @@ pub async fn fetch_storage(input: &Input, client: &HttpClient) -> anyhow::Result pub async fn node_get_zero_time(client: &HttpClient) -> anyhow::Result> { let params = rpc_params![hex::encode(str::from_utf8(ZERO_TIME).unwrap())]; let rpc_response: Option = client.request("state_getStorage", params).await?; - let time_bytes: [u8; 8] = hex::decode(rpc_response.unwrap().strip_prefix("0x").unwrap()).unwrap().try_into().unwrap(); + let time_bytes: [u8; 8] = hex::decode(rpc_response.unwrap().strip_prefix("0x").unwrap()) + .unwrap() + .try_into() + .unwrap(); let time = u64::from_le_bytes(time_bytes); Ok(Some(time)) } @@ -54,7 +57,10 @@ pub async fn node_get_zero_time(client: &HttpClient) -> anyhow::Result anyhow::Result> { let params = rpc_params![hex::encode(str::from_utf8(ZERO_SLOT).unwrap())]; let rpc_response: Option = client.request("state_getStorage", params).await?; - let slot_bytes: [u8; 8] = hex::decode(rpc_response.unwrap().strip_prefix("0x").unwrap()).unwrap().try_into().unwrap(); + let slot_bytes: [u8; 8] = hex::decode(rpc_response.unwrap().strip_prefix("0x").unwrap()) + .unwrap() + .try_into() + .unwrap(); let slot = u64::from_le_bytes(slot_bytes); Ok(Some(slot)) } @@ -63,7 +69,10 @@ pub async fn node_get_zero_slot(client: &HttpClient) -> anyhow::Result anyhow::Result> { let params = rpc_params![hex::encode(str::from_utf8(SLOT_LENGTH).unwrap())]; let rpc_response: Option = client.request("state_getStorage", params).await?; - let slot_length_bytes: [u8; 4] = hex::decode(rpc_response.unwrap().strip_prefix("0x").unwrap()).unwrap().try_into().unwrap(); + let slot_length_bytes: [u8; 4] = hex::decode(rpc_response.unwrap().strip_prefix("0x").unwrap()) + .unwrap() + .try_into() + .unwrap(); let slot_length = u32::from_le_bytes(slot_length_bytes); Ok(Some(slot_length)) } diff --git a/wallet/src/utils.rs b/wallet/src/utils.rs index ceb95fc..5a43496 100644 --- a/wallet/src/utils.rs +++ b/wallet/src/utils.rs @@ -2,7 +2,7 @@ use griffin_core::{ h224::H224, types::{Address, Input, Value}, }; -use parity_scale_codec::{Decode}; +use parity_scale_codec::Decode; use sp_core::H256; use crate::rpc; @@ -58,7 +58,10 @@ fn strip_0x_prefix(s: &str) -> &str { /// Given an output ref, fetch the details about its value from the node's /// storage. -pub async fn get_coin_from_storage(input: &Input, client: &jsonrpsee::http_client::HttpClient) -> anyhow::Result { +pub async fn get_coin_from_storage( + input: &Input, + client: &jsonrpsee::http_client::HttpClient, +) -> anyhow::Result { let utxo = rpc::fetch_storage(input, client).await?; let coin_in_storage: Value = utxo.value; From 9b411035f1804190066eb6fca5550df9bf49599c Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Wed, 12 Nov 2025 00:42:35 -0300 Subject: [PATCH 10/20] `create-ship`: fix datum build & cli args --- game/src/game.rs | 30 ++++++++---------------------- game/src/lib.rs | 16 ++++++++++++++-- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/game/src/game.rs b/game/src/game.rs index 0d41842..2240309 100644 --- a/game/src/game.rs +++ b/game/src/game.rs @@ -146,28 +146,14 @@ pub async fn create_ship( shipyard_policy, }); - let ship_datum = PallasPlutusData::from(PallasPlutusData::Constr(Constr { - tag: 121, - any_constructor: None, - fields: Indef( - [ - PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( - args.pos_x, - )))), - PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( - args.pos_y, - )))), - PallasPlutusData::BoundedBytes(BoundedBytes(ship_name.0.clone().into())), - PallasPlutusData::BoundedBytes(BoundedBytes(pilot_name.0.clone().into())), - PallasPlutusData::BigInt(BigInt::BigUInt(BoundedBytes( - (slot_config.zero_time + slot_config.slot_length as u64 * args.ttl) - .to_be_bytes() - .to_vec(), - ))), - ] - .to_vec(), - ), - })); + let ship_datum = PallasPlutusData::from(ShipDatum::Ok { + pos_x: args.pos_x, + pos_y: args.pos_y, + ship_token_name: ship_name.clone(), + pilot_token_name: pilot_name.clone(), + last_move_latest_time: slot_config.zero_time + + args.ttl * slot_config.slot_length as u64, + }); transaction.transaction_body.inputs = inputs; diff --git a/game/src/lib.rs b/game/src/lib.rs index bedc321..b39de78 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -53,10 +53,22 @@ pub struct CreateShipArgs { #[arg(long, verbatim_doc_comment, value_parser = utils::h256_from_string, default_value = keystore::SHAWN_PUB_KEY, value_name = "PUBLIC_KEY")] pub witness: H256, - #[arg(long, verbatim_doc_comment, required = true, value_name = "POS_X")] + #[arg( + long, + verbatim_doc_comment, + required = true, + allow_negative_numbers = true, + value_name = "POS_X" + )] pub pos_x: i16, - #[arg(long, verbatim_doc_comment, required = true, value_name = "POS_Y")] + #[arg( + long, + verbatim_doc_comment, + required = true, + allow_negative_numbers = true, + value_name = "POS_Y" + )] pub pos_y: i16, #[arg( From eec956273efbaa237ba82e302ac665e00015e754 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Wed, 12 Nov 2025 00:44:06 -0300 Subject: [PATCH 11/20] add command for gathering fuel --- game/src/game.rs | 297 ++++++++++++++++++++++++++++++++++++++++++++- game/src/lib.rs | 38 ++++++ wallet/src/sync.rs | 2 +- 3 files changed, 334 insertions(+), 3 deletions(-) diff --git a/game/src/game.rs b/game/src/game.rs index 2240309..3d6ec78 100644 --- a/game/src/game.rs +++ b/game/src/game.rs @@ -1,4 +1,4 @@ -use crate::CreateShipArgs; +use crate::{CreateShipArgs, GatherFuelArgs}; use anyhow::anyhow; use griffin_core::{ checks_interface::{babbage_minted_tx_from_cbor, babbage_tx_to_cbor}, @@ -19,7 +19,10 @@ use griffin_core::{ }, uplc::tx::SlotConfig, }; -use griffin_wallet::{cli::ShowOutputsAtArgs, keystore, sync}; +use griffin_wallet::{ + cli::{ShowOutputsAtArgs, ShowOutputsWithAssetArgs}, + keystore, sync, +}; use jsonrpsee::{core::client::ClientT, http_client::HttpClient, rpc_params}; use parity_scale_codec::Encode; use sc_keystore::LocalKeystore; @@ -252,6 +255,200 @@ pub async fn create_ship( } } +pub async fn gather_fuel( + db: &Db, + client: &HttpClient, + keystore: &LocalKeystore, + args: GatherFuelArgs, +) -> anyhow::Result<()> { + log::debug!("The args are:: {:?}", args); + + let spacetime_script: PlutusScript = PlutusScript(hex::decode(SHIP_SCRIPT_HEX).unwrap()); + let shipyard_policy: PolicyId = compute_plutus_v2_script_hash(spacetime_script.clone()); + + let pellet_script: PlutusScript = PlutusScript(hex::decode(PELLET_SCRIPT_HEX).unwrap()); + let pellet_policy: PolicyId = compute_plutus_v2_script_hash(pellet_script.clone()); + + // Construct a template Transaction to push coins into later + let mut transaction = Transaction::from((Vec::new(), Vec::new())); + + let (spacetime_address, ship_value, ship_datum) = + sync::get_unspent(db, &args.ship)?.expect("Ship UTxO not found"); + let (pellet_address, pellet_value, pellet_datum) = + sync::get_unspent(db, &args.pellet)?.expect("Pellet UTxO not found"); + + let ship_datum_option = ship_datum.clone().map(|d| ShipDatum::from(d)); + + if let Some(ShipDatum::Ok { + pos_x: _, + pos_y: _, + ship_token_name: _, + pilot_token_name, + last_move_latest_time: _, + }) = ship_datum_option + { + let fuel_name = AssetName::from("FUEL".to_string()); + + let pilot_utxos = sync::get_outputs_with_asset( + db, + ShowOutputsWithAssetArgs { + policy: shipyard_policy, + name: pilot_token_name.0, + }, + )?; + + if pilot_utxos.len() == 0 { + Err(anyhow!("Pilot UTxO not found"))?; + } + let pilot_utxo = &pilot_utxos[0]; + + let mut inputs = vec![ + args.ship.clone(), + args.pellet.clone(), + pilot_utxo.input.clone(), + ]; + let ordered_inputs: Vec = { + // Lexicographically order inputs by tx_hash and index + inputs.sort_by(|a, b| { + if a.tx_hash == b.tx_hash { + a.index.cmp(&b.index) + } else { + a.tx_hash.cmp(&b.tx_hash) + } + }); + inputs.clone() + }; + transaction.transaction_body.inputs = inputs; + + // BUILD REDEEMERS + let ship_redeemer = Redeemer { + tag: RedeemerTag::Spend, + index: ordered_inputs.iter().position(|i| *i == args.ship).unwrap() as u32, + data: PlutusData::from(PallasPlutusData::Constr(Constr { + tag: 122, + any_constructor: None, + fields: Indef( + [PallasPlutusData::Constr(Constr { + tag: 122, + any_constructor: None, + fields: Indef( + [PallasPlutusData::BigInt(BigInt::Int(Int( + minicbor::data::Int::from(args.fuel), + )))] + .to_vec(), + ), + })] + .to_vec(), + ), + })), + }; + + let pellet_redeemer = Redeemer { + tag: RedeemerTag::Spend, + index: ordered_inputs + .iter() + .position(|i| *i == args.pellet) + .unwrap() as u32, + data: PlutusData::from(PallasPlutusData::Constr(Constr { + tag: 122, + any_constructor: None, + fields: Indef( + [PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef( + [PallasPlutusData::BigInt(BigInt::Int(Int( + minicbor::data::Int::from(args.fuel), + )))] + .to_vec(), + ), + })] + .to_vec(), + ), + })), + }; + + let outputs = vec![ + Output { + address: pilot_utxo.address.clone(), + value: pilot_utxo.value.clone(), + datum_option: pilot_utxo.datum_option.clone(), + }, + Output { + address: pellet_address, + value: pellet_value - Value::from((pellet_policy, fuel_name.clone(), args.fuel)), + datum_option: pellet_datum, + }, + Output { + address: spacetime_address, + value: ship_value + Value::from((pellet_policy, fuel_name, args.fuel)), + datum_option: ship_datum, + }, + ]; + + for output in outputs { + transaction.transaction_body.outputs.push(output.clone()); + } + + transaction.transaction_body.validity_interval_start = Some(args.validity_interval_start); + + let pallas_tx: PallasTransaction = <_>::from(transaction.clone()); + let cbor_bytes: Vec = babbage_tx_to_cbor(&pallas_tx); + let mtx: MintedTx = babbage_minted_tx_from_cbor(&cbor_bytes); + let tx_hash: &Vec = &Vec::from(mtx.transaction_body.original_hash().as_ref()); + log::debug!("Original tx_body hash is: {:#x?}", tx_hash); + + let vkey: Vec = Vec::from(args.witness.0); + let public = Public::from_h256(args.witness); + let signature: Vec = + Vec::from(crate::keystore::sign_with(keystore, &public, tx_hash)?.0); + transaction.transaction_witness_set = <_>::from(vec![VKeyWitness::from((vkey, signature))]); + + transaction.transaction_witness_set.redeemer = Some(vec![ship_redeemer, pellet_redeemer]); + transaction.transaction_witness_set.plutus_script = + Some(vec![spacetime_script, pellet_script]); + + log::debug!("Griffin transaction is: {:#x?}", transaction); + let pallas_tx: PallasTransaction = <_>::from(transaction.clone()); + log::debug!("Babbage transaction is: {:#x?}", pallas_tx); + + // Send the transaction + let genesis_spend_hex = hex::encode(Encode::encode(&transaction)); + let params = rpc_params![genesis_spend_hex]; + let genesis_spend_response: Result = + client.request("author_submitExtrinsic", params).await; + log::info!( + "Node's response to spend transaction: {:?}", + genesis_spend_response + ); + if let Err(_) = genesis_spend_response { + Err(anyhow!("Node did not accept the transaction"))?; + } else { + println!( + "Transaction queued. When accepted, the following UTxOs will become available:" + ); + // Print new output refs for user to check later + let tx_hash = ::hash_of(&Encode::encode(&transaction)); + for (i, output) in transaction.transaction_body.outputs.iter().enumerate() { + let new_value_ref = Input { + tx_hash, + index: i as u32, + }; + let amount = &output.value; + + println!( + "{:?} worth {amount:?}.", + hex::encode(Encode::encode(&new_value_ref)) + ); + } + } + + Ok(()) + } else { + Err(anyhow!("Malformed Ship Datum"))? + } +} + #[derive(Debug, PartialEq, Eq, Clone)] pub enum AsteriaDatum { Ok { @@ -322,3 +519,99 @@ impl From for AsteriaDatum { } } } + +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum ShipDatum { + Ok { + pos_x: i16, + pos_y: i16, + ship_token_name: AssetName, + pilot_token_name: AssetName, + last_move_latest_time: u64, + }, + MalformedShipDatum, +} + +impl From for Datum { + fn from(ship_datum: ShipDatum) -> Self { + Datum(PlutusData::from(PallasPlutusData::from(ship_datum)).0) + } +} + +impl From for ShipDatum { + fn from(datum: Datum) -> Self { + <_>::from(PallasPlutusData::from(PlutusData(datum.0))) + } +} + +impl From for PallasPlutusData { + fn from(ship_datum: ShipDatum) -> Self { + match ship_datum { + ShipDatum::Ok { + pos_x, + pos_y, + ship_token_name, + pilot_token_name, + last_move_latest_time, + } => PallasPlutusData::from(PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef( + [ + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + pos_x, + )))), + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + pos_y, + )))), + PallasPlutusData::BoundedBytes(BoundedBytes( + ship_token_name.0.clone().into(), + )), + PallasPlutusData::BoundedBytes(BoundedBytes( + pilot_token_name.0.clone().into(), + )), + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + last_move_latest_time, + )))), + ] + .to_vec(), + ), + })), + ShipDatum::MalformedShipDatum => { + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from(-1)))) + } + } + } +} + +impl From for ShipDatum { + fn from(data: PallasPlutusData) -> Self { + if let PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef(ship_datum), + }) = data + { + if let [PallasPlutusData::BigInt(BigInt::Int(Int(pos_x))), PallasPlutusData::BigInt(BigInt::Int(Int(pos_y))), PallasPlutusData::BoundedBytes(BoundedBytes(ship_name_vec)), PallasPlutusData::BoundedBytes(BoundedBytes(pilot_name_vec)), PallasPlutusData::BigInt(BigInt::Int(Int(last_move_latest_time)))] = + &ship_datum[..] + { + ShipDatum::Ok { + pos_x: TryFrom::::try_from(*pos_x).unwrap(), + pos_y: TryFrom::::try_from(*pos_y).unwrap(), + ship_token_name: AssetName(String::from_utf8(ship_name_vec.to_vec()).unwrap()), + pilot_token_name: AssetName( + String::from_utf8(pilot_name_vec.to_vec()).unwrap(), + ), + last_move_latest_time: TryFrom::::try_from( + *last_move_latest_time, + ) + .unwrap(), + } + } else { + ShipDatum::MalformedShipDatum + } + } else { + ShipDatum::MalformedShipDatum + } + } +} diff --git a/game/src/lib.rs b/game/src/lib.rs index b39de78..fdd8a8d 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -15,6 +15,8 @@ pub enum GameCommand { pub enum Command { /// Create a ship to enter the game CreateShip(CreateShipArgs), + /// Gather fuel using a ship and a fuel pellet + GatherFuel(GatherFuelArgs), } impl GameCommand { @@ -33,6 +35,10 @@ impl GameCommand { let _ = game::create_ship(&db, &client, &keystore, slot_config, args).await; Ok(()) } + Command::GatherFuel(args) => { + let _ = game::gather_fuel(&db, &client, &keystore, args).await; + Ok(()) + } }, None => { log::info!(" Asteria game"); @@ -80,3 +86,35 @@ pub struct CreateShipArgs { )] pub ttl: u64, } + +#[derive(Debug, Args, Clone)] +pub struct GatherFuelArgs { + #[arg(long, short, verbatim_doc_comment, value_parser = utils::input_from_string, required = true, value_name = "SHIP_OUTPUT_REF")] + pub ship: Input, + + #[arg(long, short, verbatim_doc_comment, value_parser = utils::input_from_string, required = true, value_name = "PELLET_OUTPUT_REF")] + pub pellet: Input, + + /// 32-byte H256 public key of an input owner. + /// Their pk/sk pair must be registered in the wallet's keystore. + #[arg(long, short, verbatim_doc_comment, value_parser = utils::h256_from_string, default_value = keystore::SHAWN_PUB_KEY, value_name = "PUBLIC_KEY")] + pub witness: H256, + + #[arg( + long, + short, + verbatim_doc_comment, + required = true, + value_name = "FUEL_AMOUNT" + )] + pub fuel: u64, + + #[arg( + long, + short, + verbatim_doc_comment, + required = true, + value_name = "VALIDITY_INTERVAL_START" + )] + pub validity_interval_start: u64, +} diff --git a/wallet/src/sync.rs b/wallet/src/sync.rs index 8ce5c30..8b1e2df 100644 --- a/wallet/src/sync.rs +++ b/wallet/src/sync.rs @@ -390,7 +390,7 @@ pub fn get_outputs_at( } /// Print the unspent outputs with a specific asset. -pub(crate) fn get_outputs_with_asset( +pub fn get_outputs_with_asset( db: &Db, args: crate::cli::ShowOutputsWithAssetArgs, ) -> anyhow::Result> { From 125036bee4ee0bde1c3526cf7489a9554dda4643 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Wed, 12 Nov 2025 01:36:35 -0300 Subject: [PATCH 12/20] add command for moving ship --- game/src/game.rs | 201 ++++++++++++++++++++++++++++++++++++++++++++++- game/src/lib.rs | 55 +++++++++++++ 2 files changed, 255 insertions(+), 1 deletion(-) diff --git a/game/src/game.rs b/game/src/game.rs index 3d6ec78..bd37f40 100644 --- a/game/src/game.rs +++ b/game/src/game.rs @@ -1,4 +1,4 @@ -use crate::{CreateShipArgs, GatherFuelArgs}; +use crate::{CreateShipArgs, GatherFuelArgs, MoveShipArgs}; use anyhow::anyhow; use griffin_core::{ checks_interface::{babbage_minted_tx_from_cbor, babbage_tx_to_cbor}, @@ -449,6 +449,205 @@ pub async fn gather_fuel( } } +pub async fn move_ship( + db: &Db, + client: &HttpClient, + keystore: &LocalKeystore, + slot_config: SlotConfig, + args: MoveShipArgs, +) -> anyhow::Result<()> { + log::debug!("The args are:: {:?}", args); + + let spacetime_script: PlutusScript = PlutusScript(hex::decode(SHIP_SCRIPT_HEX).unwrap()); + let shipyard_policy: PolicyId = compute_plutus_v2_script_hash(spacetime_script.clone()); + + let pellet_script: PlutusScript = PlutusScript(hex::decode(PELLET_SCRIPT_HEX).unwrap()); + let pellet_policy: PolicyId = compute_plutus_v2_script_hash(pellet_script.clone()); + + // Construct a template Transaction to push coins into later + let mut transaction = Transaction::from((Vec::new(), Vec::new())); + + let (spacetime_address, ship_value, ship_datum) = + sync::get_unspent(db, &args.ship)?.expect("Ship UTxO not found"); + + let ship_datum_option = ship_datum.clone().map(|d| ShipDatum::from(d)); + + if let Some(ShipDatum::Ok { + pos_x, + pos_y, + ship_token_name, + pilot_token_name, + last_move_latest_time: _, + }) = ship_datum_option + { + // Asset Names + let fuel_name = AssetName::from("FUEL".to_string()); + + let pilot_utxos = sync::get_outputs_with_asset( + db, + ShowOutputsWithAssetArgs { + policy: shipyard_policy, + name: pilot_token_name.clone().0, + }, + )?; + + if pilot_utxos.len() == 0 { + Err(anyhow!("Pilot UTxO not found"))?; + } + let pilot_utxo = &pilot_utxos[0]; + + let mut inputs = vec![args.ship.clone(), pilot_utxo.input.clone()]; + let ordered_inputs: Vec = { + // Lexicographically order inputs by tx_hash and index + inputs.sort_by(|a, b| { + if a.tx_hash == b.tx_hash { + a.index.cmp(&b.index) + } else { + a.tx_hash.cmp(&b.tx_hash) + } + }); + inputs.clone() + }; + transaction.transaction_body.inputs = inputs; + + // BURNS + let moved_manhattan_distance = (pos_x - args.pos_x).abs() + (pos_y - args.pos_y).abs(); + let moved_manhattan_distance_i64: i64 = moved_manhattan_distance.try_into().unwrap(); + let burn_fuel: Option> = Some(Multiasset::from(( + pellet_policy, + fuel_name.clone(), + -moved_manhattan_distance_i64, + ))); + + // BUILD REDEEMERS + let ship_redeemer = Redeemer { + tag: RedeemerTag::Spend, + index: ordered_inputs.iter().position(|i| *i == args.ship).unwrap() as u32, + data: PlutusData::from(PallasPlutusData::Constr(Constr { + tag: 122, + any_constructor: None, + fields: Indef( + [PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef( + [ + PallasPlutusData::BigInt(BigInt::Int(Int( + minicbor::data::Int::from(args.pos_x - pos_x), + ))), + PallasPlutusData::BigInt(BigInt::Int(Int( + minicbor::data::Int::from(args.pos_y - pos_y), + ))), + ] + .to_vec(), + ), + })] + .to_vec(), + ), + })), + }; + + let pellet_redeemer = Redeemer { + tag: RedeemerTag::Mint, + index: 0, + data: PlutusData::from(PallasPlutusData::Constr(Constr { + tag: 122, + any_constructor: None, + fields: Indef([].to_vec()), + })), + }; + + let ship_output_datum = PallasPlutusData::from(ShipDatum::Ok { + pos_x: args.pos_x, + pos_y: args.pos_y, + ship_token_name, + pilot_token_name, + last_move_latest_time: slot_config.zero_time + + args.ttl * slot_config.slot_length as u64, + }); + + let outputs = vec![ + Output { + address: pilot_utxo.address.clone(), + value: pilot_utxo.value.clone(), + datum_option: pilot_utxo.datum_option.clone(), + }, + Output { + address: spacetime_address, + value: ship_value + - Value::from(( + pellet_policy, + fuel_name, + moved_manhattan_distance.try_into().unwrap(), + )), + datum_option: Some(Datum(PlutusData::from(ship_output_datum.clone()).0)), + }, + ]; + + for output in outputs { + transaction.transaction_body.outputs.push(output.clone()); + } + transaction.transaction_body.mint = burn_fuel; + transaction.transaction_body.validity_interval_start = Some(args.validity_interval_start); + transaction.transaction_body.ttl = Some(args.ttl); + + let pallas_tx: PallasTransaction = <_>::from(transaction.clone()); + let cbor_bytes: Vec = babbage_tx_to_cbor(&pallas_tx); + let mtx: MintedTx = babbage_minted_tx_from_cbor(&cbor_bytes); + let tx_hash: &Vec = &Vec::from(mtx.transaction_body.original_hash().as_ref()); + log::debug!("Original tx_body hash is: {:#x?}", tx_hash); + + let vkey: Vec = Vec::from(args.witness.0); + let public = Public::from_h256(args.witness); + let signature: Vec = + Vec::from(crate::keystore::sign_with(keystore, &public, tx_hash)?.0); + transaction.transaction_witness_set = <_>::from(vec![VKeyWitness::from((vkey, signature))]); + + transaction.transaction_witness_set.redeemer = Some(vec![ship_redeemer, pellet_redeemer]); + transaction.transaction_witness_set.plutus_script = + Some(vec![spacetime_script, pellet_script]); + + log::debug!("Griffin transaction is: {:#x?}", transaction); + let pallas_tx: PallasTransaction = <_>::from(transaction.clone()); + log::debug!("Babbage transaction is: {:#x?}", pallas_tx); + + // Send the transaction + let genesis_spend_hex = hex::encode(Encode::encode(&transaction)); + let params = rpc_params![genesis_spend_hex]; + let genesis_spend_response: Result = + client.request("author_submitExtrinsic", params).await; + log::info!( + "Node's response to spend transaction: {:?}", + genesis_spend_response + ); + if let Err(_) = genesis_spend_response { + Err(anyhow!("Node did not accept the transaction"))?; + } else { + println!( + "Transaction queued. When accepted, the following UTxOs will become available:" + ); + // Print new output refs for user to check later + let tx_hash = ::hash_of(&Encode::encode(&transaction)); + for (i, output) in transaction.transaction_body.outputs.iter().enumerate() { + let new_value_ref = Input { + tx_hash, + index: i as u32, + }; + let amount = &output.value; + + println!( + "{:?} worth {amount:?}.", + hex::encode(Encode::encode(&new_value_ref)) + ); + } + } + + Ok(()) + } else { + Err(anyhow!("Malformed Ship Datum"))? + } +} + #[derive(Debug, PartialEq, Eq, Clone)] pub enum AsteriaDatum { Ok { diff --git a/game/src/lib.rs b/game/src/lib.rs index fdd8a8d..d926f62 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -17,6 +17,8 @@ pub enum Command { CreateShip(CreateShipArgs), /// Gather fuel using a ship and a fuel pellet GatherFuel(GatherFuelArgs), + /// Move a ship to a new position + MoveShip(MoveShipArgs), } impl GameCommand { @@ -39,6 +41,10 @@ impl GameCommand { let _ = game::gather_fuel(&db, &client, &keystore, args).await; Ok(()) } + Command::MoveShip(args) => { + let _ = game::move_ship(&db, &client, &keystore, slot_config, args).await; + Ok(()) + } }, None => { log::info!(" Asteria game"); @@ -118,3 +124,52 @@ pub struct GatherFuelArgs { )] pub validity_interval_start: u64, } + +#[derive(Debug, Args, Clone)] +pub struct MoveShipArgs { + #[arg(long, short, verbatim_doc_comment, value_parser = utils::input_from_string, required = true, value_name = "SHIP_OUTPUT_REF")] + pub ship: Input, + + /// 32-byte H256 public key of an input owner. + /// Their pk/sk pair must be registered in the wallet's keystore. + #[arg(long, short, verbatim_doc_comment, value_parser = utils::h256_from_string, default_value = keystore::SHAWN_PUB_KEY, value_name = "PUBLIC_KEY")] + pub witness: H256, + + #[arg( + long, + short, + verbatim_doc_comment, + required = true, + allow_negative_numbers = true, + value_name = "POS_X" + )] + pub pos_x: i16, + + #[arg( + long, + short, + verbatim_doc_comment, + required = true, + allow_negative_numbers = true, + value_name = "POS_Y" + )] + pub pos_y: i16, + + #[arg( + long, + short, + verbatim_doc_comment, + required = true, + value_name = "VALIDITY_INTERVAL_START" + )] + pub validity_interval_start: u64, + + #[arg( + long, + short, + verbatim_doc_comment, + required = true, + value_name = "TIME_TO_LIVE" + )] + pub ttl: u64, +} From 85d0b2c1c6a2617885c9401c25eba7cd5944f6ea Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Wed, 12 Nov 2025 01:46:07 -0300 Subject: [PATCH 13/20] add command for mining asteria --- game/src/game.rs | 247 ++++++++++++++++++++++++++++++++++++++++++++++- game/src/lib.rs | 26 +++++ 2 files changed, 272 insertions(+), 1 deletion(-) diff --git a/game/src/game.rs b/game/src/game.rs index bd37f40..d414e74 100644 --- a/game/src/game.rs +++ b/game/src/game.rs @@ -1,4 +1,4 @@ -use crate::{CreateShipArgs, GatherFuelArgs, MoveShipArgs}; +use crate::{CreateShipArgs, GatherFuelArgs, MineAsteriaArgs, MoveShipArgs}; use anyhow::anyhow; use griffin_core::{ checks_interface::{babbage_minted_tx_from_cbor, babbage_tx_to_cbor}, @@ -31,6 +31,7 @@ use sp_core::ed25519::Public; use sp_runtime::traits::{BlakeTwo256, Hash}; const SHIP_FEE: Coin = 3000000; +const MAX_ASTERIA_MINING: u64 = 50; const ASTERIA_SCRIPT_HEX: &str = "590d3c01000033332323232323232323232323232322232232232323232232323232253330163232323232323232533301e300c3020375400e264646464a666044602a60486ea80044c8c8c8c8c8c8c94ccc0a4c0700184c94ccc0b800454cc0ac094584c94ccc0bcc0c80084c94ccc0b0c064c0b8dd500089919191919192999819299981919baf300b303537540106e98cc894ccc0d0c09c0b040044c8c8cc00400400c894ccc0ec0044cc0f0cdd8261014000374c00697adef6c60132323232533303b3375e66012911000024c103d879800013304033760981014000374c00e00a2a66607666e3d22100002132533303c302f303e375400226608266ec13010140003042303f3754002008200864a666078a66608000229445280a6103d87a80001301d33041374c00297ae03233001001002225333041001133042337609801014000375006a97adef6c6013232323253330413375e6601e911000024c103d879800013304633760981014000375007200a2a66608266e3d22100002132533304230353044375400226608e66ec1301014000304830453754002008200864a666084606a002298103d87a80001302333047375000297ae03370000207226608c66ec0dd48011ba800133006006003375a60860066eb8c104008c114008c10c0044cc100cdd81ba9002374c0026600c00c0066eacc0f400cdd7181d801181f801181e8009919001191980080080111299981d8008a4c264a66607800229309919299981d1816981e1baa33008375c607860800086eb8c0f00084cc014014cc0fc00800454cc0ed2401326b65797320696e206173736f63696174697665206c697374206172656e277420696e20617363656e64696e67206f7264657200163040002303e001303e0013303933760981014000375005897adef6c60225333034337200040022980103d8798000153330343371e0040022980103d87a800014c103d87b800037566016606a6ea8c02cc0d4dd50080a511533033491146d7573745f6164645f666565203f2046616c73650014a02a666064a666064006294454cc0cd2411d6d7573745f686f6c645f61646d696e5f746f6b656e203f2046616c73650014a02a666064a666064004294454cc0cd2411e6d7573745f696e6372656d656e745f636f756e746572203f2046616c73650014a02a666064002294454cc0cd2401256d7573745f70726573657276655f73686970796172645f706f6c696379203f2046616c73650014a029405280a503371e6eb8c028c0d0dd500200a19b87375a602460666ea800ccdc000a2400466e21200033300a3756601060646ea8014dd7180898191baa029375c601060646ea80a4cc0800040ad4cccccc0d4004400454cc0b80a85854cc0b80a85854cc0b80a85854cc0b80a858c0c8c0bcdd50008a998168140b180298171baa001153302c0261630300013300100f23375e6018605a6ea8004c030c0b4dd5180198169baa008132533302a3018007132533302f001153302c0261613253330303033002132533302d301a302f375400226464646464a666064604a60686ea80044c8c8c94ccc0d54ccc0d40145288a9981b24811d6d7573745f696e7075745f736869705f746f6b656e203f2046616c73650014a02a66606aa66606a004294454cc0d92411f6d7573745f726573706563745f6d61785f6d696e696e67203f2046616c73650014a02a66606a002294454cc0d924011b6d7573745f70726573657276655f646174756d203f2046616c73650014a0294052819baf0280063232323371266e08dd6981e0009bad303c303d002337046eb4c0f0008dd6981e181e800981c1baa323230183303c375066e08dd6981e8011bad303d0013303c375066e08dd6981e981f0011bad303d303e0014bd70181c9baa32323232301b3303f375066e04cdc11bad3040004001337046eb4c10000800ccc0fcdd419b820030014bd701bad303f3040001303b3754607c60766ea801cdd6981e981f000981c9baa300348008c0e0dd5180118019bab300e30383754601c60706ea804cc0dcdd5180098011bab300d303737540124602a660726ea0004cc0e530010101004bd701199807000a450048810015330334913f65787065637420536f6d652870657263656e7461676529203d20726174696f6e616c2e6e6577286d61785f617374657269615f6d696e696e672c20313030290016533303130244832004530103d87a80001533303133710906400a4000260246606c60246606c6ea0cdc0a400004e6606c6ea0cdc024000906380a5eb812f5c0260246606c60246606c6ea009ccc0d9301021864004bd7025eb80c01ccc04005c8c8cc004004c8cc004004c94ccc0d0c088c0d8dd50008a5eb7bdb1804dd5981d181b9baa0013300f37566018606c6ea8c030c0d8dd500180b11299981c0008a5eb804cc0e4c0d8c0e8004cc008008c0ec004894ccc0dc004528099299981a19b8f33371890001b8d489045348495000375c607400491104534849500014a2266006006002607400266042002058a66666606c00220022a6605e0562c2a6605e0562c2a6605e0562c2a6605e0562c606660606ea800454cc0b80a458c018c0bcdd50008a998168138b181880099801008119baf300d302e3754002601a605c6ea8c010c0b8dd50048a99981518009980500892999815999815a999815980f18169baa300d302e3754601a605c6ea8c010c0b8dd50008a5014a294128899b8848000ccc018dd5980218171baa3004302e37540026eb8c034c0b8dd50129bae3004302e375404a29405288a99815a481296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a04a666054603a60586ea80045288a5022323300100100322533303000114bd70099192999817180280109981980119802002000899802002000981a00118190009181718178009181698171817000911192999814980b98159baa0011480004dd6981798161baa0013253330293017302b3754002298103d87a80001323300100137566060605a6ea8008894ccc0bc004530103d87a80001323232533302e3371e00e6eb8c0c000c4c03ccc0ccdd4000a5eb804cc014014008dd6981800118198011818800998020018011119198008008019129998160008a60103d87a80001323232533302b3371e00c6eb8c0b400c4c030cc0c0dd3000a5eb804cc014014008dd598168011818001181700098129baa0123028302537540022a6604692013c65787065637420536f6d6528617374657269615f696e70757429203d2066696e645f696e70757428696e707574732c20617374657269615f726566290016323300200923375e600a604c6ea8004008c09cc090dd50051119198008008019129998140008a60103d87a80001323253330263005002130073302b0024bd70099802002000981600118150009ba5480008c09400454cc07d24123657870656374205370656e6428617374657269615f72656629203d20707572706f73650016375c604660480046eb4c088004c078dd50079bac3020302130210023758603e00260366ea8c078008c074c078004c064dd50008a4c2a6602e9211856616c696461746f722072657475726e65642066616c73650013656325333015300800115333019301837540082930a9980b0098b0a99980a98018008a99980c980c1baa004149854cc05804c5854ccc054c00800454ccc064c060dd50020a4c2a6602c0262c2a6602c0262c602c6ea800cdc3a40086e1d200253333330190011001153301200f16153301200f16153301200f16153301200f163300100300e225333010300330123754004264a66602a0022a660240042c26464a66602e0022a660280082c264a66603060360042930a9980a8028b19299999980e0008a9980a8028b0a9980a8028b0a9980a8028b0a9980a8028b09bae0013019001301900232533333301a0011533013003161533013003161533013003161375a0022a660260062c602e00260266ea800854cc04400458dc3a4000a66666602800220022a6601a0162c2a6601a0162c2a6601a0162c2a6601a0162c6eb4004dd6800a499c657870656374205b617374657269615f6f75747075745d203d0a202020202020202020206c6973742e66696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d20617374657269615f696e7075742e6f75747075742e61646472657373207d2c0a20202020202020202020290049013f65787065637420496e6c696e65446174756d28617374657269615f6f75747075745f646174756d29203d20617374657269615f6f75747075742e646174756d0049014065787065637420617374657269615f6f75747075745f646174756d3a2041737465726961446174756d203d20617374657269615f6f75747075745f646174756d0049011972656465656d65723a204173746572696152656465656d657200490113646174756d3a2041737465726961446174756d005734ae7155ceaab9e5573eae815d0aba257489812fd8799f581c516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d284c6173746572696141646d696eff004c01051a002dc6c0004c010218320001"; const SHIP_SCRIPT_HEX: &str = "592e3101000033333333323232323232323232323232323232323232323232323223223222232232232232223253333330280021532323232323232323330283001302a37540142a660529211c52756e6e696e672032206172672076616c696461746f72206d696e740013232533302a3232323232323232325333033300c303537540102646464a66606c601e60706ea80384c8c8c94ccc0e4c048c0ecdd500089919191919299981f180c98201baa0011323232325333046001153304303e161325333047304a0021325333044301f30463754002264646464a666090604860946ea80044c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c94ccc16d4ccc16c0805288a9982e24811d6d7573745f62655f76616c69645f61737465726961203f2046616c73650014a02a6660b6a6660b6010294454cc171241206d7573745f6d696e745f65787065637465645f76616c7565203f2046616c73650014a02a6660b6a6660b600e294454cc171241216d7573745f726573706563745f6d696e5f64697374616e6365203f2046616c73650014a02a6660b6a6660b600c294454cc1712411b6d7573745f686176655f736869705f6e616d65203f2046616c73650014a02a6660b6a6660b600a294454cc1712411c6d7573745f686176655f70696c6f745f6e616d65203f2046616c73650014a02a6660b6a6660b6008294454cc1712411d6d7573745f686176655f6c61746573745f74696d65203f2046616c73650014a02a6660b6a6660b6006294454cc1712411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660b6a6660b6004294454cc1712411e6d7573745f686f6c645f696e697469616c5f6675656c203f2046616c73650014a02a6660b6002294454cc17124011a6d7573745f686f6c645f335f617373657473203f2046616c73650014a029405280a5014a029405280a5014a06068664600200244a6660c0002290000981d99801001183180099198008009bab3025305e375403244a6660c0002297ae01323332223233001001003225333066001100313233068374e660d06ea4018cc1a0dd49bae30650013306837506eb4c1980052f5c06600600660d400460d00026eb8c17c004dd59830000998018019832001183100099b8733301f3756604660b86ea805c1252201044655454c0003f303433301e3756604460b66ea805809401ccdc39bad305d305e305e305e305e305a37540246eb4c174c168dd500819b8f375c60b860ba60ba60ba60b26ea8044010cdc79bae30193058375402000866e240e0c8cdc018009bad301e3058375402060026eb4c07cc160dd50081299982a99b88001480004c0cc0044004cdd79ba601f374c64646466660026666002a6660ac606490000a5eb7bdb1804c8c8cc0040052f5bded8c044a6660ba0022660bc66ec0dd48131ba60034bd6f7b630099191919299982e98049980501500109983119bb037520546e9801c01454ccc174cdc781500109983119bb037520546e9801c00c4cc188cdd81ba9002374c0026600c00c0066eacc17c00cdd7182e8011830801182f8009919800800a5eb7bdb180894ccc1700044cc174cdd81ba90074c010101004bd6f7b630099191919299982e18041980480580109983099bb037520169810101000051533305c3371e0160042660c266ec0dd4805a61010100003133061337606ea4008dd4000998030030019bad305e003375c60b800460c000460bc0020460089001023245044655454c0003c22225333059303200110041323233001001006225333060001133061337606ea4018dd3001a5eb7bdb1804c8c8c8c94ccc180c030cc0340280084cc194cdd81ba900a374c00e00a2a6660c066e3c0280084c94ccc184c0e8c18cdd500089983319bb0375201660ce60c86ea80040104010c94ccc1854ccc1940045288a5014c0103d87a80001303e33066374c00297ae03233001001002225333066001133067337606ea402cdd400525eb7bdb1804c8c8c8c94ccc198c048cc04c03c0084cc1accdd81ba900f375001c00a2a6660cc66e3c03c0084c94ccc19cc100c1a4dd500089983619bb0375202060da60d46ea80040104010c94ccc19cc1000045300103d87a8000130443306c375000297ae03370000201c2660d666ec0dd48011ba800133006006003375a60d00066eb8c198008c1a8008c1a00044cc194cdd81ba9002374c0026600c00c0066eacc18800cdd7183000118320011831000991900119198008008011129998300008a4c264a6660c200229309919299982f981c18309baa3300c375c60c260ca0086eb8c1840084cc014014cc19000800454cc1812401326b65797320696e206173736f63696174697665206c697374206172656e277420696e20617363656e64696e67206f7264657200163065002306300130630013305e337606ea4008dd4000a5eb7bdb180dd7a60103d879800022533305533720004002298103d8798000153330553371e0040022980103d87a800014c103d87b8000330024890550494c4f540030033004375a603660aa6ea804ccc005220104534849500030023003375a603460a86ea804888cdc500100091b9800123732660046ea00052201003001001222533333305700213232323232323300b0020013371491010128000025333053337100069007099b80483c80400c54ccc14ccdc4001a410004266e00cdc0241002800690068a9982a24929576861742061726520796f7520646f696e673f204e6f2049206d65616e2c20736572696f75736c792e001653330560011337149101035b5d2900004133714911035b5f2000375c60aa66600e00266ec1300102415d00375266e292210129000042233760980103422c2000375266601001000466e28dd7182b0009bae3057001375860a80046eb4c148004c8cdd81ba83052001374e60a60026ea80084c94ccc1500044cdc5245027b7d00002133714911037b5f2000375c60a664646600200200644a6660ae00220062664466ec130103422c2000375266601201260ae00466e29221023a20003330090093058002337146eb8c15c004dd7182c000982c80099801001182d00099bb04c10342207d0037520046eac0084c94ccc1500044cdc52441025b5d00002133714911035b5f2000375c60a666600a00266ec1300102415d0037520044466ec1300103422c2000375266600c00c00466e28dd7182a0009bae3055001375800426600a6eb40080044c8c8cdc524410268270000132333001001337006e3400920013371491101270000322253330533371000490000800899191919980300319b8000548004cdc599b80002533305633710004900a0a40c02903719b8b33700002a6660ac66e2000520141481805206e0043370c004901019b8300148080cdc70020011bae00222232330010010042253330540011004133003305600133002002305700122323300100100322533304e30270011337149110130000031533304e337100029000099b8a489012d0033002002302c00113300533708002900a19b8b3370066e1400520144818000cc0040048894ccc12ccdc4801240002002266600600666e1000920143371666e00cdc28012402890300008a9982481f0b180818251baa3011304a375402aa66608c603e60906ea80044c94ccc12c00454cc120110584c8c94ccc13400454cc128118584c8c94ccc13c00454cc130120584c8c94ccc14400454cc138128584c8c94ccc14c00454cc140130584c94ccc150c15c008526153305104d16325333333058001153305104d16153305104d16153305104d161375a0022a660a209a2c60aa00260aa00464a6666660ac0022a6609e0962c2a6609e0962c2a6609e0962c2a6609e0962c26eb8004c14c004c14c008c94cccccc15000454cc1341245854cc1341245854cc1341245854cc134124584dd7000982880098288011929999998290008a998258238b0a998258238b0a998258238b09bad001153304b04716304f001304f0023253333330500011533049045161533049045161533049045161375a0022a6609208a2c609a00260926ea800454cc11c10c594cccccc134004400454cc1181085854cc1181085854cc1181085854cc11810858c128c11cdd50008a99822a493165787065637420496e6c696e65446174756d28736869705f646174756d29203d20736869705f73746174652e646174756d00163007304637540022a6608807e2c6090002646600200202644a66608e002297ae0132325333045325333046302230483754002266e3c04cdd7182618249baa00114a0601c60906ea8c038c120dd50010998250011980200200089980200200098258011824800a999820180c98211baa0011325333045001153304203c16132325333047001153304403e161325333048304b002149854cc1140fc58c94cccccc13000454cc1140fc5854cc1140fc5854cc1140fc5854cc1140fc584dd7000982480098248011929999998250008a9982181e8b0a9982181e8b0a9982181e8b09bad001153304303d163047001304337540022a660820762ca66666608e00220022a660800742c2a660800742c2a660800742c2a660800742c608860826ea800454cc0fd2413e65787065637420496e6c696e65446174756d28617374657269615f646174756d29203d20617374657269615f696e7075742e6f75747075742e646174756d0016300130403754600e60806ea80108c10cc110c110004c06cccc004dd59802981f1baa3005303e37540046eb8c010c0f8dd50141bae3005303e375405044464a66607c603460806ea8004520001375a608860826ea8004c94ccc0f8c068c100dd50008a60103d87a8000132330010013756608a60846ea8008894ccc110004530103d87a8000132323253330433371e00e6eb8c11400c4c080cc120dd4000a5eb804cc014014008dd698228011824001182300099804001801181f981e1baa001153303a03116323300100100c22533303e00114c103d87a800013232533303c32533303d3016303f375400229404cdc79bae304330403754002056600a607e6ea8c014c0fcdd51803181f9baa00213019330410024bd70099802002000982100118200009181f0009181e981f000899299981d8008a9981c01a8b099299981e181f8010a99981c19b8748004dd6981d8008a51153303903616153303903616303d001325333037301330393754002297adef6c6013756607a60746ea8004cc00400800c88c8cc00400400c894ccc0f40045300103d87a80001323232533303c3371e00c6eb8c0f800c4c064cc104dd3000a5eb804cc014014008dd5981f0011820801181f800991980080080211299981d0008a5eb7bdb1804c8c8c8c94ccc0e8cdc7a44100002100313303f337606ea4008dd3000998030030019bab303c003375c6074004607c00460780026eb8c0e4c0d8dd50040a9981a24926657870656374204d696e742873686970796172645f706f6c69637929203d20707572706f7365001630383039303930390023756606e002606e606e0046eb0c0d4004c0d4c0d4008dd6181980098179baa303200230313032001302d37540182930a99815a4811856616c696461746f722072657475726e65642066616c7365001365632533302a30030011533302e302d37540042930a998158148b0a99981518030008a99981718169baa002149854cc0ac0a45854cc0ac0a458c0acdd5000a99999981800588058a998148138b0a998148138b0a998148138b0a998148138b0a99814a491d52756e6e696e672033206172672076616c696461746f72207370656e640013323232232322533302f323232323232323232323232323232323232323232325333045301e30473754002264a66608c604460906ea80584c8c94ccc120c084c128dd5000899192999825181318261baa001132323232323232323232323232325323233305a303300d1323232325333062001153305f05016132533306330660021325333060303b30623754002264646464a6660c8608060cc6ea80044c8c94ccc198c108c1a0dd50008991919192999835182198361baa001132323232323232323232323253330765333076305230263301f044230293035307a3754606c60f46ea80045288a9983ba481236d7573745f7370656e645f6f6e655f7363726970745f696e707574203f2046616c73650014a02a6660eca6660ec054294454cc1dd241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660eca6660ec008294454cc1dd2411d6d7573745f686176655f656e6f7567685f6675656c203f2046616c73650014a02a6660eca6660ec00c294454cc1dd2411e6d7573745f726573706563745f6d61785f7370656564203f2046616c73650014a02a6660eca6660ec00a294454cc1dd241206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a02a6660eca6660ec004294454cc1dd241216d7573745f73756274726163745f6675656c5f746f6b656e73203f2046616c73650014a02a6660eca6660ec010294454cc1dd2411c6d7573745f6275726e5f7370656e745f6675656c203f2046616c73650014a02a6660eca6660ec014294454cc1dd241156d7573745f7570646174655f78203f2046616c73650014a02a6660eca6660ec012294454cc1dd241156d7573745f7570646174655f79203f2046616c73650014a02a6660eca6660ec00e294454cc1dd2411f6d7573745f7570646174655f75707065725f626f756e64203f2046616c73650014a02a6660eca6660ec016294454cc1dd241216d7573745f70726573657276655f70696c6f745f746f6b656e203f2046616c73650014a02a6660eca6660ec006294454cc1dd2411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660ec002294454cc1dd24011a6d7573745f686f6c645f335f617373657473203f2046616c73650014a029405280a5014a029405280a5014a029405280a5014a0609e604460486eacc0d0c1e0dd500b99b8733301f3756606660ee6ea80581912201044655454c0033702014018609e66603c6eacc0c8c1d8dd500a81481b19b8900a008301900d32323371266e08dd6983c0011bad30783079001337046eb4c1e0004dd6983c183c801183a1baa02c3073375460ec60e66ea801ccdc39bad307530763076307630763072375401c012602a609800c66e1cdd6981618381baa00c3370006402266e1cdd6981518379baa00b3370006602266e3c0b0dd7183898391839183918371baa00a3330153756605260da6ea8c0a4c1b4dd501102d2441044655454c00153306b4915865787065637420536f6d6528737065656429203d0a20202020202020202020726174696f6e616c2e6e65772864697374616e63652c2074785f6c61746573745f74696d65202d2074785f6561726c696573745f74696d65290016330260023370200600a66e08004140c8cdc0180080698008061299983419b88001480004c1180044004dd6983618349baa001153306705c16302330683754604860d06ea80b8dd6983518339baa001153306505916302130663754604260cc6ea80b0cc0e40041594cccccc1a4004400454cc1881545854cc1881545854cc1881545854cc18815458c198c18cdd50008a998308298b180498311baa00115330600511630640013300602923375e603860c26ea8004c070c184dd5180e98309baa016375a60c460c60046eb4c184004c174dd50170a99982d181b0068991929998300008a9982e8270b09929998309832001099299982f181c98301baa0011323232325333062303b306437540022646464a6660ca608060ce6ea80044c8c8c8c94ccc1a4c114c1acdd5000899191919191919191929998392999839182698111980d820118129818983b1baa303230763754002294454cc1cd2401246d7573745f7370656e645f74776f5f7363726970745f696e70757473203f2046616c73650014a02a6660e4a6660e401e294454cc1cd2411c6d7573745f62655f76616c69645f70656c6c6574203f2046616c73650014a02a6660e4a6660e404c294454cc1cd241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660e4a6660e4010294454cc1cd241216d7573745f686176655f70656c6c65745f706f736974696f6e203f2046616c73650014a02a6660e4a6660e4006294454cc1cd2411c6d7573745f6164645f6675656c5f746f6b656e73203f2046616c73650014a02a6660e4a6660e400e294454cc1cd241206d7573745f6e6f745f6578636565645f6361706163697479203f2046616c73650014a02a6660e4a6660e400a294454cc1cd241206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a02a6660e4a6660e400c294454cc1cd2411b6d7573745f70726573657276655f646174756d203f2046616c73650014a02a6660e4a6660e4008294454cc1cd2411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660e4a6660e4004294454cc1cd2411a6d7573745f686f6c645f335f617373657473203f2046616c73650014a02a6660e4002294454cc1cd24011c6d7573745f6e6f745f6d696e745f746f6b656e73203f2046616c73650014a029405280a5014a029405280a5014a0294052819baf374c603a07698101a000304a301d301f3756605e60e66ea8050cdc399980d1bab302e307237540260be911044655454c003370000c02a60946660326eacc0b4c1c4dd5009012018980a9bad30733070375400a66ebc034110cdc499b80002011055533306a3370e0626eb4c0a0c1b4dd5002099b8702f375a605260da6ea801052819980a1bab3028306c3754605060d86ea8084165221044655454c00153306a05e163026306b3754604c60d66ea80c54ccc19cc100c1a4dd500089929998360008a9983482f8b0991929998370008a998358308b0991929998380008a998368318b0992999838983a0010a4c2a660dc0c82c64a6666660ea0022a660dc0c82c2a660dc0c82c2a660dc0c82c2a660dc0c82c26eb8004c1c8004c1c8008c94cccccc1cc00454cc1b01885854cc1b01885854cc1b0188584dd68008a998360310b183800098380011929999998388008a998350300b0a998350300b0a998350300b09bad001153306a06016306e001306a37540022a660d00bc2ca6666660dc00220022a660ce0ba2c2a660ce0ba2c2a660ce0ba2c2a660ce0ba2c60d660d06ea800454cc1992413c65787065637420496e6c696e65446174756d2870656c6c65745f646174756d29203d2070656c6c65745f696e7075742e6f75747075742e646174756d0016300e30673754604660ce6ea8008c10cccc038dd5981118331baa3022306637540026eb8c084c198dd50281bae3022306637540a060d060ca6ea800454cc18d2401ff65787065637420536f6d652870656c6c65745f696e70757429203d0a202020202020202020206c6973742e66696e64280a202020202020202020202020696e707574732c0a202020202020202020202020666e28696e70757429207b0a20202020202020202020202020207768656e20696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c206973207b0a20202020202020202020202020202020566572696669636174696f6e4b657943726564656e7469616c285f29202d3e2046616c73650a2020202020202020202020202020202053637269707443726564656e7469616c28616464725f7061796d656e6b7429202d3e0a202020202020202020202020202020202020616464725f7061796d656e74203d3d2070656c6c65745f76616c696461746f725f616464726573730a20202020202020202020202020207d0a2020202020202020202020207d2c0a202020202020202020202900163301b02f2325333063303c3065375400229404cdc79bae3069306637540020a6604060ca6ea8c080c194dd5181098329baa00133037001054533333306700110011533060053161533060053161533060053161533060053163064306137540022a660be0a22c600e60c06ea800454cc17813c58c188004cc01009c8cdd7980d182f9baa001301a305f3754603660be6ea8050dd69830182e9baa02e1533305a303500d132533305b3034305d375400226464a6660ba607260be6ea80044c8c8c8c94ccc1854ccc184c0f0c044cc0280bc8c050c080c194dd5181098329baa00114a22a660c49201246d7573745f7370656e645f74776f5f7363726970745f696e70757473203f2046616c73650014a02a6660c2a6660c200c294454cc1892411d6d7573745f62655f76616c69645f61737465726961203f2046616c73650014a02a6660c2a6660c202a294454cc189241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660c2a6660c2008294454cc189241226d7573745f686176655f617374657269615f706f736974696f6e203f2046616c73650014a02a6660c2a6660c2006294454cc1892411c6d7573745f6275726e5f736869705f746f6b656e203f2046616c73650014a02a6660c2a6660c2002294454cc1892411d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a02a6660c2004294454cc1892401206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a029405280a5014a029405281803981f1998059bab301f30633754603e60c66ea80601412201044655454c003007375a60ca60c46ea800ccdc4199804980501400a010a400066ebcdd31983119bb037500486ea00892f5bded8c06e98cc1892f7b6301010000010100004bd6f7b6300a9982f0290b180d182f9baa301a305f375404a607666600c6eacc068c178dd5180d182f1baa3061305e37540026eb8c064c178dd50241bae301a305e37540902a660b80a62c66028050464a6660b8606a60bc6ea8004528099b8f375c60c460be6ea8004128c064c178dd5180c982f1baa301a305e375400226464a6660b8a6660b8607060186600a0544601e603660c06ea8c070c180dd50008a51153305d491236d7573745f7370656e645f6f6e655f7363726970745f696e707574203f2046616c73650014a02a6660b8a6660b8020294454cc175241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660b8a6660b8004294454cc1752411c6d7573745f6275726e5f736869705f746f6b656e203f2046616c73650014a02a6660b8002294454cc17524011d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a029405280a50300230393330063756603460bc6ea8c068c178dd5009825a441044655454c003371066600a600c04802003a90001b8733300430050230494881044655454c00371203044646600200200644a6660be002297ae013232533305d300500213306200233004004001133004004001306300230610012305d305e305e0012223253330593035305b37540022900009bad305f305c375400264a6660b2606a60b66ea80045300103d87a800013233001001375660c060ba6ea8008894ccc17c004530103d87a80001323232533305e3371e00e6eb8c18000c4c0eccc18cdd4000a5eb804cc014014008dd6983000118318011830800998068018011191980080080111299982d8008a5eb7bdb1804c8c8c8c94ccc16ccdc7a441000021003133060337606ea4008dd3000998030030019bab305d003375c60b600460be00460ba002600200244a6660b0002290000981999801001182d8009191980080080111299982c0008a5eb804c8ccc888c8cc00400400c894ccc178004400c4c8cc180dd3998301ba90063306037526eb8c174004cc180dd41bad305e0014bd7019801801983100118300009bae3057001375660b00026600600660b800460b4002600200244a6660aa002290000981819801001182c00092999827981418289baa300d30523754002294052898279baa021533304c3025304e37546600c03446466002002646600200264a6660a0605860a46ea800452f5bded8c026eacc158c14cdd5000998021bab300e30523754601c60a46ea800c014894ccc15000452f5c02660aa60a460ac0026600400460ae00244a6660a600229404c94ccc140cdc79bae305600201114a226600600600260ac00229445281119198008008019129998298008a60103d87a8000132323253330523371e00c6eb8c15000c4c0bccc15cdd3000a5eb804cc014014008dd5982a001182b801182a8009bae3050304d37540022a660969215d6578706563742053637269707443726564656e7469616c2873686970796172645f706f6c69637929203d0a202020202020736869705f696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c00163007304c3754600e60986ea8c020c130dd5000982718259baa001153304949013665787065637420536f6d6528736869705f696e70757429203d2066696e645f696e70757428696e707574732c20736869705f726566290016323300201623375e600e60986ea8004008c134c128dd500b9119198008008019129998270008a60103d87a800013232533304c300500213029330510024bd70099802002000982900118280008a99823a48120657870656374205370656e6428736869705f72656629203d20707572706f73650016304b304837540022a6608c92015865787065637420536f6d65286d61785f73706565645f726174696f6e616c29203d0a202020202020726174696f6e616c2e6e6577286d61785f73706565642e64697374616e63652c206d61785f73706565642e74696d6529001633001375a6004608e6ea80c0dd6980198239baa030225333045301e00114c103d87a80001533304533710002900009811198251811198251ba830230023304a3750604600297ae04bd7009811198251811198251ba80023304a375000297ae04bd70118248009182418248009bad30463047002375c608a002608a0046eb8c10c004c10c008dd6982080098208011bad303f001303b3754020607a607c607c607c0046eacc0f0004c0f0c0f0008dd6181d000981d181d0011bac303800130343754606e004606c606e00260646ea8004526153303049011856616c696461746f722072657475726e65642066616c7365001365632533302e30070011325333033001153303002816132325333035001153303202a1613253330363039002149854cc0cc0ac58c94cccccc0e800454cc0cc0ac5854cc0cc0ac5854cc0cc0ac584dd68008a998198158b181b800981b80119299999981c0008a998188148b0a998188148b0a998188148b09bad0011533031029163035001303137540042a66605c6014002264a6660660022a660600502c264a666068606e0042930a998188148b19299999981c0008a998188148b0a998188148b0a998188148b09bad0011533031029163035001303137540042a66605c60120022a66606460626ea8008526153302f027161533302e300800115333032303137540042930a998178138b0a998178138b18179baa00153333330340011001153302d02516153302d02516153302d02516153302d025163300100202422533302b3004302d3754004264a6660600022a6605a0042c26464a6660640022a6605e0082c26464a6660680022a6606200c2c26464a66606c0022a660660102c26464a6660700022a6606a0142c264a66607260780042930a9981b0058b19299999981e8008a9981b0058b0a9981b0058b0a9981b0058b09bad001153303600b16303a001303a00232533333303b0011533034009161533034009161533034009161533034009161375c0026070002607000464a6666660720022a6606400e2c2a6606400e2c2a6606400e2c2a6606400e2c26eb8004c0d8004c0d8008c94cccccc0dc00454cc0c00145854cc0c00145854cc0c0014584dd68008a998180028b181a000981a00119299999981a8008a998170018b0a998170018b0a998170018b09bad001153302e003163032001302e37540042a660580022ca66666606001620162a660520442c2a660520442c2a660520442c2a660520442c605c60566ea8028dc3a40006e1d2006370e90021b8748008dd2a40006e052000370090011b884800054cc0840045854cc0840045854cc0840045854cc08400459240191496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e00375a0026eb4004dd68009bad001375c0026eb800524196657870656374205b736869705f6f75747075745d203d0a202020202020202020206c6973742e66696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d20736869705f696e7075742e6f75747075742e61646472657373207d2c0a20202020202020202020290049013965787065637420496e6c696e65446174756d28736869705f6f75747075745f646174756d29203d20736869705f6f75747075742e646174756d0049013765787065637420736869705f6f75747075745f646174756d3a2053686970446174756d203d20736869705f6f75747075745f646174756d004901476578706563742046696e6974652874785f6561726c696573745f74696d6529203d2076616c69646974795f72616e67652e6c6f7765725f626f756e642e626f756e645f74797065004901456578706563742046696e6974652874785f6c61746573745f74696d6529203d2076616c69646974795f72616e67652e75707065725f626f756e642e626f756e645f747970650049012f6578706563742070656c6c65745f646174756d3a2050656c6c6574446174756d203d2070656c6c65745f646174756d004901ff65787065637420536f6d6528617374657269615f696e70757429203d0a202020202020202020206c6973742e66696e64280a202020202020202020202020696e707574732c0a202020202020202020202020666e28696e70757429207b0a20202020202020202020202020207768656e20696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c206973207b0a20202020202020202020202020202020566572696669636174696f6e4b657943726564656e7469616c285f29202d3e2046616c73650a2020202020202020202020202020202053637269707443726564656e7469616c28616464725f7061796d656d6e7429202d3e0a202020202020202020202020202020202020616464725f7061796d656e74203d3d20617374657269615f76616c696461746f725f616464726573730a20202020202020202020202020207d0a2020202020202020202020207d2c0a20202020202020202020290049011672656465656d65723a205368697052656465656d657200490110646174756d3a2053686970446174756d0049013265787065637420617374657269615f646174756d3a2041737465726961446174756d203d20617374657269615f646174756d00490159657870656374205b736869705f73746174655d203d0a202020202020202020207472616e73616374696f6e2e66696e645f7363726970745f6f757470757473286f7574707574732c2073686970796172645f706f6c696379290049012965787065637420736869705f646174756d3a2053686970446174756d203d20736869705f646174756d00490120657870656374205b285f2c202d31295d203d206d696e7465645f746f6b656e730049011a72656465656d65723a20536869707961726452656465656d6572005734ae7155ceaab9e5573eae815d0aba257489811e581c6a25ad5476105ac4a3784769cb93f92fd67a11932ef9a65a61abd1d6004c011e581cbac1753d5f7e3609c92776371fd0eafa753889e5712858f48fb83981004c012fd8799f581c516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d284c6173746572696141646d696eff004c0108d8799f01197530ff004c01021864004c010101004c0102181e004c01010a0001"; @@ -648,6 +649,250 @@ pub async fn move_ship( } } +pub async fn mine_asteria( + db: &Db, + client: &HttpClient, + keystore: &LocalKeystore, + args: MineAsteriaArgs, +) -> anyhow::Result<()> { + log::debug!("The args are:: {:?}", args); + + let asteria_script: PlutusScript = PlutusScript(hex::decode(ASTERIA_SCRIPT_HEX).unwrap()); + let asteria_hash: PolicyId = compute_plutus_v2_script_hash(asteria_script.clone()); + let asteria_address: Address = + Address(hex::decode("70".to_owned() + &hex::encode(asteria_hash)).unwrap()); + + let spacetime_script: PlutusScript = PlutusScript(hex::decode(SHIP_SCRIPT_HEX).unwrap()); + let shipyard_policy: PolicyId = compute_plutus_v2_script_hash(spacetime_script.clone()); + + let pellet_script: PlutusScript = PlutusScript(hex::decode(PELLET_SCRIPT_HEX).unwrap()); + let pellet_policy: PolicyId = compute_plutus_v2_script_hash(pellet_script.clone()); + + // Construct a template Transaction to push coins into later + let mut transaction = Transaction::from((Vec::new(), Vec::new())); + + let asterias = sync::get_outputs_at( + db, + ShowOutputsAtArgs { + address: asteria_address, + }, + )?; + if asterias.len() != 1 { + Err(anyhow!( + "There must be exactly one Asteria UTxO, but found {}", + asterias.len() + ))?; + } + let asteria = &asterias[0]; + let rewards = coin_of(&asteria.value) * MAX_ASTERIA_MINING / 100; + + let (_spacetime_address, ship_value, ship_datum) = + sync::get_unspent(db, &args.ship)?.expect("Ship UTxO not found"); + + let ship_datum_option = ship_datum.clone().map(|d| ShipDatum::from(d)); + + if let Some(ShipDatum::Ok { + pos_x: _, + pos_y: _, + ship_token_name, + pilot_token_name, + last_move_latest_time: _, + }) = ship_datum_option + { + // Asset Names + let fuel_name = AssetName::from("FUEL".to_string()); + + let pilot_utxos = sync::get_outputs_with_asset( + db, + ShowOutputsWithAssetArgs { + policy: shipyard_policy, + name: pilot_token_name.clone().0, + }, + )?; + + if pilot_utxos.len() == 0 { + Err(anyhow!("Pilot UTxO not found"))?; + } + let pilot_utxo = &pilot_utxos[0]; + + let mut inputs = vec![ + args.ship.clone(), + asteria.input.clone(), + pilot_utxo.input.clone(), + ]; + let ordered_inputs: Vec = { + // Lexicographically order inputs by tx_hash and index + inputs.sort_by(|a, b| { + if a.tx_hash == b.tx_hash { + a.index.cmp(&b.index) + } else { + a.tx_hash.cmp(&b.tx_hash) + } + }); + inputs.clone() + }; + transaction.transaction_body.inputs = inputs; + + // BURNS + let ship_fuel = quanity_of(&ship_value, &pellet_policy, &fuel_name); + let ship_fuel_i64: i64 = ship_fuel.try_into().unwrap(); + let burns = Some( + Multiasset::from((shipyard_policy, ship_token_name.clone(), -1)) + + Multiasset::from((pellet_policy, fuel_name.clone(), -ship_fuel_i64)), + ); + + // BUILD REDEEMERS + let ship_redeemer = Redeemer { + tag: RedeemerTag::Spend, + index: ordered_inputs.iter().position(|i| *i == args.ship).unwrap() as u32, + data: PlutusData::from(PallasPlutusData::Constr(Constr { + tag: 122, + any_constructor: None, + fields: Indef( + [PallasPlutusData::Constr(Constr { + tag: 123, + any_constructor: None, + fields: Indef([].to_vec()), + })] + .to_vec(), + ), + })), + }; + + let asteria_redeemer = Redeemer { + tag: RedeemerTag::Spend, + index: ordered_inputs + .iter() + .position(|i| *i == asteria.input) + .unwrap() as u32, + data: PlutusData::from(PallasPlutusData::Constr(Constr { + tag: 122, + any_constructor: None, + fields: Indef([].to_vec()), + })), + }; + + let ship_burn_redeemer = Redeemer { + tag: RedeemerTag::Mint, + index: 0, + data: PlutusData::from(PallasPlutusData::Constr(Constr { + tag: 122, + any_constructor: None, + fields: Indef([].to_vec()), + })), + }; + + let pellet_redeemer = Redeemer { + tag: RedeemerTag::Mint, + index: 1, + data: PlutusData::from(PallasPlutusData::Constr(Constr { + tag: 122, + any_constructor: None, + fields: Indef([].to_vec()), + })), + }; + + let outputs = vec![ + Output { + address: pilot_utxo.address.clone(), + value: pilot_utxo.value.clone() + + Value::Coin(rewards) + + Value::Coin(coin_of(&ship_value)), + datum_option: pilot_utxo.datum_option.clone(), + }, + Output { + address: asteria.address.clone(), + value: asteria.value.clone() - Value::Coin(rewards), + datum_option: asteria.datum_option.clone(), + }, + ]; + + for output in outputs { + transaction.transaction_body.outputs.push(output.clone()); + } + transaction.transaction_body.mint = burns; + transaction.transaction_body.validity_interval_start = Some(args.validity_interval_start); + + let pallas_tx: PallasTransaction = <_>::from(transaction.clone()); + let cbor_bytes: Vec = babbage_tx_to_cbor(&pallas_tx); + let mtx: MintedTx = babbage_minted_tx_from_cbor(&cbor_bytes); + let tx_hash: &Vec = &Vec::from(mtx.transaction_body.original_hash().as_ref()); + log::debug!("Original tx_body hash is: {:#x?}", tx_hash); + + let vkey: Vec = Vec::from(args.witness.0); + let public = Public::from_h256(args.witness); + let signature: Vec = + Vec::from(crate::keystore::sign_with(keystore, &public, tx_hash)?.0); + transaction.transaction_witness_set = <_>::from(vec![VKeyWitness::from((vkey, signature))]); + + transaction.transaction_witness_set.redeemer = Some(vec![ + asteria_redeemer, + ship_redeemer, + ship_burn_redeemer, + pellet_redeemer, + ]); + transaction.transaction_witness_set.plutus_script = + Some(vec![asteria_script, spacetime_script, pellet_script]); + + log::debug!("Griffin transaction is: {:#x?}", transaction); + let pallas_tx: PallasTransaction = <_>::from(transaction.clone()); + log::debug!("Babbage transaction is: {:#x?}", pallas_tx); + + // Send the transaction + let genesis_spend_hex = hex::encode(Encode::encode(&transaction)); + let params = rpc_params![genesis_spend_hex]; + let genesis_spend_response: Result = + client.request("author_submitExtrinsic", params).await; + log::info!( + "Node's response to spend transaction: {:?}", + genesis_spend_response + ); + if let Err(_) = genesis_spend_response { + Err(anyhow!("Node did not accept the transaction"))?; + } else { + println!( + "Transaction queued. When accepted, the following UTxOs will become available:" + ); + // Print new output refs for user to check later + let tx_hash = ::hash_of(&Encode::encode(&transaction)); + for (i, output) in transaction.transaction_body.outputs.iter().enumerate() { + let new_value_ref = Input { + tx_hash, + index: i as u32, + }; + let amount = &output.value; + + println!( + "{:?} worth {amount:?}.", + hex::encode(Encode::encode(&new_value_ref)) + ); + } + } + + Ok(()) + } else { + Err(anyhow!("Malformed Ship Datum"))? + } +} + +fn quanity_of(value: &Value, policy: &PolicyId, name: &AssetName) -> u64 { + if let Value::Multiasset(_, ma) = value { + if let Some(assets) = ma.0.get(policy) { + if let Some(quantity) = assets.0.get(name) { + return *quantity as u64; + } + } + } + 0 +} + +fn coin_of(value: &Value) -> u64 { + match value { + Value::Coin(c) => *c, + Value::Multiasset(c, _) => *c, + } +} + #[derive(Debug, PartialEq, Eq, Clone)] pub enum AsteriaDatum { Ok { diff --git a/game/src/lib.rs b/game/src/lib.rs index d926f62..9bddec2 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -19,6 +19,8 @@ pub enum Command { GatherFuel(GatherFuelArgs), /// Move a ship to a new position MoveShip(MoveShipArgs), + /// Mine Asteria using a ship + MineAsteria(MineAsteriaArgs), } impl GameCommand { @@ -45,6 +47,10 @@ impl GameCommand { let _ = game::move_ship(&db, &client, &keystore, slot_config, args).await; Ok(()) } + Command::MineAsteria(args) => { + let _ = game::mine_asteria(&db, &client, &keystore, args).await; + Ok(()) + } }, None => { log::info!(" Asteria game"); @@ -173,3 +179,23 @@ pub struct MoveShipArgs { )] pub ttl: u64, } + +#[derive(Debug, Args, Clone)] +pub struct MineAsteriaArgs { + #[arg(long, short, verbatim_doc_comment, value_parser = utils::input_from_string, required = true, value_name = "SHIP_OUTPUT_REF")] + pub ship: Input, + + /// 32-byte H256 public key of an input owner. + /// Their pk/sk pair must be registered in the wallet's keystore. + #[arg(long, short, verbatim_doc_comment, value_parser = utils::h256_from_string, default_value = keystore::SHAWN_PUB_KEY, value_name = "PUBLIC_KEY")] + pub witness: H256, + + #[arg( + long, + short, + verbatim_doc_comment, + required = true, + value_name = "VALIDITY_INTERVAL_START" + )] + pub validity_interval_start: u64, +} From 245c189e3868ad44601d77e6aad53e0afbd38289 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Thu, 13 Nov 2025 04:27:31 -0300 Subject: [PATCH 14/20] read scripts from files --- game/src/game.rs | 44 ++++++++++++++++++++++++---------- game/src/scripts/asteria.txt | 1 + game/src/scripts/pellet.txt | 1 + game/src/scripts/spacetime.txt | 1 + 4 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 game/src/scripts/asteria.txt create mode 100644 game/src/scripts/pellet.txt create mode 100644 game/src/scripts/spacetime.txt diff --git a/game/src/game.rs b/game/src/game.rs index d414e74..cd583ab 100644 --- a/game/src/game.rs +++ b/game/src/game.rs @@ -33,9 +33,13 @@ use sp_runtime::traits::{BlakeTwo256, Hash}; const SHIP_FEE: Coin = 3000000; const MAX_ASTERIA_MINING: u64 = 50; -const ASTERIA_SCRIPT_HEX: &str = "590d3c01000033332323232323232323232323232322232232232323232232323232253330163232323232323232533301e300c3020375400e264646464a666044602a60486ea80044c8c8c8c8c8c8c94ccc0a4c0700184c94ccc0b800454cc0ac094584c94ccc0bcc0c80084c94ccc0b0c064c0b8dd500089919191919192999819299981919baf300b303537540106e98cc894ccc0d0c09c0b040044c8c8cc00400400c894ccc0ec0044cc0f0cdd8261014000374c00697adef6c60132323232533303b3375e66012911000024c103d879800013304033760981014000374c00e00a2a66607666e3d22100002132533303c302f303e375400226608266ec13010140003042303f3754002008200864a666078a66608000229445280a6103d87a80001301d33041374c00297ae03233001001002225333041001133042337609801014000375006a97adef6c6013232323253330413375e6601e911000024c103d879800013304633760981014000375007200a2a66608266e3d22100002132533304230353044375400226608e66ec1301014000304830453754002008200864a666084606a002298103d87a80001302333047375000297ae03370000207226608c66ec0dd48011ba800133006006003375a60860066eb8c104008c114008c10c0044cc100cdd81ba9002374c0026600c00c0066eacc0f400cdd7181d801181f801181e8009919001191980080080111299981d8008a4c264a66607800229309919299981d1816981e1baa33008375c607860800086eb8c0f00084cc014014cc0fc00800454cc0ed2401326b65797320696e206173736f63696174697665206c697374206172656e277420696e20617363656e64696e67206f7264657200163040002303e001303e0013303933760981014000375005897adef6c60225333034337200040022980103d8798000153330343371e0040022980103d87a800014c103d87b800037566016606a6ea8c02cc0d4dd50080a511533033491146d7573745f6164645f666565203f2046616c73650014a02a666064a666064006294454cc0cd2411d6d7573745f686f6c645f61646d696e5f746f6b656e203f2046616c73650014a02a666064a666064004294454cc0cd2411e6d7573745f696e6372656d656e745f636f756e746572203f2046616c73650014a02a666064002294454cc0cd2401256d7573745f70726573657276655f73686970796172645f706f6c696379203f2046616c73650014a029405280a503371e6eb8c028c0d0dd500200a19b87375a602460666ea800ccdc000a2400466e21200033300a3756601060646ea8014dd7180898191baa029375c601060646ea80a4cc0800040ad4cccccc0d4004400454cc0b80a85854cc0b80a85854cc0b80a85854cc0b80a858c0c8c0bcdd50008a998168140b180298171baa001153302c0261630300013300100f23375e6018605a6ea8004c030c0b4dd5180198169baa008132533302a3018007132533302f001153302c0261613253330303033002132533302d301a302f375400226464646464a666064604a60686ea80044c8c8c94ccc0d54ccc0d40145288a9981b24811d6d7573745f696e7075745f736869705f746f6b656e203f2046616c73650014a02a66606aa66606a004294454cc0d92411f6d7573745f726573706563745f6d61785f6d696e696e67203f2046616c73650014a02a66606a002294454cc0d924011b6d7573745f70726573657276655f646174756d203f2046616c73650014a0294052819baf0280063232323371266e08dd6981e0009bad303c303d002337046eb4c0f0008dd6981e181e800981c1baa323230183303c375066e08dd6981e8011bad303d0013303c375066e08dd6981e981f0011bad303d303e0014bd70181c9baa32323232301b3303f375066e04cdc11bad3040004001337046eb4c10000800ccc0fcdd419b820030014bd701bad303f3040001303b3754607c60766ea801cdd6981e981f000981c9baa300348008c0e0dd5180118019bab300e30383754601c60706ea804cc0dcdd5180098011bab300d303737540124602a660726ea0004cc0e530010101004bd701199807000a450048810015330334913f65787065637420536f6d652870657263656e7461676529203d20726174696f6e616c2e6e6577286d61785f617374657269615f6d696e696e672c20313030290016533303130244832004530103d87a80001533303133710906400a4000260246606c60246606c6ea0cdc0a400004e6606c6ea0cdc024000906380a5eb812f5c0260246606c60246606c6ea009ccc0d9301021864004bd7025eb80c01ccc04005c8c8cc004004c8cc004004c94ccc0d0c088c0d8dd50008a5eb7bdb1804dd5981d181b9baa0013300f37566018606c6ea8c030c0d8dd500180b11299981c0008a5eb804cc0e4c0d8c0e8004cc008008c0ec004894ccc0dc004528099299981a19b8f33371890001b8d489045348495000375c607400491104534849500014a2266006006002607400266042002058a66666606c00220022a6605e0562c2a6605e0562c2a6605e0562c2a6605e0562c606660606ea800454cc0b80a458c018c0bcdd50008a998168138b181880099801008119baf300d302e3754002601a605c6ea8c010c0b8dd50048a99981518009980500892999815999815a999815980f18169baa300d302e3754601a605c6ea8c010c0b8dd50008a5014a294128899b8848000ccc018dd5980218171baa3004302e37540026eb8c034c0b8dd50129bae3004302e375404a29405288a99815a481296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a04a666054603a60586ea80045288a5022323300100100322533303000114bd70099192999817180280109981980119802002000899802002000981a00118190009181718178009181698171817000911192999814980b98159baa0011480004dd6981798161baa0013253330293017302b3754002298103d87a80001323300100137566060605a6ea8008894ccc0bc004530103d87a80001323232533302e3371e00e6eb8c0c000c4c03ccc0ccdd4000a5eb804cc014014008dd6981800118198011818800998020018011119198008008019129998160008a60103d87a80001323232533302b3371e00c6eb8c0b400c4c030cc0c0dd3000a5eb804cc014014008dd598168011818001181700098129baa0123028302537540022a6604692013c65787065637420536f6d6528617374657269615f696e70757429203d2066696e645f696e70757428696e707574732c20617374657269615f726566290016323300200923375e600a604c6ea8004008c09cc090dd50051119198008008019129998140008a60103d87a80001323253330263005002130073302b0024bd70099802002000981600118150009ba5480008c09400454cc07d24123657870656374205370656e6428617374657269615f72656629203d20707572706f73650016375c604660480046eb4c088004c078dd50079bac3020302130210023758603e00260366ea8c078008c074c078004c064dd50008a4c2a6602e9211856616c696461746f722072657475726e65642066616c73650013656325333015300800115333019301837540082930a9980b0098b0a99980a98018008a99980c980c1baa004149854cc05804c5854ccc054c00800454ccc064c060dd50020a4c2a6602c0262c2a6602c0262c602c6ea800cdc3a40086e1d200253333330190011001153301200f16153301200f16153301200f16153301200f163300100300e225333010300330123754004264a66602a0022a660240042c26464a66602e0022a660280082c264a66603060360042930a9980a8028b19299999980e0008a9980a8028b0a9980a8028b0a9980a8028b0a9980a8028b09bae0013019001301900232533333301a0011533013003161533013003161533013003161375a0022a660260062c602e00260266ea800854cc04400458dc3a4000a66666602800220022a6601a0162c2a6601a0162c2a6601a0162c2a6601a0162c6eb4004dd6800a499c657870656374205b617374657269615f6f75747075745d203d0a202020202020202020206c6973742e66696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d20617374657269615f696e7075742e6f75747075742e61646472657373207d2c0a20202020202020202020290049013f65787065637420496e6c696e65446174756d28617374657269615f6f75747075745f646174756d29203d20617374657269615f6f75747075742e646174756d0049014065787065637420617374657269615f6f75747075745f646174756d3a2041737465726961446174756d203d20617374657269615f6f75747075745f646174756d0049011972656465656d65723a204173746572696152656465656d657200490113646174756d3a2041737465726961446174756d005734ae7155ceaab9e5573eae815d0aba257489812fd8799f581c516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d284c6173746572696141646d696eff004c01051a002dc6c0004c010218320001"; -const SHIP_SCRIPT_HEX: &str = "592e3101000033333333323232323232323232323232323232323232323232323223223222232232232232223253333330280021532323232323232323330283001302a37540142a660529211c52756e6e696e672032206172672076616c696461746f72206d696e740013232533302a3232323232323232325333033300c303537540102646464a66606c601e60706ea80384c8c8c94ccc0e4c048c0ecdd500089919191919299981f180c98201baa0011323232325333046001153304303e161325333047304a0021325333044301f30463754002264646464a666090604860946ea80044c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c94ccc16d4ccc16c0805288a9982e24811d6d7573745f62655f76616c69645f61737465726961203f2046616c73650014a02a6660b6a6660b6010294454cc171241206d7573745f6d696e745f65787065637465645f76616c7565203f2046616c73650014a02a6660b6a6660b600e294454cc171241216d7573745f726573706563745f6d696e5f64697374616e6365203f2046616c73650014a02a6660b6a6660b600c294454cc1712411b6d7573745f686176655f736869705f6e616d65203f2046616c73650014a02a6660b6a6660b600a294454cc1712411c6d7573745f686176655f70696c6f745f6e616d65203f2046616c73650014a02a6660b6a6660b6008294454cc1712411d6d7573745f686176655f6c61746573745f74696d65203f2046616c73650014a02a6660b6a6660b6006294454cc1712411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660b6a6660b6004294454cc1712411e6d7573745f686f6c645f696e697469616c5f6675656c203f2046616c73650014a02a6660b6002294454cc17124011a6d7573745f686f6c645f335f617373657473203f2046616c73650014a029405280a5014a029405280a5014a06068664600200244a6660c0002290000981d99801001183180099198008009bab3025305e375403244a6660c0002297ae01323332223233001001003225333066001100313233068374e660d06ea4018cc1a0dd49bae30650013306837506eb4c1980052f5c06600600660d400460d00026eb8c17c004dd59830000998018019832001183100099b8733301f3756604660b86ea805c1252201044655454c0003f303433301e3756604460b66ea805809401ccdc39bad305d305e305e305e305e305a37540246eb4c174c168dd500819b8f375c60b860ba60ba60ba60b26ea8044010cdc79bae30193058375402000866e240e0c8cdc018009bad301e3058375402060026eb4c07cc160dd50081299982a99b88001480004c0cc0044004cdd79ba601f374c64646466660026666002a6660ac606490000a5eb7bdb1804c8c8cc0040052f5bded8c044a6660ba0022660bc66ec0dd48131ba60034bd6f7b630099191919299982e98049980501500109983119bb037520546e9801c01454ccc174cdc781500109983119bb037520546e9801c00c4cc188cdd81ba9002374c0026600c00c0066eacc17c00cdd7182e8011830801182f8009919800800a5eb7bdb180894ccc1700044cc174cdd81ba90074c010101004bd6f7b630099191919299982e18041980480580109983099bb037520169810101000051533305c3371e0160042660c266ec0dd4805a61010100003133061337606ea4008dd4000998030030019bad305e003375c60b800460c000460bc0020460089001023245044655454c0003c22225333059303200110041323233001001006225333060001133061337606ea4018dd3001a5eb7bdb1804c8c8c8c94ccc180c030cc0340280084cc194cdd81ba900a374c00e00a2a6660c066e3c0280084c94ccc184c0e8c18cdd500089983319bb0375201660ce60c86ea80040104010c94ccc1854ccc1940045288a5014c0103d87a80001303e33066374c00297ae03233001001002225333066001133067337606ea402cdd400525eb7bdb1804c8c8c8c94ccc198c048cc04c03c0084cc1accdd81ba900f375001c00a2a6660cc66e3c03c0084c94ccc19cc100c1a4dd500089983619bb0375202060da60d46ea80040104010c94ccc19cc1000045300103d87a8000130443306c375000297ae03370000201c2660d666ec0dd48011ba800133006006003375a60d00066eb8c198008c1a8008c1a00044cc194cdd81ba9002374c0026600c00c0066eacc18800cdd7183000118320011831000991900119198008008011129998300008a4c264a6660c200229309919299982f981c18309baa3300c375c60c260ca0086eb8c1840084cc014014cc19000800454cc1812401326b65797320696e206173736f63696174697665206c697374206172656e277420696e20617363656e64696e67206f7264657200163065002306300130630013305e337606ea4008dd4000a5eb7bdb180dd7a60103d879800022533305533720004002298103d8798000153330553371e0040022980103d87a800014c103d87b8000330024890550494c4f540030033004375a603660aa6ea804ccc005220104534849500030023003375a603460a86ea804888cdc500100091b9800123732660046ea00052201003001001222533333305700213232323232323300b0020013371491010128000025333053337100069007099b80483c80400c54ccc14ccdc4001a410004266e00cdc0241002800690068a9982a24929576861742061726520796f7520646f696e673f204e6f2049206d65616e2c20736572696f75736c792e001653330560011337149101035b5d2900004133714911035b5f2000375c60aa66600e00266ec1300102415d00375266e292210129000042233760980103422c2000375266601001000466e28dd7182b0009bae3057001375860a80046eb4c148004c8cdd81ba83052001374e60a60026ea80084c94ccc1500044cdc5245027b7d00002133714911037b5f2000375c60a664646600200200644a6660ae00220062664466ec130103422c2000375266601201260ae00466e29221023a20003330090093058002337146eb8c15c004dd7182c000982c80099801001182d00099bb04c10342207d0037520046eac0084c94ccc1500044cdc52441025b5d00002133714911035b5f2000375c60a666600a00266ec1300102415d0037520044466ec1300103422c2000375266600c00c00466e28dd7182a0009bae3055001375800426600a6eb40080044c8c8cdc524410268270000132333001001337006e3400920013371491101270000322253330533371000490000800899191919980300319b8000548004cdc599b80002533305633710004900a0a40c02903719b8b33700002a6660ac66e2000520141481805206e0043370c004901019b8300148080cdc70020011bae00222232330010010042253330540011004133003305600133002002305700122323300100100322533304e30270011337149110130000031533304e337100029000099b8a489012d0033002002302c00113300533708002900a19b8b3370066e1400520144818000cc0040048894ccc12ccdc4801240002002266600600666e1000920143371666e00cdc28012402890300008a9982481f0b180818251baa3011304a375402aa66608c603e60906ea80044c94ccc12c00454cc120110584c8c94ccc13400454cc128118584c8c94ccc13c00454cc130120584c8c94ccc14400454cc138128584c8c94ccc14c00454cc140130584c94ccc150c15c008526153305104d16325333333058001153305104d16153305104d16153305104d161375a0022a660a209a2c60aa00260aa00464a6666660ac0022a6609e0962c2a6609e0962c2a6609e0962c2a6609e0962c26eb8004c14c004c14c008c94cccccc15000454cc1341245854cc1341245854cc1341245854cc134124584dd7000982880098288011929999998290008a998258238b0a998258238b0a998258238b09bad001153304b04716304f001304f0023253333330500011533049045161533049045161533049045161375a0022a6609208a2c609a00260926ea800454cc11c10c594cccccc134004400454cc1181085854cc1181085854cc1181085854cc11810858c128c11cdd50008a99822a493165787065637420496e6c696e65446174756d28736869705f646174756d29203d20736869705f73746174652e646174756d00163007304637540022a6608807e2c6090002646600200202644a66608e002297ae0132325333045325333046302230483754002266e3c04cdd7182618249baa00114a0601c60906ea8c038c120dd50010998250011980200200089980200200098258011824800a999820180c98211baa0011325333045001153304203c16132325333047001153304403e161325333048304b002149854cc1140fc58c94cccccc13000454cc1140fc5854cc1140fc5854cc1140fc5854cc1140fc584dd7000982480098248011929999998250008a9982181e8b0a9982181e8b0a9982181e8b09bad001153304303d163047001304337540022a660820762ca66666608e00220022a660800742c2a660800742c2a660800742c2a660800742c608860826ea800454cc0fd2413e65787065637420496e6c696e65446174756d28617374657269615f646174756d29203d20617374657269615f696e7075742e6f75747075742e646174756d0016300130403754600e60806ea80108c10cc110c110004c06cccc004dd59802981f1baa3005303e37540046eb8c010c0f8dd50141bae3005303e375405044464a66607c603460806ea8004520001375a608860826ea8004c94ccc0f8c068c100dd50008a60103d87a8000132330010013756608a60846ea8008894ccc110004530103d87a8000132323253330433371e00e6eb8c11400c4c080cc120dd4000a5eb804cc014014008dd698228011824001182300099804001801181f981e1baa001153303a03116323300100100c22533303e00114c103d87a800013232533303c32533303d3016303f375400229404cdc79bae304330403754002056600a607e6ea8c014c0fcdd51803181f9baa00213019330410024bd70099802002000982100118200009181f0009181e981f000899299981d8008a9981c01a8b099299981e181f8010a99981c19b8748004dd6981d8008a51153303903616153303903616303d001325333037301330393754002297adef6c6013756607a60746ea8004cc00400800c88c8cc00400400c894ccc0f40045300103d87a80001323232533303c3371e00c6eb8c0f800c4c064cc104dd3000a5eb804cc014014008dd5981f0011820801181f800991980080080211299981d0008a5eb7bdb1804c8c8c8c94ccc0e8cdc7a44100002100313303f337606ea4008dd3000998030030019bab303c003375c6074004607c00460780026eb8c0e4c0d8dd50040a9981a24926657870656374204d696e742873686970796172645f706f6c69637929203d20707572706f7365001630383039303930390023756606e002606e606e0046eb0c0d4004c0d4c0d4008dd6181980098179baa303200230313032001302d37540182930a99815a4811856616c696461746f722072657475726e65642066616c7365001365632533302a30030011533302e302d37540042930a998158148b0a99981518030008a99981718169baa002149854cc0ac0a45854cc0ac0a458c0acdd5000a99999981800588058a998148138b0a998148138b0a998148138b0a998148138b0a99814a491d52756e6e696e672033206172672076616c696461746f72207370656e640013323232232322533302f323232323232323232323232323232323232323232325333045301e30473754002264a66608c604460906ea80584c8c94ccc120c084c128dd5000899192999825181318261baa001132323232323232323232323232325323233305a303300d1323232325333062001153305f05016132533306330660021325333060303b30623754002264646464a6660c8608060cc6ea80044c8c94ccc198c108c1a0dd50008991919192999835182198361baa001132323232323232323232323253330765333076305230263301f044230293035307a3754606c60f46ea80045288a9983ba481236d7573745f7370656e645f6f6e655f7363726970745f696e707574203f2046616c73650014a02a6660eca6660ec054294454cc1dd241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660eca6660ec008294454cc1dd2411d6d7573745f686176655f656e6f7567685f6675656c203f2046616c73650014a02a6660eca6660ec00c294454cc1dd2411e6d7573745f726573706563745f6d61785f7370656564203f2046616c73650014a02a6660eca6660ec00a294454cc1dd241206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a02a6660eca6660ec004294454cc1dd241216d7573745f73756274726163745f6675656c5f746f6b656e73203f2046616c73650014a02a6660eca6660ec010294454cc1dd2411c6d7573745f6275726e5f7370656e745f6675656c203f2046616c73650014a02a6660eca6660ec014294454cc1dd241156d7573745f7570646174655f78203f2046616c73650014a02a6660eca6660ec012294454cc1dd241156d7573745f7570646174655f79203f2046616c73650014a02a6660eca6660ec00e294454cc1dd2411f6d7573745f7570646174655f75707065725f626f756e64203f2046616c73650014a02a6660eca6660ec016294454cc1dd241216d7573745f70726573657276655f70696c6f745f746f6b656e203f2046616c73650014a02a6660eca6660ec006294454cc1dd2411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660ec002294454cc1dd24011a6d7573745f686f6c645f335f617373657473203f2046616c73650014a029405280a5014a029405280a5014a029405280a5014a0609e604460486eacc0d0c1e0dd500b99b8733301f3756606660ee6ea80581912201044655454c0033702014018609e66603c6eacc0c8c1d8dd500a81481b19b8900a008301900d32323371266e08dd6983c0011bad30783079001337046eb4c1e0004dd6983c183c801183a1baa02c3073375460ec60e66ea801ccdc39bad307530763076307630763072375401c012602a609800c66e1cdd6981618381baa00c3370006402266e1cdd6981518379baa00b3370006602266e3c0b0dd7183898391839183918371baa00a3330153756605260da6ea8c0a4c1b4dd501102d2441044655454c00153306b4915865787065637420536f6d6528737065656429203d0a20202020202020202020726174696f6e616c2e6e65772864697374616e63652c2074785f6c61746573745f74696d65202d2074785f6561726c696573745f74696d65290016330260023370200600a66e08004140c8cdc0180080698008061299983419b88001480004c1180044004dd6983618349baa001153306705c16302330683754604860d06ea80b8dd6983518339baa001153306505916302130663754604260cc6ea80b0cc0e40041594cccccc1a4004400454cc1881545854cc1881545854cc1881545854cc18815458c198c18cdd50008a998308298b180498311baa00115330600511630640013300602923375e603860c26ea8004c070c184dd5180e98309baa016375a60c460c60046eb4c184004c174dd50170a99982d181b0068991929998300008a9982e8270b09929998309832001099299982f181c98301baa0011323232325333062303b306437540022646464a6660ca608060ce6ea80044c8c8c8c94ccc1a4c114c1acdd5000899191919191919191929998392999839182698111980d820118129818983b1baa303230763754002294454cc1cd2401246d7573745f7370656e645f74776f5f7363726970745f696e70757473203f2046616c73650014a02a6660e4a6660e401e294454cc1cd2411c6d7573745f62655f76616c69645f70656c6c6574203f2046616c73650014a02a6660e4a6660e404c294454cc1cd241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660e4a6660e4010294454cc1cd241216d7573745f686176655f70656c6c65745f706f736974696f6e203f2046616c73650014a02a6660e4a6660e4006294454cc1cd2411c6d7573745f6164645f6675656c5f746f6b656e73203f2046616c73650014a02a6660e4a6660e400e294454cc1cd241206d7573745f6e6f745f6578636565645f6361706163697479203f2046616c73650014a02a6660e4a6660e400a294454cc1cd241206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a02a6660e4a6660e400c294454cc1cd2411b6d7573745f70726573657276655f646174756d203f2046616c73650014a02a6660e4a6660e4008294454cc1cd2411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660e4a6660e4004294454cc1cd2411a6d7573745f686f6c645f335f617373657473203f2046616c73650014a02a6660e4002294454cc1cd24011c6d7573745f6e6f745f6d696e745f746f6b656e73203f2046616c73650014a029405280a5014a029405280a5014a0294052819baf374c603a07698101a000304a301d301f3756605e60e66ea8050cdc399980d1bab302e307237540260be911044655454c003370000c02a60946660326eacc0b4c1c4dd5009012018980a9bad30733070375400a66ebc034110cdc499b80002011055533306a3370e0626eb4c0a0c1b4dd5002099b8702f375a605260da6ea801052819980a1bab3028306c3754605060d86ea8084165221044655454c00153306a05e163026306b3754604c60d66ea80c54ccc19cc100c1a4dd500089929998360008a9983482f8b0991929998370008a998358308b0991929998380008a998368318b0992999838983a0010a4c2a660dc0c82c64a6666660ea0022a660dc0c82c2a660dc0c82c2a660dc0c82c2a660dc0c82c26eb8004c1c8004c1c8008c94cccccc1cc00454cc1b01885854cc1b01885854cc1b0188584dd68008a998360310b183800098380011929999998388008a998350300b0a998350300b0a998350300b09bad001153306a06016306e001306a37540022a660d00bc2ca6666660dc00220022a660ce0ba2c2a660ce0ba2c2a660ce0ba2c2a660ce0ba2c60d660d06ea800454cc1992413c65787065637420496e6c696e65446174756d2870656c6c65745f646174756d29203d2070656c6c65745f696e7075742e6f75747075742e646174756d0016300e30673754604660ce6ea8008c10cccc038dd5981118331baa3022306637540026eb8c084c198dd50281bae3022306637540a060d060ca6ea800454cc18d2401ff65787065637420536f6d652870656c6c65745f696e70757429203d0a202020202020202020206c6973742e66696e64280a202020202020202020202020696e707574732c0a202020202020202020202020666e28696e70757429207b0a20202020202020202020202020207768656e20696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c206973207b0a20202020202020202020202020202020566572696669636174696f6e4b657943726564656e7469616c285f29202d3e2046616c73650a2020202020202020202020202020202053637269707443726564656e7469616c28616464725f7061796d656e6b7429202d3e0a202020202020202020202020202020202020616464725f7061796d656e74203d3d2070656c6c65745f76616c696461746f725f616464726573730a20202020202020202020202020207d0a2020202020202020202020207d2c0a202020202020202020202900163301b02f2325333063303c3065375400229404cdc79bae3069306637540020a6604060ca6ea8c080c194dd5181098329baa00133037001054533333306700110011533060053161533060053161533060053161533060053163064306137540022a660be0a22c600e60c06ea800454cc17813c58c188004cc01009c8cdd7980d182f9baa001301a305f3754603660be6ea8050dd69830182e9baa02e1533305a303500d132533305b3034305d375400226464a6660ba607260be6ea80044c8c8c8c94ccc1854ccc184c0f0c044cc0280bc8c050c080c194dd5181098329baa00114a22a660c49201246d7573745f7370656e645f74776f5f7363726970745f696e70757473203f2046616c73650014a02a6660c2a6660c200c294454cc1892411d6d7573745f62655f76616c69645f61737465726961203f2046616c73650014a02a6660c2a6660c202a294454cc189241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660c2a6660c2008294454cc189241226d7573745f686176655f617374657269615f706f736974696f6e203f2046616c73650014a02a6660c2a6660c2006294454cc1892411c6d7573745f6275726e5f736869705f746f6b656e203f2046616c73650014a02a6660c2a6660c2002294454cc1892411d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a02a6660c2004294454cc1892401206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a029405280a5014a029405281803981f1998059bab301f30633754603e60c66ea80601412201044655454c003007375a60ca60c46ea800ccdc4199804980501400a010a400066ebcdd31983119bb037500486ea00892f5bded8c06e98cc1892f7b6301010000010100004bd6f7b6300a9982f0290b180d182f9baa301a305f375404a607666600c6eacc068c178dd5180d182f1baa3061305e37540026eb8c064c178dd50241bae301a305e37540902a660b80a62c66028050464a6660b8606a60bc6ea8004528099b8f375c60c460be6ea8004128c064c178dd5180c982f1baa301a305e375400226464a6660b8a6660b8607060186600a0544601e603660c06ea8c070c180dd50008a51153305d491236d7573745f7370656e645f6f6e655f7363726970745f696e707574203f2046616c73650014a02a6660b8a6660b8020294454cc175241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660b8a6660b8004294454cc1752411c6d7573745f6275726e5f736869705f746f6b656e203f2046616c73650014a02a6660b8002294454cc17524011d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a029405280a50300230393330063756603460bc6ea8c068c178dd5009825a441044655454c003371066600a600c04802003a90001b8733300430050230494881044655454c00371203044646600200200644a6660be002297ae013232533305d300500213306200233004004001133004004001306300230610012305d305e305e0012223253330593035305b37540022900009bad305f305c375400264a6660b2606a60b66ea80045300103d87a800013233001001375660c060ba6ea8008894ccc17c004530103d87a80001323232533305e3371e00e6eb8c18000c4c0eccc18cdd4000a5eb804cc014014008dd6983000118318011830800998068018011191980080080111299982d8008a5eb7bdb1804c8c8c8c94ccc16ccdc7a441000021003133060337606ea4008dd3000998030030019bab305d003375c60b600460be00460ba002600200244a6660b0002290000981999801001182d8009191980080080111299982c0008a5eb804c8ccc888c8cc00400400c894ccc178004400c4c8cc180dd3998301ba90063306037526eb8c174004cc180dd41bad305e0014bd7019801801983100118300009bae3057001375660b00026600600660b800460b4002600200244a6660aa002290000981819801001182c00092999827981418289baa300d30523754002294052898279baa021533304c3025304e37546600c03446466002002646600200264a6660a0605860a46ea800452f5bded8c026eacc158c14cdd5000998021bab300e30523754601c60a46ea800c014894ccc15000452f5c02660aa60a460ac0026600400460ae00244a6660a600229404c94ccc140cdc79bae305600201114a226600600600260ac00229445281119198008008019129998298008a60103d87a8000132323253330523371e00c6eb8c15000c4c0bccc15cdd3000a5eb804cc014014008dd5982a001182b801182a8009bae3050304d37540022a660969215d6578706563742053637269707443726564656e7469616c2873686970796172645f706f6c69637929203d0a202020202020736869705f696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c00163007304c3754600e60986ea8c020c130dd5000982718259baa001153304949013665787065637420536f6d6528736869705f696e70757429203d2066696e645f696e70757428696e707574732c20736869705f726566290016323300201623375e600e60986ea8004008c134c128dd500b9119198008008019129998270008a60103d87a800013232533304c300500213029330510024bd70099802002000982900118280008a99823a48120657870656374205370656e6428736869705f72656629203d20707572706f73650016304b304837540022a6608c92015865787065637420536f6d65286d61785f73706565645f726174696f6e616c29203d0a202020202020726174696f6e616c2e6e6577286d61785f73706565642e64697374616e63652c206d61785f73706565642e74696d6529001633001375a6004608e6ea80c0dd6980198239baa030225333045301e00114c103d87a80001533304533710002900009811198251811198251ba830230023304a3750604600297ae04bd7009811198251811198251ba80023304a375000297ae04bd70118248009182418248009bad30463047002375c608a002608a0046eb8c10c004c10c008dd6982080098208011bad303f001303b3754020607a607c607c607c0046eacc0f0004c0f0c0f0008dd6181d000981d181d0011bac303800130343754606e004606c606e00260646ea8004526153303049011856616c696461746f722072657475726e65642066616c7365001365632533302e30070011325333033001153303002816132325333035001153303202a1613253330363039002149854cc0cc0ac58c94cccccc0e800454cc0cc0ac5854cc0cc0ac5854cc0cc0ac584dd68008a998198158b181b800981b80119299999981c0008a998188148b0a998188148b0a998188148b09bad0011533031029163035001303137540042a66605c6014002264a6660660022a660600502c264a666068606e0042930a998188148b19299999981c0008a998188148b0a998188148b0a998188148b09bad0011533031029163035001303137540042a66605c60120022a66606460626ea8008526153302f027161533302e300800115333032303137540042930a998178138b0a998178138b18179baa00153333330340011001153302d02516153302d02516153302d02516153302d025163300100202422533302b3004302d3754004264a6660600022a6605a0042c26464a6660640022a6605e0082c26464a6660680022a6606200c2c26464a66606c0022a660660102c26464a6660700022a6606a0142c264a66607260780042930a9981b0058b19299999981e8008a9981b0058b0a9981b0058b0a9981b0058b09bad001153303600b16303a001303a00232533333303b0011533034009161533034009161533034009161533034009161375c0026070002607000464a6666660720022a6606400e2c2a6606400e2c2a6606400e2c2a6606400e2c26eb8004c0d8004c0d8008c94cccccc0dc00454cc0c00145854cc0c00145854cc0c0014584dd68008a998180028b181a000981a00119299999981a8008a998170018b0a998170018b0a998170018b09bad001153302e003163032001302e37540042a660580022ca66666606001620162a660520442c2a660520442c2a660520442c2a660520442c605c60566ea8028dc3a40006e1d2006370e90021b8748008dd2a40006e052000370090011b884800054cc0840045854cc0840045854cc0840045854cc08400459240191496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e00375a0026eb4004dd68009bad001375c0026eb800524196657870656374205b736869705f6f75747075745d203d0a202020202020202020206c6973742e66696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d20736869705f696e7075742e6f75747075742e61646472657373207d2c0a20202020202020202020290049013965787065637420496e6c696e65446174756d28736869705f6f75747075745f646174756d29203d20736869705f6f75747075742e646174756d0049013765787065637420736869705f6f75747075745f646174756d3a2053686970446174756d203d20736869705f6f75747075745f646174756d004901476578706563742046696e6974652874785f6561726c696573745f74696d6529203d2076616c69646974795f72616e67652e6c6f7765725f626f756e642e626f756e645f74797065004901456578706563742046696e6974652874785f6c61746573745f74696d6529203d2076616c69646974795f72616e67652e75707065725f626f756e642e626f756e645f747970650049012f6578706563742070656c6c65745f646174756d3a2050656c6c6574446174756d203d2070656c6c65745f646174756d004901ff65787065637420536f6d6528617374657269615f696e70757429203d0a202020202020202020206c6973742e66696e64280a202020202020202020202020696e707574732c0a202020202020202020202020666e28696e70757429207b0a20202020202020202020202020207768656e20696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c206973207b0a20202020202020202020202020202020566572696669636174696f6e4b657943726564656e7469616c285f29202d3e2046616c73650a2020202020202020202020202020202053637269707443726564656e7469616c28616464725f7061796d656d6e7429202d3e0a202020202020202020202020202020202020616464725f7061796d656e74203d3d20617374657269615f76616c696461746f725f616464726573730a20202020202020202020202020207d0a2020202020202020202020207d2c0a20202020202020202020290049011672656465656d65723a205368697052656465656d657200490110646174756d3a2053686970446174756d0049013265787065637420617374657269615f646174756d3a2041737465726961446174756d203d20617374657269615f646174756d00490159657870656374205b736869705f73746174655d203d0a202020202020202020207472616e73616374696f6e2e66696e645f7363726970745f6f757470757473286f7574707574732c2073686970796172645f706f6c696379290049012965787065637420736869705f646174756d3a2053686970446174756d203d20736869705f646174756d00490120657870656374205b285f2c202d31295d203d206d696e7465645f746f6b656e730049011a72656465656d65723a20536869707961726452656465656d6572005734ae7155ceaab9e5573eae815d0aba257489811e581c6a25ad5476105ac4a3784769cb93f92fd67a11932ef9a65a61abd1d6004c011e581cbac1753d5f7e3609c92776371fd0eafa753889e5712858f48fb83981004c012fd8799f581c516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d284c6173746572696141646d696eff004c0108d8799f01197530ff004c01021864004c010101004c0102181e004c01010a0001"; -const PELLET_SCRIPT_HEX: &str = "590d5a01000033232323232323232323232323232222325333333012002153232323233300e30013010375400c2a6601e9211c52756e6e696e672032206172672076616c696461746f72206d696e7400132325333010323232323253330153008301737540082646464a666030601660346ea80284c94ccc0654ccc0654ccc064c030c06cdd5191980080080391299980f8008a60103d87a800013232533301d3013323330073756600260426ea8c004c084dd50019bae3024302137540306eb8c004c084dd500c118121812800898091981100125eb804cc010010004c08c008c0840045288a5014a22a660349201296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a02a666032002294454cc06924011d6d7573745f6d696e745f6675656c5f746f6b656e73203f2046616c73650014a02940c038ccc00400800d2201044655454c001533301833710666002004006911044655454c00480005288a9980ca491d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a044464a666036601e603a6ea8004520001375a6042603c6ea8004c94ccc06cc03cc074dd50008a60103d87a80001323300100137566044603e6ea8008894ccc084004530103d87a8000132323253330203371e00e6eb8c08800c4c054cc094dd4000a5eb804cc014014008dd698110011812801181180099198008008021129998100008a6103d87a80001323232533301f3371e00e6eb8c08400c4c050cc090dd3000a5eb804cc014014008dd5981080118120011811000991980080080191299980e0008a5eb7bdb1804c8c8c8c94ccc070cdc7a441000021003133021337606ea4008dd3000998030030019bab301e003375c60380046040004603c0026eb8c06cc060dd50020a9980b24922657870656374204d696e74286675656c5f706f6c69637929203d20707572706f736500163756603460366036603660360046eb0c064004c054dd5180c001180b980c00098099baa008149854cc0452411856616c696461746f722072657475726e65642066616c73650013656325333010300300115333014301337540042930a998088078b0a99980818020008a99980a18099baa002149854cc04403c5854cc04403c58c044dd5000a99999980b00388038a998078068b0a998078068b0a998078068b0a998078068b0a99807a491d52756e6e696e672033206172672076616c696461746f72207370656e64001332323223232253330153232323232533301a300e301c37540082646464a66603a6020603e6ea80044c8c8c94ccc080c050c088dd5000899191919192999812980c18139baa0131323232533302c001153302902316132533302d3030002132533302a3370e900218161baa00113232323232323253330315333031300d33016019232330010013233001001325333035302930373754002297adef6c6013756607660706ea8004cc04cdd5980b181b9baa30163037375400601c44a666072002297ae013303a3037303b00133002002303c00122533303800114a0264a66606a66e3cccdc6240006e35221045348495000375c607600491104534849500014a22660060060026076002294454cc0c924011d6d7573745f696e7075745f736869705f746f6b656e203f2046616c73650014a02a666062a666062006294454cc0c92411d6d7573745f686f6c645f61646d696e5f746f6b656e203f2046616c73650014a02a666062a666062008294454cc0c92411d6d7573745f686176655f656e6f7567685f6675656c203f2046616c73650014a02a666062a666062004294454cc0c9241206d7573745f70726f766964655f6675656c5f616d6f756e74203f2046616c73650014a02a666062002294454cc0c924011b6d7573745f70726573657276655f646174756d203f2046616c73650014a029405280a5014a066ebc014088cdc39998069bab30113032375400e01e9101044655454c003370201801460446660186eacc040c0c4dd50031bae3014303137540506eb8c040c0c4dd501419b8900800a3301d00102853333330330011001153302c02716153302c02716153302c02716153302c027163030302d37540022a660569213365787065637420496e6c696e65446174756d286f75745f646174756d29203d2070656c6c65745f6f75747075742e646174756d0016302f30303030302c37540022a660540482c605c002646600200201e44a66605a002297ae013232533302b3375e6022605c6ea8008c044c0b8dd5180698171baa00e133030002330040040011330040040013031002302f001375c6058605a605a60526ea8060dd6981598141baa0131533302530013300a00d253330263330265333026301930283754601860526ea8c030c0a4dd5180418149baa00114a02945282511301c3330043756601060526ea8c020c0a4dd50009bae300c302937540406eb8c020c0a4dd50100a5014a22a6604c921296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a04a66604a6030604e6ea80045288a503330013756600a604c6ea8c014c098dd5003001a45044655454c00222325333026301a302837540022900009bad302c3029375400264a66604c603460506ea8004530103d87a8000132330010013756605a60546ea8008894ccc0b0004530103d87a80001323232533302b3371e00e6eb8c0b400c4c080cc0c0dd4000a5eb804cc014014008dd6981680118180011817000998020018011119198008008019129998148008a60103d87a8000132323253330283371e00c6eb8c0a800c4c074cc0b4dd3000a5eb804cc014014008dd59815001181680118158009bae3026302337540022a660429215b6578706563742053637269707443726564656e7469616c286675656c5f706f6c69637929203d0a20202020202070656c6c65745f696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c0016300530223754600a60446ea8c004c088dd5001118129813000981198101baa001153301e49013a65787065637420536f6d652870656c6c65745f696e70757429203d2066696e645f696e70757428696e707574732c2070656c6c65745f726566290016323300200523375e600860426ea8004008c088c07cdd50031119198008008019129998118008a60103d87a8000132325333021300500213016330260024bd7009980200200098138011812800918108008a9980da48122657870656374205370656e642870656c6c65745f72656629203d20707572706f736500163758603e604060400046eb0c078004c068dd5180e801180e180e800980c1baa001149854cc0592411856616c696461746f722072657475726e65642066616c7365001365632533301430070011325333019001153301601216132533301a301d002149854cc05c04c58c94cccccc07800454cc05c04c5854cc05c04c5854cc05c04c584dd68008a9980b8098b180d800980b9baa00215333014300800115333018301737540042930a9980a8088b0a9980a8088b180a9baa001533333301a0011001153301300f16153301300f16153301300f16153301300f163300100200e225333011300430133754004264a66602c0022a660260042c26464a6660300022a6602a0082c26464a6660340022a6602e00c2c264a666036603c0042930a9980c0038b19299999980f8008a9980c0038b0a9980c0038b0a9980c0038b0a9980c0038b09bae001301c001301c00232533333301d0011533016005161533016005161533016005161375a0022a6602c00a2c6034002603400464a6666660360022a660280062c2a660280062c2a660280062c26eb400454cc05000c58c060004c050dd50010a998090008b299999980b00388038a998078060b0a998078060b0a998078060b0a998078060b180a18089baa006370e90001b8748008dd2a40006e212000153300b00116153300b00116153300b00116153300b0011649191496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e00490195657870656374205b70656c6c65745f6f75747075745d203d0a2020202020202020202066696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d2070656c6c65745f696e7075742e6f75747075742e61646472657373207d2c0a202020202020202020202900490129657870656374206f75745f646174756d3a2050656c6c6574446174756d203d206f75745f646174756d0049011872656465656d65723a2050656c6c657452656465656d657200490112646174756d3a2050656c6c6574446174756d0049011672656465656d65723a204675656c52656465656d6572005734ae7155ceaab9e5573eae815d0aba257489812fd8799f581c516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d284c6173746572696141646d696eff0001"; +const ASTERIA_PARAMETERIZED: &str = "590cf901000032323232323232323232323232322232232232323232232323232253330163232323232323232533301e300c3020375400e264646464a666044602a60486ea80044c8c8c8c8c8c8c94ccc0a4c0700184c94ccc0b800454cc0ac094584c94ccc0bcc0c80084c94ccc0b0c064c0b8dd500089919191919192999819299981919baf300b303537540106e98cc894ccc0d0c09c0b040044c8c8cc00400400c894ccc0ec0044cc0f0cdd82601014000374c00697adef6c60132323232533303b3375e66012911000024c103d879800013304033760981014000374c00e00a2a66607666e3d22100002132533303c302f303e375400226608266ec13010140003042303f3754002008200864a666078a66608000229445280a6103d87a80001301d33041374c00297ae03233001001002225333041001133042337609801014000375006a97adef6c6013232323253330413375e6601e911000024c103d879800013304633760981014000375007200a2a66608266e3d22100002132533304230353044375400226608e66ec1301014000304830453754002008200864a666084606a002298103d87a80001302333047375000297ae03370000207226608c66ec0dd48011ba800133006006003375a60860066eb8c104008c114008c10c0044cc100cdd81ba9002374c0026600c00c0066eacc0f400cdd7181d801181f801181e8009919001191980080080111299981d8008a4c264a66607800229309919299981d1816981e1baa33008375c607860800086eb8c0f00084cc014014cc0fc00800454cc0ed2401326b65797320696e206173736f63696174697665206c697374206172656e277420696e20617363656e64696e67206f7264657200163040002303e001303e0013303933760981014000375005897adef6c60225333034337200040022980103d8798000153330343371e0040022980103d87a800014c103d87b800037566016606a6ea8c02cc0d4dd50080a511533033491146d7573745f6164645f666565203f2046616c73650014a02a666064a666064006294454cc0cd2411d6d7573745f686f6c645f61646d696e5f746f6b656e203f2046616c73650014a02a666064a666064004294454cc0cd2411e6d7573745f696e6372656d656e745f636f756e746572203f2046616c73650014a02a666064002294454cc0cd2401256d7573745f70726573657276655f73686970796172645f706f6c696379203f2046616c73650014a029405280a503371e6eb8c028c0d0dd500200a19b87375a602460666ea800ccdc000a2400466e21200033300a3756601060646ea8014dd7180898191baa029375c601060646ea80a4cc0800040ad4cccccc0d4004400454cc0b80a85854cc0b80a85854cc0b80a85854cc0b80a858c0c8c0bcdd50008a998168140b180298171baa001153302c0261630300013300100f23375e6018605a6ea8004c030c0b4dd5180198169baa008132533302a3018007132533302f001153302c0261613253330303033002132533302d301a302f375400226464646464a666064604a60686ea80044c8c8c94ccc0d54ccc0d40145288a9981b24811d6d7573745f696e7075745f736869705f746f6b656e203f2046616c73650014a02a66606aa66606a004294454cc0d92411f6d7573745f726573706563745f6d61785f6d696e696e67203f2046616c73650014a02a66606a002294454cc0d924011b6d7573745f70726573657276655f646174756d203f2046616c73650014a0294052819baf0280063232323371266e08dd6981e0009bad303c303d002337046eb4c0f0008dd6981e181e800981c1baa323230183303c375066e08dd6981e8011bad303d0013303c375066e08dd6981e981f0011bad303d303e0014bd70181c9baa32323232301b3303f375066e04cdc11bad3040004001337046eb4c10000800ccc0fcdd419b820030014bd701bad303f3040001303b3754607c60766ea801cdd6981e981f000981c9baa300348008c0e0dd5180118019bab300e30383754601c60706ea804cc0dcdd5180098011bab300d303737540124602a660726ea0004cc0e530010101004bd701199807000a450048810015330334913f65787065637420536f6d652870657263656e7461676529203d20726174696f6e616c2e6e6577286d61785f617374657269615f6d696e696e672c20313030290016533303130244832004530103d87a80001533303133710906400a4000260246606c60246606c6ea0cdc0a400004e6606c6ea0cdc024000906380a5eb812f5c0260246606c60246606c6ea009ccc0d9301021864004bd7025eb80c01ccc04005c8c8cc004004c8cc004004c94ccc0d0c088c0d8dd50008a5eb7bdb1804dd5981d181b9baa0013300f37566018606c6ea8c030c0d8dd500180b11299981c0008a5eb804cc0e4c0d8c0e8004cc008008c0ec004894ccc0dc004528099299981a19b8f33371890001b8d489045348495000375c607400491104534849500014a2266006006002607400266042002058a66666606c00220022a6605e0562c2a6605e0562c2a6605e0562c2a6605e0562c606660606ea800454cc0b80a458c018c0bcdd50008a998168138b181880099801008119baf300d302e3754002601a605c6ea8c010c0b8dd50048a99981518009980500892999815999815a999815980f18169baa300d302e3754601a605c6ea8c010c0b8dd50008a5014a294128899b8848000ccc018dd5980218171baa3004302e37540026eb8c034c0b8dd50129bae3004302e375404a29405288a99815a481296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a04a666054603a60586ea80045288a5022323300100100322533303000114bd70099192999817180280109981980119802002000899802002000981a00118190009181718178009181698171817000911192999814980b98159baa0011480004dd6981798161baa0013253330293017302b3754002298103d87a80001323300100137566060605a6ea8008894ccc0bc004530103d87a80001323232533302e3371e00e6eb8c0c000c4c03ccc0ccdd4000a5eb804cc014014008dd6981800118198011818800998020018011119198008008019129998160008a60103d87a80001323232533302b3371e00c6eb8c0b400c4c030cc0c0dd3000a5eb804cc014014008dd598168011818001181700098129baa0123028302537540022a6604692013c65787065637420536f6d6528617374657269615f696e70757429203d2066696e645f696e70757428696e707574732c20617374657269615f726566290016323300200923375e600a604c6ea8004008c09cc090dd50051119198008008019129998140008a60103d87a80001323253330263005002130073302b0024bd70099802002000981600118150009ba5480008c09400454cc07d24123657870656374205370656e6428617374657269615f72656629203d20707572706f73650016375c604660480046eb4c088004c078dd50079bac3020302130210023758603e00260366ea8c078008c074c078004c064dd50008a4c2a6602e9211856616c696461746f722072657475726e65642066616c73650013656325333015300800115333019301837540082930a9980b0098b0a99980a98018008a99980c980c1baa004149854cc05804c5854ccc054c00800454ccc064c060dd50020a4c2a6602c0262c2a6602c0262c602c6ea800cdc3a40086e1d200253333330190011001153301200f16153301200f16153301200f16153301200f163300100300e225333010300330123754004264a66602a0022a660240042c26464a66602e0022a660280082c264a66603060360042930a9980a8028b19299999980e0008a9980a8028b0a9980a8028b0a9980a8028b0a9980a8028b09bae0013019001301900232533333301a0011533013003161533013003161533013003161375a0022a660260062c602e00260266ea800854cc04400458dc3a4000a66666602800220022a6601a0162c2a6601a0162c2a6601a0162c2a6601a0162c6eb4004dd6800a499c657870656374205b617374657269615f6f75747075745d203d0a202020202020202020206c6973742e66696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d20617374657269615f696e7075742e6f75747075742e61646472657373207d2c0a20202020202020202020290049013f65787065637420496e6c696e65446174756d28617374657269615f6f75747075745f646174756d29203d20617374657269615f6f75747075742e646174756d0049014065787065637420617374657269615f6f75747075745f646174756d3a2041737465726961446174756d203d20617374657269615f6f75747075745f646174756d0049011972656465656d65723a204173746572696152656465656d657200490113646174756d3a2041737465726961446174756d005734ae7155ceaab9e5573eae815d0aba257481"; +const SPACETIME_PARAMETERIZED: &str = "592d94010000323232323232323232323232323232323232323232323223223222232232232232223253333330280021532323232323232323330283001302a37540142a660529211c52756e6e696e672032206172672076616c696461746f72206d696e740013232533302a3232323232323232325333033300c303537540102646464a66606c601e60706ea80384c8c8c94ccc0e4c048c0ecdd500089919191919299981f180c98201baa0011323232325333046001153304303e161325333047304a0021325333044301f30463754002264646464a666090604860946ea80044c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c94ccc16d4ccc16c0805288a9982e24811d6d7573745f62655f76616c69645f61737465726961203f2046616c73650014a02a6660b6a6660b6010294454cc171241206d7573745f6d696e745f65787065637465645f76616c7565203f2046616c73650014a02a6660b6a6660b600e294454cc171241216d7573745f726573706563745f6d696e5f64697374616e6365203f2046616c73650014a02a6660b6a6660b600c294454cc1712411b6d7573745f686176655f736869705f6e616d65203f2046616c73650014a02a6660b6a6660b600a294454cc1712411c6d7573745f686176655f70696c6f745f6e616d65203f2046616c73650014a02a6660b6a6660b6008294454cc1712411d6d7573745f686176655f6c61746573745f74696d65203f2046616c73650014a02a6660b6a6660b6006294454cc1712411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660b6a6660b6004294454cc1712411e6d7573745f686f6c645f696e697469616c5f6675656c203f2046616c73650014a02a6660b6002294454cc17124011a6d7573745f686f6c645f335f617373657473203f2046616c73650014a029405280a5014a029405280a5014a06068664600200244a6660c0002290000981d99801001183180099198008009bab3025305e375403244a6660c0002297ae01323332223233001001003225333066001100313233068374e660d06ea4018cc1a0dd49bae30650013306837506eb4c1980052f5c06600600660d400460d00026eb8c17c004dd59830000998018019832001183100099b8733301f3756604660b86ea805c1252201044655454c0003f303433301e3756604460b66ea805809401ccdc39bad305d305e305e305e305e305a37540246eb4c174c168dd500819b8f375c60b860ba60ba60ba60b26ea8044010cdc79bae30193058375402000866e240e0c8cdc018009bad301e3058375402060026eb4c07cc160dd50081299982a99b88001480004c0cc0044004cdd79ba601f374c64646466660026666002a6660ac606490000a5eb7bdb1804c8c8cc0040052f5bded8c044a6660ba0022660bc66ec0dd48131ba60034bd6f7b630099191919299982e98049980501500109983119bb037520546e9801c01454ccc174cdc781500109983119bb037520546e9801c00c4cc188cdd81ba9002374c0026600c00c0066eacc17c00cdd7182e8011830801182f8009919800800a5eb7bdb180894ccc1700044cc174cdd81ba90074c010101004bd6f7b630099191919299982e18041980480580109983099bb037520169810101000051533305c3371e0160042660c266ec0dd4805a61010100003133061337606ea4008dd4000998030030019bad305e003375c60b800460c000460bc0020460089001023245044655454c0003c22225333059303200110041323233001001006225333060001133061337606ea4018dd3001a5eb7bdb1804c8c8c8c94ccc180c030cc0340280084cc194cdd81ba900a374c00e00a2a6660c066e3c0280084c94ccc184c0e8c18cdd500089983319bb0375201660ce60c86ea80040104010c94ccc1854ccc1940045288a5014c0103d87a80001303e33066374c00297ae03233001001002225333066001133067337606ea402cdd400525eb7bdb1804c8c8c8c94ccc198c048cc04c03c0084cc1accdd81ba900f375001c00a2a6660cc66e3c03c0084c94ccc19cc100c1a4dd500089983619bb0375202060da60d46ea80040104010c94ccc19cc1000045300103d87a8000130443306c375000297ae03370000201c2660d666ec0dd48011ba800133006006003375a60d00066eb8c198008c1a8008c1a00044cc194cdd81ba9002374c0026600c00c0066eacc18800cdd7183000118320011831000991900119198008008011129998300008a4c264a6660c200229309919299982f981c18309baa3300c375c60c260ca0086eb8c1840084cc014014cc19000800454cc1812401326b65797320696e206173736f63696174697665206c697374206172656e277420696e20617363656e64696e67206f7264657200163065002306300130630013305e337606ea4008dd4000a5eb7bdb180dd7a60103d879800022533305533720004002298103d8798000153330553371e0040022980103d87a800014c103d87b8000330024890550494c4f540030033004375a603660aa6ea804ccc005220104534849500030023003375a603460a86ea804888cdc500100091b9800123732660046ea00052201003001001222533333305700213232323232323300b0020013371491010128000025333053337100069007099b80483c80400c54ccc14ccdc4001a410004266e00cdc0241002800690068a9982a24929576861742061726520796f7520646f696e673f204e6f2049206d65616e2c20736572696f75736c792e001653330560011337149101035b5d2900004133714911035b5f2000375c60aa66600e00266ec1300102415d00375266e292210129000042233760980103422c2000375266601001000466e28dd7182b0009bae3057001375860a80046eb4c148004c8cdd81ba83052001374e60a60026ea80084c94ccc1500044cdc5245027b7d00002133714911037b5f2000375c60a664646600200200644a6660ae00220062664466ec130103422c2000375266601201260ae00466e29221023a20003330090093058002337146eb8c15c004dd7182c000982c80099801001182d00099bb04c10342207d0037520046eac0084c94ccc1500044cdc52441025b5d00002133714911035b5f2000375c60a666600a00266ec1300102415d0037520044466ec1300103422c2000375266600c00c00466e28dd7182a0009bae3055001375800426600a6eb40080044c8c8cdc524410268270000132333001001337006e3400920013371491101270000322253330533371000490000800899191919980300319b8000548004cdc599b80002533305633710004900a0a40c02903719b8b33700002a6660ac66e2000520141481805206e0043370c004901019b8300148080cdc70020011bae00222232330010010042253330540011004133003305600133002002305700122323300100100322533304e30270011337149110130000031533304e337100029000099b8a489012d0033002002302c00113300533708002900a19b8b3370066e1400520144818000cc0040048894ccc12ccdc4801240002002266600600666e1000920143371666e00cdc28012402890300008a9982481f0b180818251baa3011304a375402aa66608c603e60906ea80044c94ccc12c00454cc120110584c8c94ccc13400454cc128118584c8c94ccc13c00454cc130120584c8c94ccc14400454cc138128584c8c94ccc14c00454cc140130584c94ccc150c15c008526153305104d16325333333058001153305104d16153305104d16153305104d161375a0022a660a209a2c60aa00260aa00464a6666660ac0022a6609e0962c2a6609e0962c2a6609e0962c2a6609e0962c26eb8004c14c004c14c008c94cccccc15000454cc1341245854cc1341245854cc1341245854cc134124584dd7000982880098288011929999998290008a998258238b0a998258238b0a998258238b09bad001153304b04716304f001304f0023253333330500011533049045161533049045161533049045161375a0022a6609208a2c609a00260926ea800454cc11c10c594cccccc134004400454cc1181085854cc1181085854cc1181085854cc11810858c128c11cdd50008a99822a493165787065637420496e6c696e65446174756d28736869705f646174756d29203d20736869705f73746174652e646174756d00163007304637540022a6608807e2c6090002646600200202644a66608e002297ae0132325333045325333046302230483754002266e3c04cdd7182618249baa00114a0601c60906ea8c038c120dd50010998250011980200200089980200200098258011824800a999820180c98211baa0011325333045001153304203c16132325333047001153304403e161325333048304b002149854cc1140fc58c94cccccc13000454cc1140fc5854cc1140fc5854cc1140fc5854cc1140fc584dd7000982480098248011929999998250008a9982181e8b0a9982181e8b0a9982181e8b09bad001153304303d163047001304337540022a660820762ca66666608e00220022a660800742c2a660800742c2a660800742c2a660800742c608860826ea800454cc0fd2413e65787065637420496e6c696e65446174756d28617374657269615f646174756d29203d20617374657269615f696e7075742e6f75747075742e646174756d0016300130403754600e60806ea80108c10cc110c110004c06cccc004dd59802981f1baa3005303e37540046eb8c010c0f8dd50141bae3005303e375405044464a66607c603460806ea8004520001375a608860826ea8004c94ccc0f8c068c100dd50008a60103d87a8000132330010013756608a60846ea8008894ccc110004530103d87a8000132323253330433371e00e6eb8c11400c4c080cc120dd4000a5eb804cc014014008dd698228011824001182300099804001801181f981e1baa001153303a03116323300100100c22533303e00114c103d87a800013232533303c32533303d3016303f375400229404cdc79bae304330403754002056600a607e6ea8c014c0fcdd51803181f9baa00213019330410024bd70099802002000982100118200009181f0009181e981f000899299981d8008a9981c01a8b099299981e181f8010a99981c19b8748004dd6981d8008a51153303903616153303903616303d001325333037301330393754002297adef6c6013756607a60746ea8004cc00400800c88c8cc00400400c894ccc0f40045300103d87a80001323232533303c3371e00c6eb8c0f800c4c064cc104dd3000a5eb804cc014014008dd5981f0011820801181f800991980080080211299981d0008a5eb7bdb1804c8c8c8c94ccc0e8cdc7a44100002100313303f337606ea4008dd3000998030030019bab303c003375c6074004607c00460780026eb8c0e4c0d8dd50040a9981a24926657870656374204d696e742873686970796172645f706f6c69637929203d20707572706f7365001630383039303930390023756606e002606e606e0046eb0c0d4004c0d4c0d4008dd6181980098179baa303200230313032001302d37540182930a99815a4811856616c696461746f722072657475726e65642066616c7365001365632533302a30030011533302e302d37540042930a998158148b0a99981518030008a99981718169baa002149854cc0ac0a45854cc0ac0a458c0acdd5000a99999981800588058a998148138b0a998148138b0a998148138b0a998148138b0a99814a491d52756e6e696e672033206172672076616c696461746f72207370656e640013323232232322533302f323232323232323232323232323232323232323232325333045301e30473754002264a66608c604460906ea80584c8c94ccc120c084c128dd5000899192999825181318261baa001132323232323232323232323232325323233305a303300d1323232325333062001153305f05016132533306330660021325333060303b30623754002264646464a6660c8608060cc6ea80044c8c94ccc198c108c1a0dd50008991919192999835182198361baa001132323232323232323232323253330765333076305230263301f044230293035307a3754606c60f46ea80045288a9983ba481236d7573745f7370656e645f6f6e655f7363726970745f696e707574203f2046616c73650014a02a6660eca6660ec054294454cc1dd241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660eca6660ec008294454cc1dd2411d6d7573745f686176655f656e6f7567685f6675656c203f2046616c73650014a02a6660eca6660ec00c294454cc1dd2411e6d7573745f726573706563745f6d61785f7370656564203f2046616c73650014a02a6660eca6660ec00a294454cc1dd241206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a02a6660eca6660ec004294454cc1dd241216d7573745f73756274726163745f6675656c5f746f6b656e73203f2046616c73650014a02a6660eca6660ec010294454cc1dd2411c6d7573745f6275726e5f7370656e745f6675656c203f2046616c73650014a02a6660eca6660ec014294454cc1dd241156d7573745f7570646174655f78203f2046616c73650014a02a6660eca6660ec012294454cc1dd241156d7573745f7570646174655f79203f2046616c73650014a02a6660eca6660ec00e294454cc1dd2411f6d7573745f7570646174655f75707065725f626f756e64203f2046616c73650014a02a6660eca6660ec016294454cc1dd241216d7573745f70726573657276655f70696c6f745f746f6b656e203f2046616c73650014a02a6660eca6660ec006294454cc1dd2411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660ec002294454cc1dd24011a6d7573745f686f6c645f335f617373657473203f2046616c73650014a029405280a5014a029405280a5014a029405280a5014a0609e604460486eacc0d0c1e0dd500b99b8733301f3756606660ee6ea80581912201044655454c0033702014018609e66603c6eacc0c8c1d8dd500a81481b19b8900a008301900d32323371266e08dd6983c0011bad30783079001337046eb4c1e0004dd6983c183c801183a1baa02c3073375460ec60e66ea801ccdc39bad307530763076307630763072375401c012602a609800c66e1cdd6981618381baa00c3370006402266e1cdd6981518379baa00b3370006602266e3c0b0dd7183898391839183918371baa00a3330153756605260da6ea8c0a4c1b4dd501102d2441044655454c00153306b4915865787065637420536f6d6528737065656429203d0a20202020202020202020726174696f6e616c2e6e65772864697374616e63652c2074785f6c61746573745f74696d65202d2074785f6561726c696573745f74696d65290016330260023370200600a66e08004140c8cdc0180080698008061299983419b88001480004c1180044004dd6983618349baa001153306705c16302330683754604860d06ea80b8dd6983518339baa001153306505916302130663754604260cc6ea80b0cc0e40041594cccccc1a4004400454cc1881545854cc1881545854cc1881545854cc18815458c198c18cdd50008a998308298b180498311baa00115330600511630640013300602923375e603860c26ea8004c070c184dd5180e98309baa016375a60c460c60046eb4c184004c174dd50170a99982d181b0068991929998300008a9982e8270b09929998309832001099299982f181c98301baa0011323232325333062303b306437540022646464a6660ca608060ce6ea80044c8c8c8c94ccc1a4c114c1acdd5000899191919191919191929998392999839182698111980d820118129818983b1baa303230763754002294454cc1cd2401246d7573745f7370656e645f74776f5f7363726970745f696e70757473203f2046616c73650014a02a6660e4a6660e401e294454cc1cd2411c6d7573745f62655f76616c69645f70656c6c6574203f2046616c73650014a02a6660e4a6660e404c294454cc1cd241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660e4a6660e4010294454cc1cd241216d7573745f686176655f70656c6c65745f706f736974696f6e203f2046616c73650014a02a6660e4a6660e4006294454cc1cd2411c6d7573745f6164645f6675656c5f746f6b656e73203f2046616c73650014a02a6660e4a6660e400e294454cc1cd241206d7573745f6e6f745f6578636565645f6361706163697479203f2046616c73650014a02a6660e4a6660e400a294454cc1cd241206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a02a6660e4a6660e400c294454cc1cd2411b6d7573745f70726573657276655f646174756d203f2046616c73650014a02a6660e4a6660e4008294454cc1cd2411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660e4a6660e4004294454cc1cd2411a6d7573745f686f6c645f335f617373657473203f2046616c73650014a02a6660e4002294454cc1cd24011c6d7573745f6e6f745f6d696e745f746f6b656e73203f2046616c73650014a029405280a5014a029405280a5014a0294052819baf374c603a07698101a000304a301d301f3756605e60e66ea8050cdc399980d1bab302e307237540260be911044655454c003370000c02a60946660326eacc0b4c1c4dd5009012018980a9bad30733070375400a66ebc034110cdc499b80002011055533306a3370e0626eb4c0a0c1b4dd5002099b8702f375a605260da6ea801052819980a1bab3028306c3754605060d86ea8084165221044655454c00153306a05e163026306b3754604c60d66ea80c54ccc19cc100c1a4dd500089929998360008a9983482f8b0991929998370008a998358308b0991929998380008a998368318b0992999838983a0010a4c2a660dc0c82c64a6666660ea0022a660dc0c82c2a660dc0c82c2a660dc0c82c2a660dc0c82c26eb8004c1c8004c1c8008c94cccccc1cc00454cc1b01885854cc1b01885854cc1b0188584dd68008a998360310b183800098380011929999998388008a998350300b0a998350300b0a998350300b09bad001153306a06016306e001306a37540022a660d00bc2ca6666660dc00220022a660ce0ba2c2a660ce0ba2c2a660ce0ba2c2a660ce0ba2c60d660d06ea800454cc1992413c65787065637420496e6c696e65446174756d2870656c6c65745f646174756d29203d2070656c6c65745f696e7075742e6f75747075742e646174756d0016300e30673754604660ce6ea8008c10cccc038dd5981118331baa3022306637540026eb8c084c198dd50281bae3022306637540a060d060ca6ea800454cc18d2401ff65787065637420536f6d652870656c6c65745f696e70757429203d0a202020202020202020206c6973742e66696e64280a202020202020202020202020696e707574732c0a202020202020202020202020666e28696e70757429207b0a20202020202020202020202020207768656e20696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c206973207b0a20202020202020202020202020202020566572696669636174696f6e4b657943726564656e7469616c285f29202d3e2046616c73650a2020202020202020202020202020202053637269707443726564656e7469616c28616464725f7061796d656e6b7429202d3e0a202020202020202020202020202020202020616464725f7061796d656e74203d3d2070656c6c65745f76616c696461746f725f616464726573730a20202020202020202020202020207d0a2020202020202020202020207d2c0a202020202020202020202900163301b02f2325333063303c3065375400229404cdc79bae3069306637540020a6604060ca6ea8c080c194dd5181098329baa00133037001054533333306700110011533060053161533060053161533060053161533060053163064306137540022a660be0a22c600e60c06ea800454cc17813c58c188004cc01009c8cdd7980d182f9baa001301a305f3754603660be6ea8050dd69830182e9baa02e1533305a303500d132533305b3034305d375400226464a6660ba607260be6ea80044c8c8c8c94ccc1854ccc184c0f0c044cc0280bc8c050c080c194dd5181098329baa00114a22a660c49201246d7573745f7370656e645f74776f5f7363726970745f696e70757473203f2046616c73650014a02a6660c2a6660c200c294454cc1892411d6d7573745f62655f76616c69645f61737465726961203f2046616c73650014a02a6660c2a6660c202a294454cc189241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660c2a6660c2008294454cc189241226d7573745f686176655f617374657269615f706f736974696f6e203f2046616c73650014a02a6660c2a6660c2006294454cc1892411c6d7573745f6275726e5f736869705f746f6b656e203f2046616c73650014a02a6660c2a6660c2002294454cc1892411d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a02a6660c2004294454cc1892401206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a029405280a5014a029405281803981f1998059bab301f30633754603e60c66ea80601412201044655454c003007375a60ca60c46ea800ccdc4199804980501400a010a400066ebcdd31983119bb037500486ea00892f5bded8c06e98cc1892f7b6301010000010100004bd6f7b6300a9982f0290b180d182f9baa301a305f375404a607666600c6eacc068c178dd5180d182f1baa3061305e37540026eb8c064c178dd50241bae301a305e37540902a660b80a62c66028050464a6660b8606a60bc6ea8004528099b8f375c60c460be6ea8004128c064c178dd5180c982f1baa301a305e375400226464a6660b8a6660b8607060186600a0544601e603660c06ea8c070c180dd50008a51153305d491236d7573745f7370656e645f6f6e655f7363726970745f696e707574203f2046616c73650014a02a6660b8a6660b8020294454cc175241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660b8a6660b8004294454cc1752411c6d7573745f6275726e5f736869705f746f6b656e203f2046616c73650014a02a6660b8002294454cc17524011d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a029405280a50300230393330063756603460bc6ea8c068c178dd5009825a441044655454c003371066600a600c04802003a90001b8733300430050230494881044655454c00371203044646600200200644a6660be002297ae013232533305d300500213306200233004004001133004004001306300230610012305d305e305e0012223253330593035305b37540022900009bad305f305c375400264a6660b2606a60b66ea80045300103d87a800013233001001375660c060ba6ea8008894ccc17c004530103d87a80001323232533305e3371e00e6eb8c18000c4c0eccc18cdd4000a5eb804cc014014008dd6983000118318011830800998068018011191980080080111299982d8008a5eb7bdb1804c8c8c8c94ccc16ccdc7a441000021003133060337606ea4008dd3000998030030019bab305d003375c60b600460be00460ba002600200244a6660b0002290000981999801001182d8009191980080080111299982c0008a5eb804c8ccc888c8cc00400400c894ccc178004400c4c8cc180dd3998301ba90063306037526eb8c174004cc180dd41bad305e0014bd7019801801983100118300009bae3057001375660b00026600600660b800460b4002600200244a6660aa002290000981819801001182c00092999827981418289baa300d30523754002294052898279baa021533304c3025304e37546600c03446466002002646600200264a6660a0605860a46ea800452f5bded8c026eacc158c14cdd5000998021bab300e30523754601c60a46ea800c014894ccc15000452f5c02660aa60a460ac0026600400460ae00244a6660a600229404c94ccc140cdc79bae305600201114a226600600600260ac00229445281119198008008019129998298008a60103d87a8000132323253330523371e00c6eb8c15000c4c0bccc15cdd3000a5eb804cc014014008dd5982a001182b801182a8009bae3050304d37540022a660969215d6578706563742053637269707443726564656e7469616c2873686970796172645f706f6c69637929203d0a202020202020736869705f696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c00163007304c3754600e60986ea8c020c130dd5000982718259baa001153304949013665787065637420536f6d6528736869705f696e70757429203d2066696e645f696e70757428696e707574732c20736869705f726566290016323300201623375e600e60986ea8004008c134c128dd500b9119198008008019129998270008a60103d87a800013232533304c300500213029330510024bd70099802002000982900118280008a99823a48120657870656374205370656e6428736869705f72656629203d20707572706f73650016304b304837540022a6608c92015865787065637420536f6d65286d61785f73706565645f726174696f6e616c29203d0a202020202020726174696f6e616c2e6e6577286d61785f73706565642e64697374616e63652c206d61785f73706565642e74696d6529001633001375a6004608e6ea80c0dd6980198239baa030225333045301e00114c103d87a80001533304533710002900009811198251811198251ba830230023304a3750604600297ae04bd7009811198251811198251ba80023304a375000297ae04bd70118248009182418248009bad30463047002375c608a002608a0046eb8c10c004c10c008dd6982080098208011bad303f001303b3754020607a607c607c607c0046eacc0f0004c0f0c0f0008dd6181d000981d181d0011bac303800130343754606e004606c606e00260646ea8004526153303049011856616c696461746f722072657475726e65642066616c7365001365632533302e30070011325333033001153303002816132325333035001153303202a1613253330363039002149854cc0cc0ac58c94cccccc0e800454cc0cc0ac5854cc0cc0ac5854cc0cc0ac584dd68008a998198158b181b800981b80119299999981c0008a998188148b0a998188148b0a998188148b09bad0011533031029163035001303137540042a66605c6014002264a6660660022a660600502c264a666068606e0042930a998188148b19299999981c0008a998188148b0a998188148b0a998188148b09bad0011533031029163035001303137540042a66605c60120022a66606460626ea8008526153302f027161533302e300800115333032303137540042930a998178138b0a998178138b18179baa00153333330340011001153302d02516153302d02516153302d02516153302d025163300100202422533302b3004302d3754004264a6660600022a6605a0042c26464a6660640022a6605e0082c26464a6660680022a6606200c2c26464a66606c0022a660660102c26464a6660700022a6606a0142c264a66607260780042930a9981b0058b19299999981e8008a9981b0058b0a9981b0058b0a9981b0058b09bad001153303600b16303a001303a00232533333303b0011533034009161533034009161533034009161533034009161375c0026070002607000464a6666660720022a6606400e2c2a6606400e2c2a6606400e2c2a6606400e2c26eb8004c0d8004c0d8008c94cccccc0dc00454cc0c00145854cc0c00145854cc0c0014584dd68008a998180028b181a000981a00119299999981a8008a998170018b0a998170018b0a998170018b09bad001153302e003163032001302e37540042a660580022ca66666606001620162a660520442c2a660520442c2a660520442c2a660520442c605c60566ea8028dc3a40006e1d2006370e90021b8748008dd2a40006e052000370090011b884800054cc0840045854cc0840045854cc0840045854cc08400459240191496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e00375a0026eb4004dd68009bad001375c0026eb800524196657870656374205b736869705f6f75747075745d203d0a202020202020202020206c6973742e66696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d20736869705f696e7075742e6f75747075742e61646472657373207d2c0a20202020202020202020290049013965787065637420496e6c696e65446174756d28736869705f6f75747075745f646174756d29203d20736869705f6f75747075742e646174756d0049013765787065637420736869705f6f75747075745f646174756d3a2053686970446174756d203d20736869705f6f75747075745f646174756d004901476578706563742046696e6974652874785f6561726c696573745f74696d6529203d2076616c69646974795f72616e67652e6c6f7765725f626f756e642e626f756e645f74797065004901456578706563742046696e6974652874785f6c61746573745f74696d6529203d2076616c69646974795f72616e67652e75707065725f626f756e642e626f756e645f747970650049012f6578706563742070656c6c65745f646174756d3a2050656c6c6574446174756d203d2070656c6c65745f646174756d004901ff65787065637420536f6d6528617374657269615f696e70757429203d0a202020202020202020206c6973742e66696e64280a202020202020202020202020696e707574732c0a202020202020202020202020666e28696e70757429207b0a20202020202020202020202020207768656e20696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c206973207b0a20202020202020202020202020202020566572696669636174696f6e4b657943726564656e7469616c285f29202d3e2046616c73650a2020202020202020202020202020202053637269707443726564656e7469616c28616464725f7061796d656d6e7429202d3e0a202020202020202020202020202020202020616464725f7061796d656e74203d3d20617374657269615f76616c696461746f725f616464726573730a20202020202020202020202020207d0a2020202020202020202020207d2c0a20202020202020202020290049011672656465656d65723a205368697052656465656d657200490110646174756d3a2053686970446174756d0049013265787065637420617374657269615f646174756d3a2041737465726961446174756d203d20617374657269615f646174756d00490159657870656374205b736869705f73746174655d203d0a202020202020202020207472616e73616374696f6e2e66696e645f7363726970745f6f757470757473286f7574707574732c2073686970796172645f706f6c696379290049012965787065637420736869705f646174756d3a2053686970446174756d203d20736869705f646174756d00490120657870656374205b285f2c202d31295d203d206d696e7465645f746f6b656e730049011a72656465656d65723a20536869707961726452656465656d6572005734ae7155ceaab9e5573eae815d0aba257481"; +const PELLET_PARAMETERIZED: &str = "590d270100003232323232323232323232323232222325333333012002153232323233300e30013010375400c2a6601e92011c52756e6e696e672032206172672076616c696461746f72206d696e7400132325333010323232323253330153008301737540082646464a666030601660346ea80284c94ccc0654ccc0654ccc064c030c06cdd5191980080080391299980f8008a60103d87a800013232533301d3013323330073756600260426ea8c004c084dd50019bae3024302137540306eb8c004c084dd500c118121812800898091981100125eb804cc010010004c08c008c0840045288a5014a22a660349201296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a02a666032002294454cc06924011d6d7573745f6d696e745f6675656c5f746f6b656e73203f2046616c73650014a02940c038ccc00400800d2201044655454c001533301833710666002004006911044655454c00480005288a9980ca491d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a044464a666036601e603a6ea8004520001375a6042603c6ea8004c94ccc06cc03cc074dd50008a60103d87a80001323300100137566044603e6ea8008894ccc084004530103d87a8000132323253330203371e00e6eb8c08800c4c054cc094dd4000a5eb804cc014014008dd698110011812801181180099198008008021129998100008a6103d87a80001323232533301f3371e00e6eb8c08400c4c050cc090dd3000a5eb804cc014014008dd5981080118120011811000991980080080191299980e0008a5eb7bdb1804c8c8c8c94ccc070cdc7a441000021003133021337606ea4008dd3000998030030019bab301e003375c60380046040004603c0026eb8c06cc060dd50020a9980b24922657870656374204d696e74286675656c5f706f6c69637929203d20707572706f736500163756603460366036603660360046eb0c064004c054dd5180c001180b980c00098099baa008149854cc0452411856616c696461746f722072657475726e65642066616c73650013656325333010300300115333014301337540042930a998088078b0a99980818020008a99980a18099baa002149854cc04403c5854cc04403c58c044dd5000a99999980b00388038a998078068b0a998078068b0a998078068b0a998078068b0a99807a491d52756e6e696e672033206172672076616c696461746f72207370656e64001332323223232253330153232323232533301a300e301c37540082646464a66603a6020603e6ea80044c8c8c94ccc080c050c088dd5000899191919192999812980c18139baa0131323232533302c001153302902316132533302d3030002132533302a3370e900218161baa00113232323232323253330315333031300d33016019232330010013233001001325333035302930373754002297adef6c6013756607660706ea8004cc04cdd5980b181b9baa30163037375400601c44a666072002297ae013303a3037303b00133002002303c00122533303800114a0264a66606a66e3cccdc6240006e35221045348495000375c607600491104534849500014a22660060060026076002294454cc0c924011d6d7573745f696e7075745f736869705f746f6b656e203f2046616c73650014a02a666062a666062006294454cc0c92411d6d7573745f686f6c645f61646d696e5f746f6b656e203f2046616c73650014a02a666062a666062008294454cc0c92411d6d7573745f686176655f656e6f7567685f6675656c203f2046616c73650014a02a666062a666062004294454cc0c9241206d7573745f70726f766964655f6675656c5f616d6f756e74203f2046616c73650014a02a666062002294454cc0c924011b6d7573745f70726573657276655f646174756d203f2046616c73650014a029405280a5014a066ebc014088cdc39998069bab30113032375400e01e9101044655454c003370201801460446660186eacc040c0c4dd50031bae3014303137540506eb8c040c0c4dd501419b8900800a3301d00102853333330330011001153302c02716153302c02716153302c02716153302c027163030302d37540022a660569213365787065637420496e6c696e65446174756d286f75745f646174756d29203d2070656c6c65745f6f75747075742e646174756d0016302f30303030302c37540022a660540482c605c002646600200201e44a66605a002297ae013232533302b3375e6022605c6ea8008c044c0b8dd5180698171baa00e133030002330040040011330040040013031002302f001375c6058605a605a60526ea8060dd6981598141baa0131533302530013300a00d253330263330265333026301930283754601860526ea8c030c0a4dd5180418149baa00114a02945282511301c3330043756601060526ea8c020c0a4dd50009bae300c302937540406eb8c020c0a4dd50100a5014a22a6604c921296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a04a66604a6030604e6ea80045288a503330013756600a604c6ea8c014c098dd5003001a45044655454c00222325333026301a302837540022900009bad302c3029375400264a66604c603460506ea8004530103d87a8000132330010013756605a60546ea8008894ccc0b0004530103d87a80001323232533302b3371e00e6eb8c0b400c4c080cc0c0dd4000a5eb804cc014014008dd6981680118180011817000998020018011119198008008019129998148008a60103d87a8000132323253330283371e00c6eb8c0a800c4c074cc0b4dd3000a5eb804cc014014008dd59815001181680118158009bae3026302337540022a660429215b6578706563742053637269707443726564656e7469616c286675656c5f706f6c69637929203d0a20202020202070656c6c65745f696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c0016300530223754600a60446ea8c004c088dd5001118129813000981198101baa001153301e49013a65787065637420536f6d652870656c6c65745f696e70757429203d2066696e645f696e70757428696e707574732c2070656c6c65745f726566290016323300200523375e600860426ea8004008c088c07cdd50031119198008008019129998118008a60103d87a8000132325333021300500213016330260024bd7009980200200098138011812800918108008a9980da48122657870656374205370656e642870656c6c65745f72656629203d20707572706f736500163758603e604060400046eb0c078004c068dd5180e801180e180e800980c1baa001149854cc0592411856616c696461746f722072657475726e65642066616c7365001365632533301430070011325333019001153301601216132533301a301d002149854cc05c04c58c94cccccc07800454cc05c04c5854cc05c04c5854cc05c04c584dd68008a9980b8098b180d800980b9baa00215333014300800115333018301737540042930a9980a8088b0a9980a8088b180a9baa001533333301a0011001153301300f16153301300f16153301300f16153301300f163300100200e225333011300430133754004264a66602c0022a660260042c26464a6660300022a6602a0082c26464a6660340022a6602e00c2c264a666036603c0042930a9980c0038b19299999980f8008a9980c0038b0a9980c0038b0a9980c0038b0a9980c0038b09bae001301c001301c00232533333301d0011533016005161533016005161533016005161375a0022a6602c00a2c6034002603400464a6666660360022a660280062c2a660280062c2a660280062c26eb400454cc05000c58c060004c050dd50010a998090008b299999980b00388038a998078060b0a998078060b0a998078060b0a998078060b180a18089baa006370e90001b8748008dd2a40006e212000153300b00116153300b00116153300b00116153300b0011649191496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e00490195657870656374205b70656c6c65745f6f75747075745d203d0a2020202020202020202066696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d2070656c6c65745f696e7075742e6f75747075742e61646472657373207d2c0a202020202020202020202900490129657870656374206f75745f646174756d3a2050656c6c6574446174756d203d206f75745f646174756d0049011872656465656d65723a2050656c6c657452656465656d657200490112646174756d3a2050656c6c6574446174756d0049011672656465656d65723a204675656c52656465656d6572005734ae7155ceaab9e5573eae815d0aba257481"; + +const ASTERIA_PATH: &str = "game/src/scripts/asteria.txt"; +const SPACETIME_PATH: &str = "game/src/scripts/spacetime.txt"; +const PELLET_PATH: &str = "game/src/scripts/pellet.txt"; pub async fn create_ship( db: &Db, @@ -46,17 +50,21 @@ pub async fn create_ship( ) -> anyhow::Result<()> { log::debug!("The args are:: {:?}", args); - let asteria_script: PlutusScript = PlutusScript(hex::decode(ASTERIA_SCRIPT_HEX).unwrap()); + let asteria_script_hex: &str = &std::fs::read_to_string(ASTERIA_PATH)?; + let spacetime_script_hex: &str = &std::fs::read_to_string(SPACETIME_PATH)?; + let pellet_script_hex: &str = &std::fs::read_to_string(PELLET_PATH)?; + + let asteria_script: PlutusScript = PlutusScript(hex::decode(asteria_script_hex).unwrap()); let asteria_hash: PolicyId = compute_plutus_v2_script_hash(asteria_script.clone()); let asteria_address: Address = Address(hex::decode("70".to_owned() + &hex::encode(asteria_hash)).unwrap()); - let spacetime_script: PlutusScript = PlutusScript(hex::decode(SHIP_SCRIPT_HEX).unwrap()); + let spacetime_script: PlutusScript = PlutusScript(hex::decode(spacetime_script_hex).unwrap()); let spacetime_hash: PolicyId = compute_plutus_v2_script_hash(spacetime_script.clone()); let spacetime_address: Address = Address(hex::decode("70".to_owned() + &hex::encode(spacetime_hash)).unwrap()); - let pellet_script: PlutusScript = PlutusScript(hex::decode(PELLET_SCRIPT_HEX).unwrap()); + let pellet_script: PlutusScript = PlutusScript(hex::decode(pellet_script_hex).unwrap()); let pellet_policy: PolicyId = compute_plutus_v2_script_hash(pellet_script.clone()); // Construct a template Transaction to push coins into later @@ -264,10 +272,13 @@ pub async fn gather_fuel( ) -> anyhow::Result<()> { log::debug!("The args are:: {:?}", args); - let spacetime_script: PlutusScript = PlutusScript(hex::decode(SHIP_SCRIPT_HEX).unwrap()); + let spacetime_script_hex: &str = &std::fs::read_to_string(SPACETIME_PATH)?; + let pellet_script_hex: &str = &std::fs::read_to_string(PELLET_PATH)?; + + let spacetime_script: PlutusScript = PlutusScript(hex::decode(spacetime_script_hex).unwrap()); let shipyard_policy: PolicyId = compute_plutus_v2_script_hash(spacetime_script.clone()); - let pellet_script: PlutusScript = PlutusScript(hex::decode(PELLET_SCRIPT_HEX).unwrap()); + let pellet_script: PlutusScript = PlutusScript(hex::decode(pellet_script_hex).unwrap()); let pellet_policy: PolicyId = compute_plutus_v2_script_hash(pellet_script.clone()); // Construct a template Transaction to push coins into later @@ -459,10 +470,13 @@ pub async fn move_ship( ) -> anyhow::Result<()> { log::debug!("The args are:: {:?}", args); - let spacetime_script: PlutusScript = PlutusScript(hex::decode(SHIP_SCRIPT_HEX).unwrap()); + let spacetime_script_hex: &str = &std::fs::read_to_string(SPACETIME_PATH)?; + let pellet_script_hex: &str = &std::fs::read_to_string(PELLET_PATH)?; + + let spacetime_script: PlutusScript = PlutusScript(hex::decode(spacetime_script_hex).unwrap()); let shipyard_policy: PolicyId = compute_plutus_v2_script_hash(spacetime_script.clone()); - let pellet_script: PlutusScript = PlutusScript(hex::decode(PELLET_SCRIPT_HEX).unwrap()); + let pellet_script: PlutusScript = PlutusScript(hex::decode(pellet_script_hex).unwrap()); let pellet_policy: PolicyId = compute_plutus_v2_script_hash(pellet_script.clone()); // Construct a template Transaction to push coins into later @@ -657,15 +671,19 @@ pub async fn mine_asteria( ) -> anyhow::Result<()> { log::debug!("The args are:: {:?}", args); - let asteria_script: PlutusScript = PlutusScript(hex::decode(ASTERIA_SCRIPT_HEX).unwrap()); + let asteria_script_hex: &str = &std::fs::read_to_string(ASTERIA_PATH)?; + let spacetime_script_hex: &str = &std::fs::read_to_string(SPACETIME_PATH)?; + let pellet_script_hex: &str = &std::fs::read_to_string(PELLET_PATH)?; + + let asteria_script: PlutusScript = PlutusScript(hex::decode(asteria_script_hex).unwrap()); let asteria_hash: PolicyId = compute_plutus_v2_script_hash(asteria_script.clone()); let asteria_address: Address = Address(hex::decode("70".to_owned() + &hex::encode(asteria_hash)).unwrap()); - let spacetime_script: PlutusScript = PlutusScript(hex::decode(SHIP_SCRIPT_HEX).unwrap()); + let spacetime_script: PlutusScript = PlutusScript(hex::decode(spacetime_script_hex).unwrap()); let shipyard_policy: PolicyId = compute_plutus_v2_script_hash(spacetime_script.clone()); - let pellet_script: PlutusScript = PlutusScript(hex::decode(PELLET_SCRIPT_HEX).unwrap()); + let pellet_script: PlutusScript = PlutusScript(hex::decode(pellet_script_hex).unwrap()); let pellet_policy: PolicyId = compute_plutus_v2_script_hash(pellet_script.clone()); // Construct a template Transaction to push coins into later diff --git a/game/src/scripts/asteria.txt b/game/src/scripts/asteria.txt new file mode 100644 index 0000000..e4baa9f --- /dev/null +++ b/game/src/scripts/asteria.txt @@ -0,0 +1 @@ +590d3c01000033332323232323232323232323232322232232232323232232323232253330163232323232323232533301e300c3020375400e264646464a666044602a60486ea80044c8c8c8c8c8c8c94ccc0a4c0700184c94ccc0b800454cc0ac094584c94ccc0bcc0c80084c94ccc0b0c064c0b8dd500089919191919192999819299981919baf300b303537540106e98cc894ccc0d0c09c0b040044c8c8cc00400400c894ccc0ec0044cc0f0cdd8261014000374c00697adef6c60132323232533303b3375e66012911000024c103d879800013304033760981014000374c00e00a2a66607666e3d22100002132533303c302f303e375400226608266ec13010140003042303f3754002008200864a666078a66608000229445280a6103d87a80001301d33041374c00297ae03233001001002225333041001133042337609801014000375006a97adef6c6013232323253330413375e6601e911000024c103d879800013304633760981014000375007200a2a66608266e3d22100002132533304230353044375400226608e66ec1301014000304830453754002008200864a666084606a002298103d87a80001302333047375000297ae03370000207226608c66ec0dd48011ba800133006006003375a60860066eb8c104008c114008c10c0044cc100cdd81ba9002374c0026600c00c0066eacc0f400cdd7181d801181f801181e8009919001191980080080111299981d8008a4c264a66607800229309919299981d1816981e1baa33008375c607860800086eb8c0f00084cc014014cc0fc00800454cc0ed2401326b65797320696e206173736f63696174697665206c697374206172656e277420696e20617363656e64696e67206f7264657200163040002303e001303e0013303933760981014000375005897adef6c60225333034337200040022980103d8798000153330343371e0040022980103d87a800014c103d87b800037566016606a6ea8c02cc0d4dd50080a511533033491146d7573745f6164645f666565203f2046616c73650014a02a666064a666064006294454cc0cd2411d6d7573745f686f6c645f61646d696e5f746f6b656e203f2046616c73650014a02a666064a666064004294454cc0cd2411e6d7573745f696e6372656d656e745f636f756e746572203f2046616c73650014a02a666064002294454cc0cd2401256d7573745f70726573657276655f73686970796172645f706f6c696379203f2046616c73650014a029405280a503371e6eb8c028c0d0dd500200a19b87375a602460666ea800ccdc000a2400466e21200033300a3756601060646ea8014dd7180898191baa029375c601060646ea80a4cc0800040ad4cccccc0d4004400454cc0b80a85854cc0b80a85854cc0b80a85854cc0b80a858c0c8c0bcdd50008a998168140b180298171baa001153302c0261630300013300100f23375e6018605a6ea8004c030c0b4dd5180198169baa008132533302a3018007132533302f001153302c0261613253330303033002132533302d301a302f375400226464646464a666064604a60686ea80044c8c8c94ccc0d54ccc0d40145288a9981b24811d6d7573745f696e7075745f736869705f746f6b656e203f2046616c73650014a02a66606aa66606a004294454cc0d92411f6d7573745f726573706563745f6d61785f6d696e696e67203f2046616c73650014a02a66606a002294454cc0d924011b6d7573745f70726573657276655f646174756d203f2046616c73650014a0294052819baf0280063232323371266e08dd6981e0009bad303c303d002337046eb4c0f0008dd6981e181e800981c1baa323230183303c375066e08dd6981e8011bad303d0013303c375066e08dd6981e981f0011bad303d303e0014bd70181c9baa32323232301b3303f375066e04cdc11bad3040004001337046eb4c10000800ccc0fcdd419b820030014bd701bad303f3040001303b3754607c60766ea801cdd6981e981f000981c9baa300348008c0e0dd5180118019bab300e30383754601c60706ea804cc0dcdd5180098011bab300d303737540124602a660726ea0004cc0e530010101004bd701199807000a450048810015330334913f65787065637420536f6d652870657263656e7461676529203d20726174696f6e616c2e6e6577286d61785f617374657269615f6d696e696e672c20313030290016533303130244832004530103d87a80001533303133710906400a4000260246606c60246606c6ea0cdc0a400004e6606c6ea0cdc024000906380a5eb812f5c0260246606c60246606c6ea009ccc0d9301021864004bd7025eb80c01ccc04005c8c8cc004004c8cc004004c94ccc0d0c088c0d8dd50008a5eb7bdb1804dd5981d181b9baa0013300f37566018606c6ea8c030c0d8dd500180b11299981c0008a5eb804cc0e4c0d8c0e8004cc008008c0ec004894ccc0dc004528099299981a19b8f33371890001b8d489045348495000375c607400491104534849500014a2266006006002607400266042002058a66666606c00220022a6605e0562c2a6605e0562c2a6605e0562c2a6605e0562c606660606ea800454cc0b80a458c018c0bcdd50008a998168138b181880099801008119baf300d302e3754002601a605c6ea8c010c0b8dd50048a99981518009980500892999815999815a999815980f18169baa300d302e3754601a605c6ea8c010c0b8dd50008a5014a294128899b8848000ccc018dd5980218171baa3004302e37540026eb8c034c0b8dd50129bae3004302e375404a29405288a99815a481296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a04a666054603a60586ea80045288a5022323300100100322533303000114bd70099192999817180280109981980119802002000899802002000981a00118190009181718178009181698171817000911192999814980b98159baa0011480004dd6981798161baa0013253330293017302b3754002298103d87a80001323300100137566060605a6ea8008894ccc0bc004530103d87a80001323232533302e3371e00e6eb8c0c000c4c03ccc0ccdd4000a5eb804cc014014008dd6981800118198011818800998020018011119198008008019129998160008a60103d87a80001323232533302b3371e00c6eb8c0b400c4c030cc0c0dd3000a5eb804cc014014008dd598168011818001181700098129baa0123028302537540022a6604692013c65787065637420536f6d6528617374657269615f696e70757429203d2066696e645f696e70757428696e707574732c20617374657269615f726566290016323300200923375e600a604c6ea8004008c09cc090dd50051119198008008019129998140008a60103d87a80001323253330263005002130073302b0024bd70099802002000981600118150009ba5480008c09400454cc07d24123657870656374205370656e6428617374657269615f72656629203d20707572706f73650016375c604660480046eb4c088004c078dd50079bac3020302130210023758603e00260366ea8c078008c074c078004c064dd50008a4c2a6602e9211856616c696461746f722072657475726e65642066616c73650013656325333015300800115333019301837540082930a9980b0098b0a99980a98018008a99980c980c1baa004149854cc05804c5854ccc054c00800454ccc064c060dd50020a4c2a6602c0262c2a6602c0262c602c6ea800cdc3a40086e1d200253333330190011001153301200f16153301200f16153301200f16153301200f163300100300e225333010300330123754004264a66602a0022a660240042c26464a66602e0022a660280082c264a66603060360042930a9980a8028b19299999980e0008a9980a8028b0a9980a8028b0a9980a8028b0a9980a8028b09bae0013019001301900232533333301a0011533013003161533013003161533013003161375a0022a660260062c602e00260266ea800854cc04400458dc3a4000a66666602800220022a6601a0162c2a6601a0162c2a6601a0162c2a6601a0162c6eb4004dd6800a499c657870656374205b617374657269615f6f75747075745d203d0a202020202020202020206c6973742e66696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d20617374657269615f696e7075742e6f75747075742e61646472657373207d2c0a20202020202020202020290049013f65787065637420496e6c696e65446174756d28617374657269615f6f75747075745f646174756d29203d20617374657269615f6f75747075742e646174756d0049014065787065637420617374657269615f6f75747075745f646174756d3a2041737465726961446174756d203d20617374657269615f6f75747075745f646174756d0049011972656465656d65723a204173746572696152656465656d657200490113646174756d3a2041737465726961446174756d005734ae7155ceaab9e5573eae815d0aba257489812fd8799f581c516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d284c6173746572696141646d696eff004c01051a002dc6c0004c010218320001 \ No newline at end of file diff --git a/game/src/scripts/pellet.txt b/game/src/scripts/pellet.txt new file mode 100644 index 0000000..4241244 --- /dev/null +++ b/game/src/scripts/pellet.txt @@ -0,0 +1 @@ +590d5a01000033232323232323232323232323232222325333333012002153232323233300e30013010375400c2a6601e9211c52756e6e696e672032206172672076616c696461746f72206d696e7400132325333010323232323253330153008301737540082646464a666030601660346ea80284c94ccc0654ccc0654ccc064c030c06cdd5191980080080391299980f8008a60103d87a800013232533301d3013323330073756600260426ea8c004c084dd50019bae3024302137540306eb8c004c084dd500c118121812800898091981100125eb804cc010010004c08c008c0840045288a5014a22a660349201296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a02a666032002294454cc06924011d6d7573745f6d696e745f6675656c5f746f6b656e73203f2046616c73650014a02940c038ccc00400800d2201044655454c001533301833710666002004006911044655454c00480005288a9980ca491d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a044464a666036601e603a6ea8004520001375a6042603c6ea8004c94ccc06cc03cc074dd50008a60103d87a80001323300100137566044603e6ea8008894ccc084004530103d87a8000132323253330203371e00e6eb8c08800c4c054cc094dd4000a5eb804cc014014008dd698110011812801181180099198008008021129998100008a6103d87a80001323232533301f3371e00e6eb8c08400c4c050cc090dd3000a5eb804cc014014008dd5981080118120011811000991980080080191299980e0008a5eb7bdb1804c8c8c8c94ccc070cdc7a441000021003133021337606ea4008dd3000998030030019bab301e003375c60380046040004603c0026eb8c06cc060dd50020a9980b24922657870656374204d696e74286675656c5f706f6c69637929203d20707572706f736500163756603460366036603660360046eb0c064004c054dd5180c001180b980c00098099baa008149854cc0452411856616c696461746f722072657475726e65642066616c73650013656325333010300300115333014301337540042930a998088078b0a99980818020008a99980a18099baa002149854cc04403c5854cc04403c58c044dd5000a99999980b00388038a998078068b0a998078068b0a998078068b0a998078068b0a99807a491d52756e6e696e672033206172672076616c696461746f72207370656e64001332323223232253330153232323232533301a300e301c37540082646464a66603a6020603e6ea80044c8c8c94ccc080c050c088dd5000899191919192999812980c18139baa0131323232533302c001153302902316132533302d3030002132533302a3370e900218161baa00113232323232323253330315333031300d33016019232330010013233001001325333035302930373754002297adef6c6013756607660706ea8004cc04cdd5980b181b9baa30163037375400601c44a666072002297ae013303a3037303b00133002002303c00122533303800114a0264a66606a66e3cccdc6240006e35221045348495000375c607600491104534849500014a22660060060026076002294454cc0c924011d6d7573745f696e7075745f736869705f746f6b656e203f2046616c73650014a02a666062a666062006294454cc0c92411d6d7573745f686f6c645f61646d696e5f746f6b656e203f2046616c73650014a02a666062a666062008294454cc0c92411d6d7573745f686176655f656e6f7567685f6675656c203f2046616c73650014a02a666062a666062004294454cc0c9241206d7573745f70726f766964655f6675656c5f616d6f756e74203f2046616c73650014a02a666062002294454cc0c924011b6d7573745f70726573657276655f646174756d203f2046616c73650014a029405280a5014a066ebc014088cdc39998069bab30113032375400e01e9101044655454c003370201801460446660186eacc040c0c4dd50031bae3014303137540506eb8c040c0c4dd501419b8900800a3301d00102853333330330011001153302c02716153302c02716153302c02716153302c027163030302d37540022a660569213365787065637420496e6c696e65446174756d286f75745f646174756d29203d2070656c6c65745f6f75747075742e646174756d0016302f30303030302c37540022a660540482c605c002646600200201e44a66605a002297ae013232533302b3375e6022605c6ea8008c044c0b8dd5180698171baa00e133030002330040040011330040040013031002302f001375c6058605a605a60526ea8060dd6981598141baa0131533302530013300a00d253330263330265333026301930283754601860526ea8c030c0a4dd5180418149baa00114a02945282511301c3330043756601060526ea8c020c0a4dd50009bae300c302937540406eb8c020c0a4dd50100a5014a22a6604c921296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a04a66604a6030604e6ea80045288a503330013756600a604c6ea8c014c098dd5003001a45044655454c00222325333026301a302837540022900009bad302c3029375400264a66604c603460506ea8004530103d87a8000132330010013756605a60546ea8008894ccc0b0004530103d87a80001323232533302b3371e00e6eb8c0b400c4c080cc0c0dd4000a5eb804cc014014008dd6981680118180011817000998020018011119198008008019129998148008a60103d87a8000132323253330283371e00c6eb8c0a800c4c074cc0b4dd3000a5eb804cc014014008dd59815001181680118158009bae3026302337540022a660429215b6578706563742053637269707443726564656e7469616c286675656c5f706f6c69637929203d0a20202020202070656c6c65745f696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c0016300530223754600a60446ea8c004c088dd5001118129813000981198101baa001153301e49013a65787065637420536f6d652870656c6c65745f696e70757429203d2066696e645f696e70757428696e707574732c2070656c6c65745f726566290016323300200523375e600860426ea8004008c088c07cdd50031119198008008019129998118008a60103d87a8000132325333021300500213016330260024bd7009980200200098138011812800918108008a9980da48122657870656374205370656e642870656c6c65745f72656629203d20707572706f736500163758603e604060400046eb0c078004c068dd5180e801180e180e800980c1baa001149854cc0592411856616c696461746f722072657475726e65642066616c7365001365632533301430070011325333019001153301601216132533301a301d002149854cc05c04c58c94cccccc07800454cc05c04c5854cc05c04c5854cc05c04c584dd68008a9980b8098b180d800980b9baa00215333014300800115333018301737540042930a9980a8088b0a9980a8088b180a9baa001533333301a0011001153301300f16153301300f16153301300f16153301300f163300100200e225333011300430133754004264a66602c0022a660260042c26464a6660300022a6602a0082c26464a6660340022a6602e00c2c264a666036603c0042930a9980c0038b19299999980f8008a9980c0038b0a9980c0038b0a9980c0038b0a9980c0038b09bae001301c001301c00232533333301d0011533016005161533016005161533016005161375a0022a6602c00a2c6034002603400464a6666660360022a660280062c2a660280062c2a660280062c26eb400454cc05000c58c060004c050dd50010a998090008b299999980b00388038a998078060b0a998078060b0a998078060b0a998078060b180a18089baa006370e90001b8748008dd2a40006e212000153300b00116153300b00116153300b00116153300b0011649191496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e00490195657870656374205b70656c6c65745f6f75747075745d203d0a2020202020202020202066696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d2070656c6c65745f696e7075742e6f75747075742e61646472657373207d2c0a202020202020202020202900490129657870656374206f75745f646174756d3a2050656c6c6574446174756d203d206f75745f646174756d0049011872656465656d65723a2050656c6c657452656465656d657200490112646174756d3a2050656c6c6574446174756d0049011672656465656d65723a204675656c52656465656d6572005734ae7155ceaab9e5573eae815d0aba257489812fd8799f581c516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d284c6173746572696141646d696eff0001 \ No newline at end of file diff --git a/game/src/scripts/spacetime.txt b/game/src/scripts/spacetime.txt new file mode 100644 index 0000000..8cef1ca --- /dev/null +++ b/game/src/scripts/spacetime.txt @@ -0,0 +1 @@ +592e3101000033333333323232323232323232323232323232323232323232323223223222232232232232223253333330280021532323232323232323330283001302a37540142a660529211c52756e6e696e672032206172672076616c696461746f72206d696e740013232533302a3232323232323232325333033300c303537540102646464a66606c601e60706ea80384c8c8c94ccc0e4c048c0ecdd500089919191919299981f180c98201baa0011323232325333046001153304303e161325333047304a0021325333044301f30463754002264646464a666090604860946ea80044c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c94ccc16d4ccc16c0805288a9982e24811d6d7573745f62655f76616c69645f61737465726961203f2046616c73650014a02a6660b6a6660b6010294454cc171241206d7573745f6d696e745f65787065637465645f76616c7565203f2046616c73650014a02a6660b6a6660b600e294454cc171241216d7573745f726573706563745f6d696e5f64697374616e6365203f2046616c73650014a02a6660b6a6660b600c294454cc1712411b6d7573745f686176655f736869705f6e616d65203f2046616c73650014a02a6660b6a6660b600a294454cc1712411c6d7573745f686176655f70696c6f745f6e616d65203f2046616c73650014a02a6660b6a6660b6008294454cc1712411d6d7573745f686176655f6c61746573745f74696d65203f2046616c73650014a02a6660b6a6660b6006294454cc1712411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660b6a6660b6004294454cc1712411e6d7573745f686f6c645f696e697469616c5f6675656c203f2046616c73650014a02a6660b6002294454cc17124011a6d7573745f686f6c645f335f617373657473203f2046616c73650014a029405280a5014a029405280a5014a06068664600200244a6660c0002290000981d99801001183180099198008009bab3025305e375403244a6660c0002297ae01323332223233001001003225333066001100313233068374e660d06ea4018cc1a0dd49bae30650013306837506eb4c1980052f5c06600600660d400460d00026eb8c17c004dd59830000998018019832001183100099b8733301f3756604660b86ea805c1252201044655454c0003f303433301e3756604460b66ea805809401ccdc39bad305d305e305e305e305e305a37540246eb4c174c168dd500819b8f375c60b860ba60ba60ba60b26ea8044010cdc79bae30193058375402000866e240e0c8cdc018009bad301e3058375402060026eb4c07cc160dd50081299982a99b88001480004c0cc0044004cdd79ba601f374c64646466660026666002a6660ac606490000a5eb7bdb1804c8c8cc0040052f5bded8c044a6660ba0022660bc66ec0dd48131ba60034bd6f7b630099191919299982e98049980501500109983119bb037520546e9801c01454ccc174cdc781500109983119bb037520546e9801c00c4cc188cdd81ba9002374c0026600c00c0066eacc17c00cdd7182e8011830801182f8009919800800a5eb7bdb180894ccc1700044cc174cdd81ba90074c010101004bd6f7b630099191919299982e18041980480580109983099bb037520169810101000051533305c3371e0160042660c266ec0dd4805a61010100003133061337606ea4008dd4000998030030019bad305e003375c60b800460c000460bc0020460089001023245044655454c0003c22225333059303200110041323233001001006225333060001133061337606ea4018dd3001a5eb7bdb1804c8c8c8c94ccc180c030cc0340280084cc194cdd81ba900a374c00e00a2a6660c066e3c0280084c94ccc184c0e8c18cdd500089983319bb0375201660ce60c86ea80040104010c94ccc1854ccc1940045288a5014c0103d87a80001303e33066374c00297ae03233001001002225333066001133067337606ea402cdd400525eb7bdb1804c8c8c8c94ccc198c048cc04c03c0084cc1accdd81ba900f375001c00a2a6660cc66e3c03c0084c94ccc19cc100c1a4dd500089983619bb0375202060da60d46ea80040104010c94ccc19cc1000045300103d87a8000130443306c375000297ae03370000201c2660d666ec0dd48011ba800133006006003375a60d00066eb8c198008c1a8008c1a00044cc194cdd81ba9002374c0026600c00c0066eacc18800cdd7183000118320011831000991900119198008008011129998300008a4c264a6660c200229309919299982f981c18309baa3300c375c60c260ca0086eb8c1840084cc014014cc19000800454cc1812401326b65797320696e206173736f63696174697665206c697374206172656e277420696e20617363656e64696e67206f7264657200163065002306300130630013305e337606ea4008dd4000a5eb7bdb180dd7a60103d879800022533305533720004002298103d8798000153330553371e0040022980103d87a800014c103d87b8000330024890550494c4f540030033004375a603660aa6ea804ccc005220104534849500030023003375a603460a86ea804888cdc500100091b9800123732660046ea00052201003001001222533333305700213232323232323300b0020013371491010128000025333053337100069007099b80483c80400c54ccc14ccdc4001a410004266e00cdc0241002800690068a9982a24929576861742061726520796f7520646f696e673f204e6f2049206d65616e2c20736572696f75736c792e001653330560011337149101035b5d2900004133714911035b5f2000375c60aa66600e00266ec1300102415d00375266e292210129000042233760980103422c2000375266601001000466e28dd7182b0009bae3057001375860a80046eb4c148004c8cdd81ba83052001374e60a60026ea80084c94ccc1500044cdc5245027b7d00002133714911037b5f2000375c60a664646600200200644a6660ae00220062664466ec130103422c2000375266601201260ae00466e29221023a20003330090093058002337146eb8c15c004dd7182c000982c80099801001182d00099bb04c10342207d0037520046eac0084c94ccc1500044cdc52441025b5d00002133714911035b5f2000375c60a666600a00266ec1300102415d0037520044466ec1300103422c2000375266600c00c00466e28dd7182a0009bae3055001375800426600a6eb40080044c8c8cdc524410268270000132333001001337006e3400920013371491101270000322253330533371000490000800899191919980300319b8000548004cdc599b80002533305633710004900a0a40c02903719b8b33700002a6660ac66e2000520141481805206e0043370c004901019b8300148080cdc70020011bae00222232330010010042253330540011004133003305600133002002305700122323300100100322533304e30270011337149110130000031533304e337100029000099b8a489012d0033002002302c00113300533708002900a19b8b3370066e1400520144818000cc0040048894ccc12ccdc4801240002002266600600666e1000920143371666e00cdc28012402890300008a9982481f0b180818251baa3011304a375402aa66608c603e60906ea80044c94ccc12c00454cc120110584c8c94ccc13400454cc128118584c8c94ccc13c00454cc130120584c8c94ccc14400454cc138128584c8c94ccc14c00454cc140130584c94ccc150c15c008526153305104d16325333333058001153305104d16153305104d16153305104d161375a0022a660a209a2c60aa00260aa00464a6666660ac0022a6609e0962c2a6609e0962c2a6609e0962c2a6609e0962c26eb8004c14c004c14c008c94cccccc15000454cc1341245854cc1341245854cc1341245854cc134124584dd7000982880098288011929999998290008a998258238b0a998258238b0a998258238b09bad001153304b04716304f001304f0023253333330500011533049045161533049045161533049045161375a0022a6609208a2c609a00260926ea800454cc11c10c594cccccc134004400454cc1181085854cc1181085854cc1181085854cc11810858c128c11cdd50008a99822a493165787065637420496e6c696e65446174756d28736869705f646174756d29203d20736869705f73746174652e646174756d00163007304637540022a6608807e2c6090002646600200202644a66608e002297ae0132325333045325333046302230483754002266e3c04cdd7182618249baa00114a0601c60906ea8c038c120dd50010998250011980200200089980200200098258011824800a999820180c98211baa0011325333045001153304203c16132325333047001153304403e161325333048304b002149854cc1140fc58c94cccccc13000454cc1140fc5854cc1140fc5854cc1140fc5854cc1140fc584dd7000982480098248011929999998250008a9982181e8b0a9982181e8b0a9982181e8b09bad001153304303d163047001304337540022a660820762ca66666608e00220022a660800742c2a660800742c2a660800742c2a660800742c608860826ea800454cc0fd2413e65787065637420496e6c696e65446174756d28617374657269615f646174756d29203d20617374657269615f696e7075742e6f75747075742e646174756d0016300130403754600e60806ea80108c10cc110c110004c06cccc004dd59802981f1baa3005303e37540046eb8c010c0f8dd50141bae3005303e375405044464a66607c603460806ea8004520001375a608860826ea8004c94ccc0f8c068c100dd50008a60103d87a8000132330010013756608a60846ea8008894ccc110004530103d87a8000132323253330433371e00e6eb8c11400c4c080cc120dd4000a5eb804cc014014008dd698228011824001182300099804001801181f981e1baa001153303a03116323300100100c22533303e00114c103d87a800013232533303c32533303d3016303f375400229404cdc79bae304330403754002056600a607e6ea8c014c0fcdd51803181f9baa00213019330410024bd70099802002000982100118200009181f0009181e981f000899299981d8008a9981c01a8b099299981e181f8010a99981c19b8748004dd6981d8008a51153303903616153303903616303d001325333037301330393754002297adef6c6013756607a60746ea8004cc00400800c88c8cc00400400c894ccc0f40045300103d87a80001323232533303c3371e00c6eb8c0f800c4c064cc104dd3000a5eb804cc014014008dd5981f0011820801181f800991980080080211299981d0008a5eb7bdb1804c8c8c8c94ccc0e8cdc7a44100002100313303f337606ea4008dd3000998030030019bab303c003375c6074004607c00460780026eb8c0e4c0d8dd50040a9981a24926657870656374204d696e742873686970796172645f706f6c69637929203d20707572706f7365001630383039303930390023756606e002606e606e0046eb0c0d4004c0d4c0d4008dd6181980098179baa303200230313032001302d37540182930a99815a4811856616c696461746f722072657475726e65642066616c7365001365632533302a30030011533302e302d37540042930a998158148b0a99981518030008a99981718169baa002149854cc0ac0a45854cc0ac0a458c0acdd5000a99999981800588058a998148138b0a998148138b0a998148138b0a998148138b0a99814a491d52756e6e696e672033206172672076616c696461746f72207370656e640013323232232322533302f323232323232323232323232323232323232323232325333045301e30473754002264a66608c604460906ea80584c8c94ccc120c084c128dd5000899192999825181318261baa001132323232323232323232323232325323233305a303300d1323232325333062001153305f05016132533306330660021325333060303b30623754002264646464a6660c8608060cc6ea80044c8c94ccc198c108c1a0dd50008991919192999835182198361baa001132323232323232323232323253330765333076305230263301f044230293035307a3754606c60f46ea80045288a9983ba481236d7573745f7370656e645f6f6e655f7363726970745f696e707574203f2046616c73650014a02a6660eca6660ec054294454cc1dd241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660eca6660ec008294454cc1dd2411d6d7573745f686176655f656e6f7567685f6675656c203f2046616c73650014a02a6660eca6660ec00c294454cc1dd2411e6d7573745f726573706563745f6d61785f7370656564203f2046616c73650014a02a6660eca6660ec00a294454cc1dd241206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a02a6660eca6660ec004294454cc1dd241216d7573745f73756274726163745f6675656c5f746f6b656e73203f2046616c73650014a02a6660eca6660ec010294454cc1dd2411c6d7573745f6275726e5f7370656e745f6675656c203f2046616c73650014a02a6660eca6660ec014294454cc1dd241156d7573745f7570646174655f78203f2046616c73650014a02a6660eca6660ec012294454cc1dd241156d7573745f7570646174655f79203f2046616c73650014a02a6660eca6660ec00e294454cc1dd2411f6d7573745f7570646174655f75707065725f626f756e64203f2046616c73650014a02a6660eca6660ec016294454cc1dd241216d7573745f70726573657276655f70696c6f745f746f6b656e203f2046616c73650014a02a6660eca6660ec006294454cc1dd2411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660ec002294454cc1dd24011a6d7573745f686f6c645f335f617373657473203f2046616c73650014a029405280a5014a029405280a5014a029405280a5014a0609e604460486eacc0d0c1e0dd500b99b8733301f3756606660ee6ea80581912201044655454c0033702014018609e66603c6eacc0c8c1d8dd500a81481b19b8900a008301900d32323371266e08dd6983c0011bad30783079001337046eb4c1e0004dd6983c183c801183a1baa02c3073375460ec60e66ea801ccdc39bad307530763076307630763072375401c012602a609800c66e1cdd6981618381baa00c3370006402266e1cdd6981518379baa00b3370006602266e3c0b0dd7183898391839183918371baa00a3330153756605260da6ea8c0a4c1b4dd501102d2441044655454c00153306b4915865787065637420536f6d6528737065656429203d0a20202020202020202020726174696f6e616c2e6e65772864697374616e63652c2074785f6c61746573745f74696d65202d2074785f6561726c696573745f74696d65290016330260023370200600a66e08004140c8cdc0180080698008061299983419b88001480004c1180044004dd6983618349baa001153306705c16302330683754604860d06ea80b8dd6983518339baa001153306505916302130663754604260cc6ea80b0cc0e40041594cccccc1a4004400454cc1881545854cc1881545854cc1881545854cc18815458c198c18cdd50008a998308298b180498311baa00115330600511630640013300602923375e603860c26ea8004c070c184dd5180e98309baa016375a60c460c60046eb4c184004c174dd50170a99982d181b0068991929998300008a9982e8270b09929998309832001099299982f181c98301baa0011323232325333062303b306437540022646464a6660ca608060ce6ea80044c8c8c8c94ccc1a4c114c1acdd5000899191919191919191929998392999839182698111980d820118129818983b1baa303230763754002294454cc1cd2401246d7573745f7370656e645f74776f5f7363726970745f696e70757473203f2046616c73650014a02a6660e4a6660e401e294454cc1cd2411c6d7573745f62655f76616c69645f70656c6c6574203f2046616c73650014a02a6660e4a6660e404c294454cc1cd241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660e4a6660e4010294454cc1cd241216d7573745f686176655f70656c6c65745f706f736974696f6e203f2046616c73650014a02a6660e4a6660e4006294454cc1cd2411c6d7573745f6164645f6675656c5f746f6b656e73203f2046616c73650014a02a6660e4a6660e400e294454cc1cd241206d7573745f6e6f745f6578636565645f6361706163697479203f2046616c73650014a02a6660e4a6660e400a294454cc1cd241206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a02a6660e4a6660e400c294454cc1cd2411b6d7573745f70726573657276655f646174756d203f2046616c73650014a02a6660e4a6660e4008294454cc1cd2411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660e4a6660e4004294454cc1cd2411a6d7573745f686f6c645f335f617373657473203f2046616c73650014a02a6660e4002294454cc1cd24011c6d7573745f6e6f745f6d696e745f746f6b656e73203f2046616c73650014a029405280a5014a029405280a5014a0294052819baf374c603a07698101a000304a301d301f3756605e60e66ea8050cdc399980d1bab302e307237540260be911044655454c003370000c02a60946660326eacc0b4c1c4dd5009012018980a9bad30733070375400a66ebc034110cdc499b80002011055533306a3370e0626eb4c0a0c1b4dd5002099b8702f375a605260da6ea801052819980a1bab3028306c3754605060d86ea8084165221044655454c00153306a05e163026306b3754604c60d66ea80c54ccc19cc100c1a4dd500089929998360008a9983482f8b0991929998370008a998358308b0991929998380008a998368318b0992999838983a0010a4c2a660dc0c82c64a6666660ea0022a660dc0c82c2a660dc0c82c2a660dc0c82c2a660dc0c82c26eb8004c1c8004c1c8008c94cccccc1cc00454cc1b01885854cc1b01885854cc1b0188584dd68008a998360310b183800098380011929999998388008a998350300b0a998350300b0a998350300b09bad001153306a06016306e001306a37540022a660d00bc2ca6666660dc00220022a660ce0ba2c2a660ce0ba2c2a660ce0ba2c2a660ce0ba2c60d660d06ea800454cc1992413c65787065637420496e6c696e65446174756d2870656c6c65745f646174756d29203d2070656c6c65745f696e7075742e6f75747075742e646174756d0016300e30673754604660ce6ea8008c10cccc038dd5981118331baa3022306637540026eb8c084c198dd50281bae3022306637540a060d060ca6ea800454cc18d2401ff65787065637420536f6d652870656c6c65745f696e70757429203d0a202020202020202020206c6973742e66696e64280a202020202020202020202020696e707574732c0a202020202020202020202020666e28696e70757429207b0a20202020202020202020202020207768656e20696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c206973207b0a20202020202020202020202020202020566572696669636174696f6e4b657943726564656e7469616c285f29202d3e2046616c73650a2020202020202020202020202020202053637269707443726564656e7469616c28616464725f7061796d656e6b7429202d3e0a202020202020202020202020202020202020616464725f7061796d656e74203d3d2070656c6c65745f76616c696461746f725f616464726573730a20202020202020202020202020207d0a2020202020202020202020207d2c0a202020202020202020202900163301b02f2325333063303c3065375400229404cdc79bae3069306637540020a6604060ca6ea8c080c194dd5181098329baa00133037001054533333306700110011533060053161533060053161533060053161533060053163064306137540022a660be0a22c600e60c06ea800454cc17813c58c188004cc01009c8cdd7980d182f9baa001301a305f3754603660be6ea8050dd69830182e9baa02e1533305a303500d132533305b3034305d375400226464a6660ba607260be6ea80044c8c8c8c94ccc1854ccc184c0f0c044cc0280bc8c050c080c194dd5181098329baa00114a22a660c49201246d7573745f7370656e645f74776f5f7363726970745f696e70757473203f2046616c73650014a02a6660c2a6660c200c294454cc1892411d6d7573745f62655f76616c69645f61737465726961203f2046616c73650014a02a6660c2a6660c202a294454cc189241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660c2a6660c2008294454cc189241226d7573745f686176655f617374657269615f706f736974696f6e203f2046616c73650014a02a6660c2a6660c2006294454cc1892411c6d7573745f6275726e5f736869705f746f6b656e203f2046616c73650014a02a6660c2a6660c2002294454cc1892411d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a02a6660c2004294454cc1892401206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a029405280a5014a029405281803981f1998059bab301f30633754603e60c66ea80601412201044655454c003007375a60ca60c46ea800ccdc4199804980501400a010a400066ebcdd31983119bb037500486ea00892f5bded8c06e98cc1892f7b6301010000010100004bd6f7b6300a9982f0290b180d182f9baa301a305f375404a607666600c6eacc068c178dd5180d182f1baa3061305e37540026eb8c064c178dd50241bae301a305e37540902a660b80a62c66028050464a6660b8606a60bc6ea8004528099b8f375c60c460be6ea8004128c064c178dd5180c982f1baa301a305e375400226464a6660b8a6660b8607060186600a0544601e603660c06ea8c070c180dd50008a51153305d491236d7573745f7370656e645f6f6e655f7363726970745f696e707574203f2046616c73650014a02a6660b8a6660b8020294454cc175241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660b8a6660b8004294454cc1752411c6d7573745f6275726e5f736869705f746f6b656e203f2046616c73650014a02a6660b8002294454cc17524011d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a029405280a50300230393330063756603460bc6ea8c068c178dd5009825a441044655454c003371066600a600c04802003a90001b8733300430050230494881044655454c00371203044646600200200644a6660be002297ae013232533305d300500213306200233004004001133004004001306300230610012305d305e305e0012223253330593035305b37540022900009bad305f305c375400264a6660b2606a60b66ea80045300103d87a800013233001001375660c060ba6ea8008894ccc17c004530103d87a80001323232533305e3371e00e6eb8c18000c4c0eccc18cdd4000a5eb804cc014014008dd6983000118318011830800998068018011191980080080111299982d8008a5eb7bdb1804c8c8c8c94ccc16ccdc7a441000021003133060337606ea4008dd3000998030030019bab305d003375c60b600460be00460ba002600200244a6660b0002290000981999801001182d8009191980080080111299982c0008a5eb804c8ccc888c8cc00400400c894ccc178004400c4c8cc180dd3998301ba90063306037526eb8c174004cc180dd41bad305e0014bd7019801801983100118300009bae3057001375660b00026600600660b800460b4002600200244a6660aa002290000981819801001182c00092999827981418289baa300d30523754002294052898279baa021533304c3025304e37546600c03446466002002646600200264a6660a0605860a46ea800452f5bded8c026eacc158c14cdd5000998021bab300e30523754601c60a46ea800c014894ccc15000452f5c02660aa60a460ac0026600400460ae00244a6660a600229404c94ccc140cdc79bae305600201114a226600600600260ac00229445281119198008008019129998298008a60103d87a8000132323253330523371e00c6eb8c15000c4c0bccc15cdd3000a5eb804cc014014008dd5982a001182b801182a8009bae3050304d37540022a660969215d6578706563742053637269707443726564656e7469616c2873686970796172645f706f6c69637929203d0a202020202020736869705f696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c00163007304c3754600e60986ea8c020c130dd5000982718259baa001153304949013665787065637420536f6d6528736869705f696e70757429203d2066696e645f696e70757428696e707574732c20736869705f726566290016323300201623375e600e60986ea8004008c134c128dd500b9119198008008019129998270008a60103d87a800013232533304c300500213029330510024bd70099802002000982900118280008a99823a48120657870656374205370656e6428736869705f72656629203d20707572706f73650016304b304837540022a6608c92015865787065637420536f6d65286d61785f73706565645f726174696f6e616c29203d0a202020202020726174696f6e616c2e6e6577286d61785f73706565642e64697374616e63652c206d61785f73706565642e74696d6529001633001375a6004608e6ea80c0dd6980198239baa030225333045301e00114c103d87a80001533304533710002900009811198251811198251ba830230023304a3750604600297ae04bd7009811198251811198251ba80023304a375000297ae04bd70118248009182418248009bad30463047002375c608a002608a0046eb8c10c004c10c008dd6982080098208011bad303f001303b3754020607a607c607c607c0046eacc0f0004c0f0c0f0008dd6181d000981d181d0011bac303800130343754606e004606c606e00260646ea8004526153303049011856616c696461746f722072657475726e65642066616c7365001365632533302e30070011325333033001153303002816132325333035001153303202a1613253330363039002149854cc0cc0ac58c94cccccc0e800454cc0cc0ac5854cc0cc0ac5854cc0cc0ac584dd68008a998198158b181b800981b80119299999981c0008a998188148b0a998188148b0a998188148b09bad0011533031029163035001303137540042a66605c6014002264a6660660022a660600502c264a666068606e0042930a998188148b19299999981c0008a998188148b0a998188148b0a998188148b09bad0011533031029163035001303137540042a66605c60120022a66606460626ea8008526153302f027161533302e300800115333032303137540042930a998178138b0a998178138b18179baa00153333330340011001153302d02516153302d02516153302d02516153302d025163300100202422533302b3004302d3754004264a6660600022a6605a0042c26464a6660640022a6605e0082c26464a6660680022a6606200c2c26464a66606c0022a660660102c26464a6660700022a6606a0142c264a66607260780042930a9981b0058b19299999981e8008a9981b0058b0a9981b0058b0a9981b0058b09bad001153303600b16303a001303a00232533333303b0011533034009161533034009161533034009161533034009161375c0026070002607000464a6666660720022a6606400e2c2a6606400e2c2a6606400e2c2a6606400e2c26eb8004c0d8004c0d8008c94cccccc0dc00454cc0c00145854cc0c00145854cc0c0014584dd68008a998180028b181a000981a00119299999981a8008a998170018b0a998170018b0a998170018b09bad001153302e003163032001302e37540042a660580022ca66666606001620162a660520442c2a660520442c2a660520442c2a660520442c605c60566ea8028dc3a40006e1d2006370e90021b8748008dd2a40006e052000370090011b884800054cc0840045854cc0840045854cc0840045854cc08400459240191496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e00375a0026eb4004dd68009bad001375c0026eb800524196657870656374205b736869705f6f75747075745d203d0a202020202020202020206c6973742e66696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d20736869705f696e7075742e6f75747075742e61646472657373207d2c0a20202020202020202020290049013965787065637420496e6c696e65446174756d28736869705f6f75747075745f646174756d29203d20736869705f6f75747075742e646174756d0049013765787065637420736869705f6f75747075745f646174756d3a2053686970446174756d203d20736869705f6f75747075745f646174756d004901476578706563742046696e6974652874785f6561726c696573745f74696d6529203d2076616c69646974795f72616e67652e6c6f7765725f626f756e642e626f756e645f74797065004901456578706563742046696e6974652874785f6c61746573745f74696d6529203d2076616c69646974795f72616e67652e75707065725f626f756e642e626f756e645f747970650049012f6578706563742070656c6c65745f646174756d3a2050656c6c6574446174756d203d2070656c6c65745f646174756d004901ff65787065637420536f6d6528617374657269615f696e70757429203d0a202020202020202020206c6973742e66696e64280a202020202020202020202020696e707574732c0a202020202020202020202020666e28696e70757429207b0a20202020202020202020202020207768656e20696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c206973207b0a20202020202020202020202020202020566572696669636174696f6e4b657943726564656e7469616c285f29202d3e2046616c73650a2020202020202020202020202020202053637269707443726564656e7469616c28616464725f7061796d656d6e7429202d3e0a202020202020202020202020202020202020616464725f7061796d656e74203d3d20617374657269615f76616c696461746f725f616464726573730a20202020202020202020202020207d0a2020202020202020202020207d2c0a20202020202020202020290049011672656465656d65723a205368697052656465656d657200490110646174756d3a2053686970446174756d0049013265787065637420617374657269615f646174756d3a2041737465726961446174756d203d20617374657269615f646174756d00490159657870656374205b736869705f73746174655d203d0a202020202020202020207472616e73616374696f6e2e66696e645f7363726970745f6f757470757473286f7574707574732c2073686970796172645f706f6c696379290049012965787065637420736869705f646174756d3a2053686970446174756d203d20736869705f646174756d00490120657870656374205b285f2c202d31295d203d206d696e7465645f746f6b656e730049011a72656465656d65723a20536869707961726452656465656d6572005734ae7155ceaab9e5573eae815d0aba257489811e581c6a25ad5476105ac4a3784769cb93f92fd67a11932ef9a65a61abd1d6004c011e581cbac1753d5f7e3609c92776371fd0eafa753889e5712858f48fb83981004c012fd8799f581c516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d284c6173746572696141646d696eff004c0108d8799f01197530ff004c01021864004c010101004c0102181e004c01010a0001 \ No newline at end of file From 39a11fa24f439f7bd2852eaa1e9920294ca006c0 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Thu, 13 Nov 2025 04:34:43 -0300 Subject: [PATCH 15/20] add command for applying custom params to scripts --- Cargo.lock | 2 + game/Cargo.toml | 2 + game/src/deploy_params.json | 14 +++ game/src/game.rs | 167 ++++++++++++++++++++++++++++++++++-- game/src/lib.rs | 18 ++++ 5 files changed, 198 insertions(+), 5 deletions(-) create mode 100644 game/src/deploy_params.json diff --git a/Cargo.lock b/Cargo.lock index b0b0d84..1129ad1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3335,6 +3335,8 @@ dependencies = [ "parity-scale-codec", "sc-cli", "sc-keystore", + "serde", + "serde_json", "sled", "sp-core", "sp-runtime", diff --git a/game/Cargo.toml b/game/Cargo.toml index c725625..fd4c41f 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -16,6 +16,8 @@ log = { workspace = true } parity-scale-codec = { workspace = true } sc-cli = { workspace = true } sc-keystore = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } sp-core ={ workspace = true } sp-runtime ={ workspace = true } diff --git a/game/src/deploy_params.json b/game/src/deploy_params.json new file mode 100644 index 0000000..341d622 --- /dev/null +++ b/game/src/deploy_params.json @@ -0,0 +1,14 @@ +{ + "admin_policy": "516238dd0a79bac4bebe041c44bad8bf880d74720733d2fc0d255d28", + "admin_name": "asteriaAdmin", + "fuel_per_step": 1, + "initial_fuel": 30, + "max_speed": { + "distance": 1, + "time": 30000 + }, + "max_ship_fuel": 100, + "max_asteria_mining": 50, + "min_asteria_distance": 10, + "ship_mint_lovelace_fee": 3000000 +} diff --git a/game/src/game.rs b/game/src/game.rs index cd583ab..7772618 100644 --- a/game/src/game.rs +++ b/game/src/game.rs @@ -1,4 +1,4 @@ -use crate::{CreateShipArgs, GatherFuelArgs, MineAsteriaArgs, MoveShipArgs}; +use crate::{CreateShipArgs, DeployScriptsArgs, GatherFuelArgs, MineAsteriaArgs, MoveShipArgs}; use anyhow::anyhow; use griffin_core::{ checks_interface::{babbage_minted_tx_from_cbor, babbage_tx_to_cbor}, @@ -8,16 +8,19 @@ use griffin_core::{ utils::{Int, MaybeIndefArray::Indef}, }, pallas_crypto::hash::Hash as PallasHash, - pallas_primitives::babbage::{ - BigInt, BoundedBytes, Constr, MintedTx, PlutusData as PallasPlutusData, - Tx as PallasTransaction, + pallas_primitives::{ + babbage::{ + BigInt, BoundedBytes, Constr, MintedTx, PlutusData as PallasPlutusData, + Tx as PallasTransaction, + }, + Fragment, }, pallas_traverse::OriginalHash, types::{ compute_plutus_v2_script_hash, Address, AssetName, Coin, Datum, Input, Multiasset, Output, PlutusData, PlutusScript, PolicyId, Redeemer, RedeemerTag, Transaction, VKeyWitness, Value, }, - uplc::tx::SlotConfig, + uplc::tx::{apply_params_to_script, SlotConfig}, }; use griffin_wallet::{ cli::{ShowOutputsAtArgs, ShowOutputsWithAssetArgs}, @@ -26,6 +29,7 @@ use griffin_wallet::{ use jsonrpsee::{core::client::ClientT, http_client::HttpClient, rpc_params}; use parity_scale_codec::Encode; use sc_keystore::LocalKeystore; +use serde::{Deserialize, Serialize}; use sled::Db; use sp_core::ed25519::Public; use sp_runtime::traits::{BlakeTwo256, Hash}; @@ -893,6 +897,140 @@ pub async fn mine_asteria( } } +pub async fn deploy_scripts(args: DeployScriptsArgs) -> anyhow::Result<()> { + log::debug!("The args are:: {:?}", args); + + let params_json: String = std::fs::read_to_string(args.params)?; + let params: ScriptsParams = + serde_json::from_str(¶ms_json).map_err(|e| anyhow!("Invalid params JSON: {}", e))?; + + let asteria_params = PallasPlutusData::Array(Indef( + [ + PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef( + [ + PallasPlutusData::BoundedBytes(BoundedBytes( + hex::decode(params.admin_policy.clone()).unwrap(), + )), + PallasPlutusData::BoundedBytes(BoundedBytes( + params.admin_name.clone().into(), + )), + ] + .to_vec(), + ), + }), + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + params.ship_mint_lovelace_fee, + )))), + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + params.max_asteria_mining, + )))), + ] + .to_vec(), + )); + + let asteria_script = PlutusScript( + apply_params_to_script( + asteria_params.encode_fragment().unwrap().as_slice(), + hex::decode(ASTERIA_PARAMETERIZED).unwrap().as_slice(), + ) + .unwrap(), + ); + let asteria_hash: PolicyId = compute_plutus_v2_script_hash(asteria_script.clone()); + + let pellet_params = PallasPlutusData::Array(Indef( + [PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef( + [ + PallasPlutusData::BoundedBytes(BoundedBytes( + hex::decode(params.admin_policy.clone()).unwrap(), + )), + PallasPlutusData::BoundedBytes(BoundedBytes(params.admin_name.clone().into())), + ] + .to_vec(), + ), + })] + .to_vec(), + )); + + let pellet_script = PlutusScript( + apply_params_to_script( + pellet_params.encode_fragment().unwrap().as_slice(), + hex::decode(PELLET_PARAMETERIZED).unwrap().as_slice(), + ) + .unwrap(), + ); + let pellet_hash: PolicyId = compute_plutus_v2_script_hash(pellet_script.clone()); + + let spacetime_params = PallasPlutusData::Array(Indef( + [ + PallasPlutusData::BoundedBytes(BoundedBytes(pellet_hash.0.to_vec())), + PallasPlutusData::BoundedBytes(BoundedBytes(asteria_hash.0.to_vec())), + PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef( + [ + PallasPlutusData::BoundedBytes(BoundedBytes( + hex::decode(params.admin_policy.clone()).unwrap(), + )), + PallasPlutusData::BoundedBytes(BoundedBytes( + params.admin_name.clone().into(), + )), + ] + .to_vec(), + ), + }), + PallasPlutusData::Constr(Constr { + tag: 121, + any_constructor: None, + fields: Indef( + [ + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + params.max_speed.distance, + )))), + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + params.max_speed.time, + )))), + ] + .to_vec(), + ), + }), + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + params.max_ship_fuel, + )))), + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + params.fuel_per_step, + )))), + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + params.initial_fuel, + )))), + PallasPlutusData::BigInt(BigInt::Int(Int(minicbor::data::Int::from( + params.min_asteria_distance, + )))), + ] + .to_vec(), + )); + + let spacetime_script = PlutusScript( + apply_params_to_script( + spacetime_params.encode_fragment().unwrap().as_slice(), + hex::decode(SPACETIME_PARAMETERIZED).unwrap().as_slice(), + ) + .unwrap(), + ); + + std::fs::write(PELLET_PATH, hex::encode(pellet_script.0)).unwrap(); + std::fs::write(ASTERIA_PATH, hex::encode(asteria_script.0)).unwrap(); + std::fs::write(SPACETIME_PATH, hex::encode(spacetime_script.0)).unwrap(); + println!("All scripts written successfully!"); + Ok(()) +} + fn quanity_of(value: &Value, policy: &PolicyId, name: &AssetName) -> u64 { if let Value::Multiasset(_, ma) = value { if let Some(assets) = ma.0.get(policy) { @@ -911,6 +1049,25 @@ fn coin_of(value: &Value) -> u64 { } } +#[derive(Serialize, Deserialize, Debug, Clone)] +struct ScriptsParams { + admin_policy: String, + admin_name: String, + fuel_per_step: u64, + initial_fuel: u64, + max_speed: Speed, + max_ship_fuel: u64, + max_asteria_mining: u64, + min_asteria_distance: u64, + ship_mint_lovelace_fee: u64, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +struct Speed { + distance: u64, + time: u64, +} + #[derive(Debug, PartialEq, Eq, Clone)] pub enum AsteriaDatum { Ok { diff --git a/game/src/lib.rs b/game/src/lib.rs index 9bddec2..2ae4f89 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -21,6 +21,8 @@ pub enum Command { MoveShip(MoveShipArgs), /// Mine Asteria using a ship MineAsteria(MineAsteriaArgs), + /// Apply parameters and write game scripts + DeployScripts(DeployScriptsArgs), } impl GameCommand { @@ -51,6 +53,10 @@ impl GameCommand { let _ = game::mine_asteria(&db, &client, &keystore, args).await; Ok(()) } + Command::DeployScripts(args) => { + let _ = game::deploy_scripts(args).await; + Ok(()) + } }, None => { log::info!(" Asteria game"); @@ -199,3 +205,15 @@ pub struct MineAsteriaArgs { )] pub validity_interval_start: u64, } + +#[derive(Debug, Args, Clone)] +pub struct DeployScriptsArgs { + #[arg( + long, + short, + verbatim_doc_comment, + required = true, + value_name = "SCRIPTS_PARAMS_PATH" + )] + pub params: String, +} From dc55b9436f8826b2fa31a3b0bcc243ee2f204783 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Thu, 13 Nov 2025 17:27:32 -0300 Subject: [PATCH 16/20] add game README --- README.md | 4 +- game/README.md | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 game/README.md diff --git a/README.md b/README.md index 9514131..080c78e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ This repository will contain a reference implementation of a Substrate partnerch - [Start a chain with docker](#build-and-run-with-docker) -- [Use-case: Asteria game]() +- [Use-case: Asteria game](#use-case-asteria-game) - [Setting up a partner chain](#setting-up-a-partner-chain) @@ -92,7 +92,7 @@ Make sure that the endpoint you are connecting to matches the node's being run i ## Use-case: Asteria game As the result of the discovery process, after surveying many developers, it was decided that the use case for the partnerchain reference implementation would be a game. We chose the game Asteria which consists of ships moving across a board to find the Asteria prize and collect a portion of it. -In this repository we include the [on-chain code](./game/onchain/), which comes with a [design document](./game/onchain/docs/design/design.md) that thoroughly explains the transactions involved in the game. +In this repository we include the [on-chain code](./game/onchain/), which comes with a [design document](./game/onchain/docs/design/design.md) that thoroughly explains the transactions involved in the game. In the game [src](./game/src/) you can find the implementation of the commands necessary to play the game and [detailed instructions](./game/README.md) on how to run them. ## Setting up a Partner Chain diff --git a/game/README.md b/game/README.md new file mode 100644 index 0000000..1d8949d --- /dev/null +++ b/game/README.md @@ -0,0 +1,107 @@ +# Game: Asteria + +As part of the discovery process, it was decided that the use case for the partnerchain reference implementation would be a game. We decided on implementing Asteria which is a simple game about that showcases the capabilities of the eUTxO model. +The game consists of ships moving across a two-dimension grid to find the Asteria, which holds a prize pool that the players can redeem a portion of. In the grid there are also pellets that hold fuel for the ships to collect. The operations of the game are: create a ship, move a ship, gather fuel and mine asteria. + +The game is implemented through commands that build the transactions for each operation. A more in depth explanation of the game can be found in the [design document](./onchain/docs/design/design.md). + +## Game usage + +Each of the following actions must be run with a running instance of the node. + +### Deploy Scripts + +This command reads all the script parameters from `game/src/deploy_params.json` and applies them to the generic (parameterized) +scripts, writing the resulting ones in their respective files, inside the `scripts` directory. + +```console +./target/release/griffin-partner-chains-node game deploy-scripts +--params +``` + +#### Arguments details: + +*params*: path to the json file containing all the script parameters. + +### Create Ship + +This command creates the player’s Ship. The transaction also mints the initial ship’s fuel, the ship and pilot tokens, and pays an inscription fee that is added to the total prize in the Asteria UTxO. The pilot token goes back to the wallet input owner, and serves as a proof of the ownership of the Ship. + +```console +./target/release/griffin-partner-chains-node game create-ship +--input +--witness +--pos-x +--pos-y +--ttl +``` +#### Arguments details: + +- *input*: a wallet input that must be consumed to pay for the minimal amount of coin in the Ship output and the fee added to the Asteria accumulated rewards. +- *witness*: public key of the input owner. If omitted, Shawn’s pub key is the default value, since this makes it easier to test transactions in a `dev` environment. +- *pos-x*: initial “x” coordinate of the Ship output. +- *pos-y*: initial “y” coordinate of the Ship output. +- *ttl*: the transaction’s time-to-live. The resulting POSIX time of the validity interval is used to set the initial `last-move-latest-time` field in the Ship output datum. + +### Gather Fuel + +This command moves fuel tokens from a pellet UTxO to a ship UTxO, only if they have the same position in the grid, as specified in the datums. The amount of fuel to gather is specified in the redeemer, and the total ship fuel must not exceed its maximum capacity. + +```console +./target/release/griffin-partner-chains-node game gather-fuel +--ship +--pellet +--witness +--fuel +--validity-interval-start +``` + +#### Arguments details: + +- *ship*: reference to the ship UTxO. +- *pellet*: reference to the pellet UTxO. +- *witness*: public key of the pilot token owner. This is necessary since the pilot UTxO must be provided as input to prove the ship ownership. If omitted, Shawn’s pub key is the default value. +- *fuel*: the amount of fuel to transfer from the pellet to the ship. +- *validity-interval-start*: start of the transaction’s validity interval. The corresponding POSIX must be greater than the `last-move-latest-time` field in the ship datum, in order to respect the speed limit of the last move. + +### Move Ship + +This command moves the ship to a different point in the grid (updates de `pos_x` and `pos_y` fields in the ship datum). The transaction also burns the fuel tokens consumed. + +```console +./target/release/griffin-partner-chains-node game move-ship +--ship +--witness +--pos-x +--pos-y +--validity-interval-start +--ttl +``` + +#### Arguments details: + +- *ship*: reference to the ship UTxO. +witness: public key of the pilot token owner. This is necessary since the pilot UTxO must be provided as input to prove the ship ownership. If omitted, Shawn’s pub key is the default value. +- *pos-x*: new “x” coordinate of the ship. +- *pos-y*: new “y” coordinate of the ship. +- *validity-interval-start*: start of the transaction’s validity interval. The corresponding POSIX must be greater than the `last-move-latest-time` field in the ship datum, in order to respect the speed limit of the last move. +- *ttl*: the transaction’s time-to-live. The resulting POSIX time of the validity interval is used to set the initial `last-move-latest-time` field in the Ship output datum. The manhattan distance travelled divided by the POSIX validity range must be less or equal to the max speed. + +### Mine Asteria + +This command can be triggered when the ship reaches Asteria, i.e., its coordinates are both zero. Then the ship owner can receive a percentage of the total prize given by (MAX_ASTERIA_MINING/100). This transaction also burns the ship and all remaining fuel tokens. + +```console +./target/release/griffin-partner-chains-node game mine-asteria +--ship +--witness +--validity-interval-start +``` + +#### Arguments details: + +- *ship*: reference to the ship UTxO. +- *witness*: public key of the pilot token owner. This is necessary since the pilot UTxO must be provided as input to prove the ship ownership. If omitted, Shawn’s pub key is the default value. +- *validity-interval-start*: start of the transaction’s validity interval. The corresponding POSIX must be greater than the `last-move-latest-time` field in the ship datum, in order to respect the speed limit of the last move. + + From 7c0e088214dd4c9b988682b2c2da5b8e8eb7a5f4 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Thu, 13 Nov 2025 17:28:34 -0300 Subject: [PATCH 17/20] fix underflow issue with griffin values --- griffin-core/src/types.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/griffin-core/src/types.rs b/griffin-core/src/types.rs index 00c2bff..259c9a7 100644 --- a/griffin-core/src/types.rs +++ b/griffin-core/src/types.rs @@ -857,18 +857,18 @@ impl + Clone> Sub for EncapBTree { impl Sub for Value { type Output = Self; - /// Coordinate-wise subtraction of `Value`s + /// Coordinate-wise subtraction of Values fn sub(self, other: Self) -> Self { use Value::*; match self { Coin(c) => match other { - Coin(d) => Coin(c - d), - Multiasset(d, ma) => Multiasset(c - d, ma), + Coin(d) => Coin(c.saturating_sub(d)), + Multiasset(d, ma) => Multiasset(c.saturating_sub(d), ma), }, Multiasset(c, ma) => match other { - Coin(d) => Multiasset(c - d, ma), - Multiasset(d, mb) => Multiasset(c - d, ma - mb), + Coin(d) => Multiasset(c.saturating_sub(d), ma), + Multiasset(d, mb) => Multiasset(c.saturating_sub(d), ma - mb), }, } .normalize() From 6db9ae7c153bda78b9ebca8bbf18c43afd54b4d7 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Thu, 13 Nov 2025 17:31:12 -0300 Subject: [PATCH 18/20] remove initial ship UTxOs in genesis --- runtime/src/genesis.rs | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/runtime/src/genesis.rs b/runtime/src/genesis.rs index 4d01854..c96aab4 100644 --- a/runtime/src/genesis.rs +++ b/runtime/src/genesis.rs @@ -21,10 +21,6 @@ pub const GENESIS_DEFAULT_JSON: &str = r#" { "policy": "0298aa99f95e2fe0a0132a6bb794261fb7e7b0d988215da2f2de2005", "assets": [ ["tokenA", 271000000], ["tokenB", 1123581321] ] - }, - { - "policy": "7ba97fb6e48018ef131dd08916939350c0ce7050534f8e51b5e0e3a4", - "assets": [ ["PILOT0", 1], ["PILOT1", 1] ] } ], "datum": "820080" @@ -38,37 +34,7 @@ pub const GENESIS_DEFAULT_JSON: &str = r#" "assets": [ ["asteriaAdmin", 1] ] } ], - "datum": "D8799F02581C7BA97FB6E48018EF131DD08916939350C0CE7050534F8E51B5E0E3A4FF" - }, - { - "address": "707ba97fb6e48018ef131dd08916939350c0ce7050534f8e51b5e0e3a4", - "coin": 314150000, - "value": [ - { - "policy": "6a25ad5476105ac4a3784769cb93f92fd67a11932ef9a65a61abd1d6", - "assets": [ ["FUEL", 30] ] - }, - { - "policy": "7ba97fb6e48018ef131dd08916939350c0ce7050534f8e51b5e0e3a4", - "assets": [ ["SHIP0", 1] ] - } - ], - "datum": "D8799F27034553484950304650494C4F54301B0000018AE4FFE838FF" - }, - { - "address": "707ba97fb6e48018ef131dd08916939350c0ce7050534f8e51b5e0e3a4", - "coin": 2000, - "value": [ - { - "policy": "6a25ad5476105ac4a3784769cb93f92fd67a11932ef9a65a61abd1d6", - "assets": [ ["FUEL", 25] ] - }, - { - "policy": "7ba97fb6e48018ef131dd08916939350c0ce7050534f8e51b5e0e3a4", - "assets": [ ["SHIP1", 1] ] - } - ], - "datum": "D8799F00004553484950314650494C4F54311B00000196C625FAE0FF" + "datum": "D8799F00581C7BA97FB6E48018EF131DD08916939350C0CE7050534F8E51B5E0E3A4FF" }, { "address": "706a25ad5476105ac4a3784769cb93f92fd67a11932ef9a65a61abd1d6", From bd7c8e8b5b5c0df1095f679654f9f4a8246357b4 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Thu, 13 Nov 2025 17:44:12 -0300 Subject: [PATCH 19/20] set params path and add `mine_coin_amount` arg to `mine-asteria` --- game/src/game.rs | 16 +++++++--------- game/src/lib.rs | 13 +++++-------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/game/src/game.rs b/game/src/game.rs index 7772618..f5ce9b1 100644 --- a/game/src/game.rs +++ b/game/src/game.rs @@ -1,4 +1,4 @@ -use crate::{CreateShipArgs, DeployScriptsArgs, GatherFuelArgs, MineAsteriaArgs, MoveShipArgs}; +use crate::{CreateShipArgs, GatherFuelArgs, MineAsteriaArgs, MoveShipArgs}; use anyhow::anyhow; use griffin_core::{ checks_interface::{babbage_minted_tx_from_cbor, babbage_tx_to_cbor}, @@ -17,7 +17,7 @@ use griffin_core::{ }, pallas_traverse::OriginalHash, types::{ - compute_plutus_v2_script_hash, Address, AssetName, Coin, Datum, Input, Multiasset, Output, + compute_plutus_v2_script_hash, Address, AssetName, Datum, Input, Multiasset, Output, PlutusData, PlutusScript, PolicyId, Redeemer, RedeemerTag, Transaction, VKeyWitness, Value, }, uplc::tx::{apply_params_to_script, SlotConfig}, @@ -44,6 +44,7 @@ const PELLET_PARAMETERIZED: &str = "590d2701000032323232323232323232323232322223 const ASTERIA_PATH: &str = "game/src/scripts/asteria.txt"; const SPACETIME_PATH: &str = "game/src/scripts/spacetime.txt"; const PELLET_PATH: &str = "game/src/scripts/pellet.txt"; +const DEPLOY_PARAMS_PATH: &str = "game/src/deploy_params.json"; pub async fn create_ship( db: &Db, @@ -706,7 +707,6 @@ pub async fn mine_asteria( ))?; } let asteria = &asterias[0]; - let rewards = coin_of(&asteria.value) * MAX_ASTERIA_MINING / 100; let (_spacetime_address, ship_value, ship_datum) = sync::get_unspent(db, &args.ship)?.expect("Ship UTxO not found"); @@ -818,13 +818,13 @@ pub async fn mine_asteria( Output { address: pilot_utxo.address.clone(), value: pilot_utxo.value.clone() - + Value::Coin(rewards) + + Value::Coin(args.mine_coin_amount) + Value::Coin(coin_of(&ship_value)), datum_option: pilot_utxo.datum_option.clone(), }, Output { address: asteria.address.clone(), - value: asteria.value.clone() - Value::Coin(rewards), + value: asteria.value.clone() - Value::Coin(args.mine_coin_amount), datum_option: asteria.datum_option.clone(), }, ]; @@ -897,10 +897,8 @@ pub async fn mine_asteria( } } -pub async fn deploy_scripts(args: DeployScriptsArgs) -> anyhow::Result<()> { - log::debug!("The args are:: {:?}", args); - - let params_json: String = std::fs::read_to_string(args.params)?; +pub async fn deploy_scripts() -> anyhow::Result<()> { + let params_json: String = std::fs::read_to_string(DEPLOY_PARAMS_PATH)?; let params: ScriptsParams = serde_json::from_str(¶ms_json).map_err(|e| anyhow!("Invalid params JSON: {}", e))?; diff --git a/game/src/lib.rs b/game/src/lib.rs index 2ae4f89..f134580 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -22,7 +22,7 @@ pub enum Command { /// Mine Asteria using a ship MineAsteria(MineAsteriaArgs), /// Apply parameters and write game scripts - DeployScripts(DeployScriptsArgs), + DeployScripts, } impl GameCommand { @@ -53,8 +53,8 @@ impl GameCommand { let _ = game::mine_asteria(&db, &client, &keystore, args).await; Ok(()) } - Command::DeployScripts(args) => { - let _ = game::deploy_scripts(args).await; + Command::DeployScripts => { + let _ = game::deploy_scripts().await; Ok(()) } }, @@ -204,16 +204,13 @@ pub struct MineAsteriaArgs { value_name = "VALIDITY_INTERVAL_START" )] pub validity_interval_start: u64, -} -#[derive(Debug, Args, Clone)] -pub struct DeployScriptsArgs { #[arg( long, short, verbatim_doc_comment, required = true, - value_name = "SCRIPTS_PARAMS_PATH" + value_name = "MINE_COIN_AMOUNT" )] - pub params: String, + pub mine_coin_amount: u64, } From f605f74b109ccdb855bf5d3e8e92a3e2131edad1 Mon Sep 17 00:00:00 2001 From: Francisco Joray Date: Thu, 13 Nov 2025 17:45:08 -0300 Subject: [PATCH 20/20] fix hardcoded fee param in `create-ship` --- game/src/game.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/game/src/game.rs b/game/src/game.rs index f5ce9b1..04aea21 100644 --- a/game/src/game.rs +++ b/game/src/game.rs @@ -34,9 +34,6 @@ use sled::Db; use sp_core::ed25519::Public; use sp_runtime::traits::{BlakeTwo256, Hash}; -const SHIP_FEE: Coin = 3000000; -const MAX_ASTERIA_MINING: u64 = 50; - const ASTERIA_PARAMETERIZED: &str = "590cf901000032323232323232323232323232322232232232323232232323232253330163232323232323232533301e300c3020375400e264646464a666044602a60486ea80044c8c8c8c8c8c8c94ccc0a4c0700184c94ccc0b800454cc0ac094584c94ccc0bcc0c80084c94ccc0b0c064c0b8dd500089919191919192999819299981919baf300b303537540106e98cc894ccc0d0c09c0b040044c8c8cc00400400c894ccc0ec0044cc0f0cdd82601014000374c00697adef6c60132323232533303b3375e66012911000024c103d879800013304033760981014000374c00e00a2a66607666e3d22100002132533303c302f303e375400226608266ec13010140003042303f3754002008200864a666078a66608000229445280a6103d87a80001301d33041374c00297ae03233001001002225333041001133042337609801014000375006a97adef6c6013232323253330413375e6601e911000024c103d879800013304633760981014000375007200a2a66608266e3d22100002132533304230353044375400226608e66ec1301014000304830453754002008200864a666084606a002298103d87a80001302333047375000297ae03370000207226608c66ec0dd48011ba800133006006003375a60860066eb8c104008c114008c10c0044cc100cdd81ba9002374c0026600c00c0066eacc0f400cdd7181d801181f801181e8009919001191980080080111299981d8008a4c264a66607800229309919299981d1816981e1baa33008375c607860800086eb8c0f00084cc014014cc0fc00800454cc0ed2401326b65797320696e206173736f63696174697665206c697374206172656e277420696e20617363656e64696e67206f7264657200163040002303e001303e0013303933760981014000375005897adef6c60225333034337200040022980103d8798000153330343371e0040022980103d87a800014c103d87b800037566016606a6ea8c02cc0d4dd50080a511533033491146d7573745f6164645f666565203f2046616c73650014a02a666064a666064006294454cc0cd2411d6d7573745f686f6c645f61646d696e5f746f6b656e203f2046616c73650014a02a666064a666064004294454cc0cd2411e6d7573745f696e6372656d656e745f636f756e746572203f2046616c73650014a02a666064002294454cc0cd2401256d7573745f70726573657276655f73686970796172645f706f6c696379203f2046616c73650014a029405280a503371e6eb8c028c0d0dd500200a19b87375a602460666ea800ccdc000a2400466e21200033300a3756601060646ea8014dd7180898191baa029375c601060646ea80a4cc0800040ad4cccccc0d4004400454cc0b80a85854cc0b80a85854cc0b80a85854cc0b80a858c0c8c0bcdd50008a998168140b180298171baa001153302c0261630300013300100f23375e6018605a6ea8004c030c0b4dd5180198169baa008132533302a3018007132533302f001153302c0261613253330303033002132533302d301a302f375400226464646464a666064604a60686ea80044c8c8c94ccc0d54ccc0d40145288a9981b24811d6d7573745f696e7075745f736869705f746f6b656e203f2046616c73650014a02a66606aa66606a004294454cc0d92411f6d7573745f726573706563745f6d61785f6d696e696e67203f2046616c73650014a02a66606a002294454cc0d924011b6d7573745f70726573657276655f646174756d203f2046616c73650014a0294052819baf0280063232323371266e08dd6981e0009bad303c303d002337046eb4c0f0008dd6981e181e800981c1baa323230183303c375066e08dd6981e8011bad303d0013303c375066e08dd6981e981f0011bad303d303e0014bd70181c9baa32323232301b3303f375066e04cdc11bad3040004001337046eb4c10000800ccc0fcdd419b820030014bd701bad303f3040001303b3754607c60766ea801cdd6981e981f000981c9baa300348008c0e0dd5180118019bab300e30383754601c60706ea804cc0dcdd5180098011bab300d303737540124602a660726ea0004cc0e530010101004bd701199807000a450048810015330334913f65787065637420536f6d652870657263656e7461676529203d20726174696f6e616c2e6e6577286d61785f617374657269615f6d696e696e672c20313030290016533303130244832004530103d87a80001533303133710906400a4000260246606c60246606c6ea0cdc0a400004e6606c6ea0cdc024000906380a5eb812f5c0260246606c60246606c6ea009ccc0d9301021864004bd7025eb80c01ccc04005c8c8cc004004c8cc004004c94ccc0d0c088c0d8dd50008a5eb7bdb1804dd5981d181b9baa0013300f37566018606c6ea8c030c0d8dd500180b11299981c0008a5eb804cc0e4c0d8c0e8004cc008008c0ec004894ccc0dc004528099299981a19b8f33371890001b8d489045348495000375c607400491104534849500014a2266006006002607400266042002058a66666606c00220022a6605e0562c2a6605e0562c2a6605e0562c2a6605e0562c606660606ea800454cc0b80a458c018c0bcdd50008a998168138b181880099801008119baf300d302e3754002601a605c6ea8c010c0b8dd50048a99981518009980500892999815999815a999815980f18169baa300d302e3754601a605c6ea8c010c0b8dd50008a5014a294128899b8848000ccc018dd5980218171baa3004302e37540026eb8c034c0b8dd50129bae3004302e375404a29405288a99815a481296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a04a666054603a60586ea80045288a5022323300100100322533303000114bd70099192999817180280109981980119802002000899802002000981a00118190009181718178009181698171817000911192999814980b98159baa0011480004dd6981798161baa0013253330293017302b3754002298103d87a80001323300100137566060605a6ea8008894ccc0bc004530103d87a80001323232533302e3371e00e6eb8c0c000c4c03ccc0ccdd4000a5eb804cc014014008dd6981800118198011818800998020018011119198008008019129998160008a60103d87a80001323232533302b3371e00c6eb8c0b400c4c030cc0c0dd3000a5eb804cc014014008dd598168011818001181700098129baa0123028302537540022a6604692013c65787065637420536f6d6528617374657269615f696e70757429203d2066696e645f696e70757428696e707574732c20617374657269615f726566290016323300200923375e600a604c6ea8004008c09cc090dd50051119198008008019129998140008a60103d87a80001323253330263005002130073302b0024bd70099802002000981600118150009ba5480008c09400454cc07d24123657870656374205370656e6428617374657269615f72656629203d20707572706f73650016375c604660480046eb4c088004c078dd50079bac3020302130210023758603e00260366ea8c078008c074c078004c064dd50008a4c2a6602e9211856616c696461746f722072657475726e65642066616c73650013656325333015300800115333019301837540082930a9980b0098b0a99980a98018008a99980c980c1baa004149854cc05804c5854ccc054c00800454ccc064c060dd50020a4c2a6602c0262c2a6602c0262c602c6ea800cdc3a40086e1d200253333330190011001153301200f16153301200f16153301200f16153301200f163300100300e225333010300330123754004264a66602a0022a660240042c26464a66602e0022a660280082c264a66603060360042930a9980a8028b19299999980e0008a9980a8028b0a9980a8028b0a9980a8028b0a9980a8028b09bae0013019001301900232533333301a0011533013003161533013003161533013003161375a0022a660260062c602e00260266ea800854cc04400458dc3a4000a66666602800220022a6601a0162c2a6601a0162c2a6601a0162c2a6601a0162c6eb4004dd6800a499c657870656374205b617374657269615f6f75747075745d203d0a202020202020202020206c6973742e66696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d20617374657269615f696e7075742e6f75747075742e61646472657373207d2c0a20202020202020202020290049013f65787065637420496e6c696e65446174756d28617374657269615f6f75747075745f646174756d29203d20617374657269615f6f75747075742e646174756d0049014065787065637420617374657269615f6f75747075745f646174756d3a2041737465726961446174756d203d20617374657269615f6f75747075745f646174756d0049011972656465656d65723a204173746572696152656465656d657200490113646174756d3a2041737465726961446174756d005734ae7155ceaab9e5573eae815d0aba257481"; const SPACETIME_PARAMETERIZED: &str = "592d94010000323232323232323232323232323232323232323232323223223222232232232232223253333330280021532323232323232323330283001302a37540142a660529211c52756e6e696e672032206172672076616c696461746f72206d696e740013232533302a3232323232323232325333033300c303537540102646464a66606c601e60706ea80384c8c8c94ccc0e4c048c0ecdd500089919191919299981f180c98201baa0011323232325333046001153304303e161325333047304a0021325333044301f30463754002264646464a666090604860946ea80044c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c94ccc16d4ccc16c0805288a9982e24811d6d7573745f62655f76616c69645f61737465726961203f2046616c73650014a02a6660b6a6660b6010294454cc171241206d7573745f6d696e745f65787065637465645f76616c7565203f2046616c73650014a02a6660b6a6660b600e294454cc171241216d7573745f726573706563745f6d696e5f64697374616e6365203f2046616c73650014a02a6660b6a6660b600c294454cc1712411b6d7573745f686176655f736869705f6e616d65203f2046616c73650014a02a6660b6a6660b600a294454cc1712411c6d7573745f686176655f70696c6f745f6e616d65203f2046616c73650014a02a6660b6a6660b6008294454cc1712411d6d7573745f686176655f6c61746573745f74696d65203f2046616c73650014a02a6660b6a6660b6006294454cc1712411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660b6a6660b6004294454cc1712411e6d7573745f686f6c645f696e697469616c5f6675656c203f2046616c73650014a02a6660b6002294454cc17124011a6d7573745f686f6c645f335f617373657473203f2046616c73650014a029405280a5014a029405280a5014a06068664600200244a6660c0002290000981d99801001183180099198008009bab3025305e375403244a6660c0002297ae01323332223233001001003225333066001100313233068374e660d06ea4018cc1a0dd49bae30650013306837506eb4c1980052f5c06600600660d400460d00026eb8c17c004dd59830000998018019832001183100099b8733301f3756604660b86ea805c1252201044655454c0003f303433301e3756604460b66ea805809401ccdc39bad305d305e305e305e305e305a37540246eb4c174c168dd500819b8f375c60b860ba60ba60ba60b26ea8044010cdc79bae30193058375402000866e240e0c8cdc018009bad301e3058375402060026eb4c07cc160dd50081299982a99b88001480004c0cc0044004cdd79ba601f374c64646466660026666002a6660ac606490000a5eb7bdb1804c8c8cc0040052f5bded8c044a6660ba0022660bc66ec0dd48131ba60034bd6f7b630099191919299982e98049980501500109983119bb037520546e9801c01454ccc174cdc781500109983119bb037520546e9801c00c4cc188cdd81ba9002374c0026600c00c0066eacc17c00cdd7182e8011830801182f8009919800800a5eb7bdb180894ccc1700044cc174cdd81ba90074c010101004bd6f7b630099191919299982e18041980480580109983099bb037520169810101000051533305c3371e0160042660c266ec0dd4805a61010100003133061337606ea4008dd4000998030030019bad305e003375c60b800460c000460bc0020460089001023245044655454c0003c22225333059303200110041323233001001006225333060001133061337606ea4018dd3001a5eb7bdb1804c8c8c8c94ccc180c030cc0340280084cc194cdd81ba900a374c00e00a2a6660c066e3c0280084c94ccc184c0e8c18cdd500089983319bb0375201660ce60c86ea80040104010c94ccc1854ccc1940045288a5014c0103d87a80001303e33066374c00297ae03233001001002225333066001133067337606ea402cdd400525eb7bdb1804c8c8c8c94ccc198c048cc04c03c0084cc1accdd81ba900f375001c00a2a6660cc66e3c03c0084c94ccc19cc100c1a4dd500089983619bb0375202060da60d46ea80040104010c94ccc19cc1000045300103d87a8000130443306c375000297ae03370000201c2660d666ec0dd48011ba800133006006003375a60d00066eb8c198008c1a8008c1a00044cc194cdd81ba9002374c0026600c00c0066eacc18800cdd7183000118320011831000991900119198008008011129998300008a4c264a6660c200229309919299982f981c18309baa3300c375c60c260ca0086eb8c1840084cc014014cc19000800454cc1812401326b65797320696e206173736f63696174697665206c697374206172656e277420696e20617363656e64696e67206f7264657200163065002306300130630013305e337606ea4008dd4000a5eb7bdb180dd7a60103d879800022533305533720004002298103d8798000153330553371e0040022980103d87a800014c103d87b8000330024890550494c4f540030033004375a603660aa6ea804ccc005220104534849500030023003375a603460a86ea804888cdc500100091b9800123732660046ea00052201003001001222533333305700213232323232323300b0020013371491010128000025333053337100069007099b80483c80400c54ccc14ccdc4001a410004266e00cdc0241002800690068a9982a24929576861742061726520796f7520646f696e673f204e6f2049206d65616e2c20736572696f75736c792e001653330560011337149101035b5d2900004133714911035b5f2000375c60aa66600e00266ec1300102415d00375266e292210129000042233760980103422c2000375266601001000466e28dd7182b0009bae3057001375860a80046eb4c148004c8cdd81ba83052001374e60a60026ea80084c94ccc1500044cdc5245027b7d00002133714911037b5f2000375c60a664646600200200644a6660ae00220062664466ec130103422c2000375266601201260ae00466e29221023a20003330090093058002337146eb8c15c004dd7182c000982c80099801001182d00099bb04c10342207d0037520046eac0084c94ccc1500044cdc52441025b5d00002133714911035b5f2000375c60a666600a00266ec1300102415d0037520044466ec1300103422c2000375266600c00c00466e28dd7182a0009bae3055001375800426600a6eb40080044c8c8cdc524410268270000132333001001337006e3400920013371491101270000322253330533371000490000800899191919980300319b8000548004cdc599b80002533305633710004900a0a40c02903719b8b33700002a6660ac66e2000520141481805206e0043370c004901019b8300148080cdc70020011bae00222232330010010042253330540011004133003305600133002002305700122323300100100322533304e30270011337149110130000031533304e337100029000099b8a489012d0033002002302c00113300533708002900a19b8b3370066e1400520144818000cc0040048894ccc12ccdc4801240002002266600600666e1000920143371666e00cdc28012402890300008a9982481f0b180818251baa3011304a375402aa66608c603e60906ea80044c94ccc12c00454cc120110584c8c94ccc13400454cc128118584c8c94ccc13c00454cc130120584c8c94ccc14400454cc138128584c8c94ccc14c00454cc140130584c94ccc150c15c008526153305104d16325333333058001153305104d16153305104d16153305104d161375a0022a660a209a2c60aa00260aa00464a6666660ac0022a6609e0962c2a6609e0962c2a6609e0962c2a6609e0962c26eb8004c14c004c14c008c94cccccc15000454cc1341245854cc1341245854cc1341245854cc134124584dd7000982880098288011929999998290008a998258238b0a998258238b0a998258238b09bad001153304b04716304f001304f0023253333330500011533049045161533049045161533049045161375a0022a6609208a2c609a00260926ea800454cc11c10c594cccccc134004400454cc1181085854cc1181085854cc1181085854cc11810858c128c11cdd50008a99822a493165787065637420496e6c696e65446174756d28736869705f646174756d29203d20736869705f73746174652e646174756d00163007304637540022a6608807e2c6090002646600200202644a66608e002297ae0132325333045325333046302230483754002266e3c04cdd7182618249baa00114a0601c60906ea8c038c120dd50010998250011980200200089980200200098258011824800a999820180c98211baa0011325333045001153304203c16132325333047001153304403e161325333048304b002149854cc1140fc58c94cccccc13000454cc1140fc5854cc1140fc5854cc1140fc5854cc1140fc584dd7000982480098248011929999998250008a9982181e8b0a9982181e8b0a9982181e8b09bad001153304303d163047001304337540022a660820762ca66666608e00220022a660800742c2a660800742c2a660800742c2a660800742c608860826ea800454cc0fd2413e65787065637420496e6c696e65446174756d28617374657269615f646174756d29203d20617374657269615f696e7075742e6f75747075742e646174756d0016300130403754600e60806ea80108c10cc110c110004c06cccc004dd59802981f1baa3005303e37540046eb8c010c0f8dd50141bae3005303e375405044464a66607c603460806ea8004520001375a608860826ea8004c94ccc0f8c068c100dd50008a60103d87a8000132330010013756608a60846ea8008894ccc110004530103d87a8000132323253330433371e00e6eb8c11400c4c080cc120dd4000a5eb804cc014014008dd698228011824001182300099804001801181f981e1baa001153303a03116323300100100c22533303e00114c103d87a800013232533303c32533303d3016303f375400229404cdc79bae304330403754002056600a607e6ea8c014c0fcdd51803181f9baa00213019330410024bd70099802002000982100118200009181f0009181e981f000899299981d8008a9981c01a8b099299981e181f8010a99981c19b8748004dd6981d8008a51153303903616153303903616303d001325333037301330393754002297adef6c6013756607a60746ea8004cc00400800c88c8cc00400400c894ccc0f40045300103d87a80001323232533303c3371e00c6eb8c0f800c4c064cc104dd3000a5eb804cc014014008dd5981f0011820801181f800991980080080211299981d0008a5eb7bdb1804c8c8c8c94ccc0e8cdc7a44100002100313303f337606ea4008dd3000998030030019bab303c003375c6074004607c00460780026eb8c0e4c0d8dd50040a9981a24926657870656374204d696e742873686970796172645f706f6c69637929203d20707572706f7365001630383039303930390023756606e002606e606e0046eb0c0d4004c0d4c0d4008dd6181980098179baa303200230313032001302d37540182930a99815a4811856616c696461746f722072657475726e65642066616c7365001365632533302a30030011533302e302d37540042930a998158148b0a99981518030008a99981718169baa002149854cc0ac0a45854cc0ac0a458c0acdd5000a99999981800588058a998148138b0a998148138b0a998148138b0a998148138b0a99814a491d52756e6e696e672033206172672076616c696461746f72207370656e640013323232232322533302f323232323232323232323232323232323232323232325333045301e30473754002264a66608c604460906ea80584c8c94ccc120c084c128dd5000899192999825181318261baa001132323232323232323232323232325323233305a303300d1323232325333062001153305f05016132533306330660021325333060303b30623754002264646464a6660c8608060cc6ea80044c8c94ccc198c108c1a0dd50008991919192999835182198361baa001132323232323232323232323253330765333076305230263301f044230293035307a3754606c60f46ea80045288a9983ba481236d7573745f7370656e645f6f6e655f7363726970745f696e707574203f2046616c73650014a02a6660eca6660ec054294454cc1dd241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660eca6660ec008294454cc1dd2411d6d7573745f686176655f656e6f7567685f6675656c203f2046616c73650014a02a6660eca6660ec00c294454cc1dd2411e6d7573745f726573706563745f6d61785f7370656564203f2046616c73650014a02a6660eca6660ec00a294454cc1dd241206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a02a6660eca6660ec004294454cc1dd241216d7573745f73756274726163745f6675656c5f746f6b656e73203f2046616c73650014a02a6660eca6660ec010294454cc1dd2411c6d7573745f6275726e5f7370656e745f6675656c203f2046616c73650014a02a6660eca6660ec014294454cc1dd241156d7573745f7570646174655f78203f2046616c73650014a02a6660eca6660ec012294454cc1dd241156d7573745f7570646174655f79203f2046616c73650014a02a6660eca6660ec00e294454cc1dd2411f6d7573745f7570646174655f75707065725f626f756e64203f2046616c73650014a02a6660eca6660ec016294454cc1dd241216d7573745f70726573657276655f70696c6f745f746f6b656e203f2046616c73650014a02a6660eca6660ec006294454cc1dd2411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660ec002294454cc1dd24011a6d7573745f686f6c645f335f617373657473203f2046616c73650014a029405280a5014a029405280a5014a029405280a5014a0609e604460486eacc0d0c1e0dd500b99b8733301f3756606660ee6ea80581912201044655454c0033702014018609e66603c6eacc0c8c1d8dd500a81481b19b8900a008301900d32323371266e08dd6983c0011bad30783079001337046eb4c1e0004dd6983c183c801183a1baa02c3073375460ec60e66ea801ccdc39bad307530763076307630763072375401c012602a609800c66e1cdd6981618381baa00c3370006402266e1cdd6981518379baa00b3370006602266e3c0b0dd7183898391839183918371baa00a3330153756605260da6ea8c0a4c1b4dd501102d2441044655454c00153306b4915865787065637420536f6d6528737065656429203d0a20202020202020202020726174696f6e616c2e6e65772864697374616e63652c2074785f6c61746573745f74696d65202d2074785f6561726c696573745f74696d65290016330260023370200600a66e08004140c8cdc0180080698008061299983419b88001480004c1180044004dd6983618349baa001153306705c16302330683754604860d06ea80b8dd6983518339baa001153306505916302130663754604260cc6ea80b0cc0e40041594cccccc1a4004400454cc1881545854cc1881545854cc1881545854cc18815458c198c18cdd50008a998308298b180498311baa00115330600511630640013300602923375e603860c26ea8004c070c184dd5180e98309baa016375a60c460c60046eb4c184004c174dd50170a99982d181b0068991929998300008a9982e8270b09929998309832001099299982f181c98301baa0011323232325333062303b306437540022646464a6660ca608060ce6ea80044c8c8c8c94ccc1a4c114c1acdd5000899191919191919191929998392999839182698111980d820118129818983b1baa303230763754002294454cc1cd2401246d7573745f7370656e645f74776f5f7363726970745f696e70757473203f2046616c73650014a02a6660e4a6660e401e294454cc1cd2411c6d7573745f62655f76616c69645f70656c6c6574203f2046616c73650014a02a6660e4a6660e404c294454cc1cd241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660e4a6660e4010294454cc1cd241216d7573745f686176655f70656c6c65745f706f736974696f6e203f2046616c73650014a02a6660e4a6660e4006294454cc1cd2411c6d7573745f6164645f6675656c5f746f6b656e73203f2046616c73650014a02a6660e4a6660e400e294454cc1cd241206d7573745f6e6f745f6578636565645f6361706163697479203f2046616c73650014a02a6660e4a6660e400a294454cc1cd241206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a02a6660e4a6660e400c294454cc1cd2411b6d7573745f70726573657276655f646174756d203f2046616c73650014a02a6660e4a6660e4008294454cc1cd2411c6d7573745f686f6c645f736869705f746f6b656e203f2046616c73650014a02a6660e4a6660e4004294454cc1cd2411a6d7573745f686f6c645f335f617373657473203f2046616c73650014a02a6660e4002294454cc1cd24011c6d7573745f6e6f745f6d696e745f746f6b656e73203f2046616c73650014a029405280a5014a029405280a5014a0294052819baf374c603a07698101a000304a301d301f3756605e60e66ea8050cdc399980d1bab302e307237540260be911044655454c003370000c02a60946660326eacc0b4c1c4dd5009012018980a9bad30733070375400a66ebc034110cdc499b80002011055533306a3370e0626eb4c0a0c1b4dd5002099b8702f375a605260da6ea801052819980a1bab3028306c3754605060d86ea8084165221044655454c00153306a05e163026306b3754604c60d66ea80c54ccc19cc100c1a4dd500089929998360008a9983482f8b0991929998370008a998358308b0991929998380008a998368318b0992999838983a0010a4c2a660dc0c82c64a6666660ea0022a660dc0c82c2a660dc0c82c2a660dc0c82c2a660dc0c82c26eb8004c1c8004c1c8008c94cccccc1cc00454cc1b01885854cc1b01885854cc1b0188584dd68008a998360310b183800098380011929999998388008a998350300b0a998350300b0a998350300b09bad001153306a06016306e001306a37540022a660d00bc2ca6666660dc00220022a660ce0ba2c2a660ce0ba2c2a660ce0ba2c2a660ce0ba2c60d660d06ea800454cc1992413c65787065637420496e6c696e65446174756d2870656c6c65745f646174756d29203d2070656c6c65745f696e7075742e6f75747075742e646174756d0016300e30673754604660ce6ea8008c10cccc038dd5981118331baa3022306637540026eb8c084c198dd50281bae3022306637540a060d060ca6ea800454cc18d2401ff65787065637420536f6d652870656c6c65745f696e70757429203d0a202020202020202020206c6973742e66696e64280a202020202020202020202020696e707574732c0a202020202020202020202020666e28696e70757429207b0a20202020202020202020202020207768656e20696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c206973207b0a20202020202020202020202020202020566572696669636174696f6e4b657943726564656e7469616c285f29202d3e2046616c73650a2020202020202020202020202020202053637269707443726564656e7469616c28616464725f7061796d656e6b7429202d3e0a202020202020202020202020202020202020616464725f7061796d656e74203d3d2070656c6c65745f76616c696461746f725f616464726573730a20202020202020202020202020207d0a2020202020202020202020207d2c0a202020202020202020202900163301b02f2325333063303c3065375400229404cdc79bae3069306637540020a6604060ca6ea8c080c194dd5181098329baa00133037001054533333306700110011533060053161533060053161533060053161533060053163064306137540022a660be0a22c600e60c06ea800454cc17813c58c188004cc01009c8cdd7980d182f9baa001301a305f3754603660be6ea8050dd69830182e9baa02e1533305a303500d132533305b3034305d375400226464a6660ba607260be6ea80044c8c8c8c94ccc1854ccc184c0f0c044cc0280bc8c050c080c194dd5181098329baa00114a22a660c49201246d7573745f7370656e645f74776f5f7363726970745f696e70757473203f2046616c73650014a02a6660c2a6660c200c294454cc1892411d6d7573745f62655f76616c69645f61737465726961203f2046616c73650014a02a6660c2a6660c202a294454cc189241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660c2a6660c2008294454cc189241226d7573745f686176655f617374657269615f706f736974696f6e203f2046616c73650014a02a6660c2a6660c2006294454cc1892411c6d7573745f6275726e5f736869705f746f6b656e203f2046616c73650014a02a6660c2a6660c2002294454cc1892411d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a02a6660c2004294454cc1892401206d7573745f726573706563745f6c61746573745f74696d65203f2046616c73650014a029405280a5014a029405281803981f1998059bab301f30633754603e60c66ea80601412201044655454c003007375a60ca60c46ea800ccdc4199804980501400a010a400066ebcdd31983119bb037500486ea00892f5bded8c06e98cc1892f7b6301010000010100004bd6f7b6300a9982f0290b180d182f9baa301a305f375404a607666600c6eacc068c178dd5180d182f1baa3061305e37540026eb8c064c178dd50241bae301a305e37540902a660b80a62c66028050464a6660b8606a60bc6ea8004528099b8f375c60c460be6ea8004128c064c178dd5180c982f1baa301a305e375400226464a6660b8a6660b8607060186600a0544601e603660c06ea8c070c180dd50008a51153305d491236d7573745f7370656e645f6f6e655f7363726970745f696e707574203f2046616c73650014a02a6660b8a6660b8020294454cc175241206d7573745f696e636c7564655f70696c6f745f746f6b656e203f2046616c73650014a02a6660b8a6660b8004294454cc1752411c6d7573745f6275726e5f736869705f746f6b656e203f2046616c73650014a02a6660b8002294454cc17524011d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a029405280a50300230393330063756603460bc6ea8c068c178dd5009825a441044655454c003371066600a600c04802003a90001b8733300430050230494881044655454c00371203044646600200200644a6660be002297ae013232533305d300500213306200233004004001133004004001306300230610012305d305e305e0012223253330593035305b37540022900009bad305f305c375400264a6660b2606a60b66ea80045300103d87a800013233001001375660c060ba6ea8008894ccc17c004530103d87a80001323232533305e3371e00e6eb8c18000c4c0eccc18cdd4000a5eb804cc014014008dd6983000118318011830800998068018011191980080080111299982d8008a5eb7bdb1804c8c8c8c94ccc16ccdc7a441000021003133060337606ea4008dd3000998030030019bab305d003375c60b600460be00460ba002600200244a6660b0002290000981999801001182d8009191980080080111299982c0008a5eb804c8ccc888c8cc00400400c894ccc178004400c4c8cc180dd3998301ba90063306037526eb8c174004cc180dd41bad305e0014bd7019801801983100118300009bae3057001375660b00026600600660b800460b4002600200244a6660aa002290000981819801001182c00092999827981418289baa300d30523754002294052898279baa021533304c3025304e37546600c03446466002002646600200264a6660a0605860a46ea800452f5bded8c026eacc158c14cdd5000998021bab300e30523754601c60a46ea800c014894ccc15000452f5c02660aa60a460ac0026600400460ae00244a6660a600229404c94ccc140cdc79bae305600201114a226600600600260ac00229445281119198008008019129998298008a60103d87a8000132323253330523371e00c6eb8c15000c4c0bccc15cdd3000a5eb804cc014014008dd5982a001182b801182a8009bae3050304d37540022a660969215d6578706563742053637269707443726564656e7469616c2873686970796172645f706f6c69637929203d0a202020202020736869705f696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c00163007304c3754600e60986ea8c020c130dd5000982718259baa001153304949013665787065637420536f6d6528736869705f696e70757429203d2066696e645f696e70757428696e707574732c20736869705f726566290016323300201623375e600e60986ea8004008c134c128dd500b9119198008008019129998270008a60103d87a800013232533304c300500213029330510024bd70099802002000982900118280008a99823a48120657870656374205370656e6428736869705f72656629203d20707572706f73650016304b304837540022a6608c92015865787065637420536f6d65286d61785f73706565645f726174696f6e616c29203d0a202020202020726174696f6e616c2e6e6577286d61785f73706565642e64697374616e63652c206d61785f73706565642e74696d6529001633001375a6004608e6ea80c0dd6980198239baa030225333045301e00114c103d87a80001533304533710002900009811198251811198251ba830230023304a3750604600297ae04bd7009811198251811198251ba80023304a375000297ae04bd70118248009182418248009bad30463047002375c608a002608a0046eb8c10c004c10c008dd6982080098208011bad303f001303b3754020607a607c607c607c0046eacc0f0004c0f0c0f0008dd6181d000981d181d0011bac303800130343754606e004606c606e00260646ea8004526153303049011856616c696461746f722072657475726e65642066616c7365001365632533302e30070011325333033001153303002816132325333035001153303202a1613253330363039002149854cc0cc0ac58c94cccccc0e800454cc0cc0ac5854cc0cc0ac5854cc0cc0ac584dd68008a998198158b181b800981b80119299999981c0008a998188148b0a998188148b0a998188148b09bad0011533031029163035001303137540042a66605c6014002264a6660660022a660600502c264a666068606e0042930a998188148b19299999981c0008a998188148b0a998188148b0a998188148b09bad0011533031029163035001303137540042a66605c60120022a66606460626ea8008526153302f027161533302e300800115333032303137540042930a998178138b0a998178138b18179baa00153333330340011001153302d02516153302d02516153302d02516153302d025163300100202422533302b3004302d3754004264a6660600022a6605a0042c26464a6660640022a6605e0082c26464a6660680022a6606200c2c26464a66606c0022a660660102c26464a6660700022a6606a0142c264a66607260780042930a9981b0058b19299999981e8008a9981b0058b0a9981b0058b0a9981b0058b09bad001153303600b16303a001303a00232533333303b0011533034009161533034009161533034009161533034009161375c0026070002607000464a6666660720022a6606400e2c2a6606400e2c2a6606400e2c2a6606400e2c26eb8004c0d8004c0d8008c94cccccc0dc00454cc0c00145854cc0c00145854cc0c0014584dd68008a998180028b181a000981a00119299999981a8008a998170018b0a998170018b0a998170018b09bad001153302e003163032001302e37540042a660580022ca66666606001620162a660520442c2a660520442c2a660520442c2a660520442c605c60566ea8028dc3a40006e1d2006370e90021b8748008dd2a40006e052000370090011b884800054cc0840045854cc0840045854cc0840045854cc08400459240191496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e00375a0026eb4004dd68009bad001375c0026eb800524196657870656374205b736869705f6f75747075745d203d0a202020202020202020206c6973742e66696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d20736869705f696e7075742e6f75747075742e61646472657373207d2c0a20202020202020202020290049013965787065637420496e6c696e65446174756d28736869705f6f75747075745f646174756d29203d20736869705f6f75747075742e646174756d0049013765787065637420736869705f6f75747075745f646174756d3a2053686970446174756d203d20736869705f6f75747075745f646174756d004901476578706563742046696e6974652874785f6561726c696573745f74696d6529203d2076616c69646974795f72616e67652e6c6f7765725f626f756e642e626f756e645f74797065004901456578706563742046696e6974652874785f6c61746573745f74696d6529203d2076616c69646974795f72616e67652e75707065725f626f756e642e626f756e645f747970650049012f6578706563742070656c6c65745f646174756d3a2050656c6c6574446174756d203d2070656c6c65745f646174756d004901ff65787065637420536f6d6528617374657269615f696e70757429203d0a202020202020202020206c6973742e66696e64280a202020202020202020202020696e707574732c0a202020202020202020202020666e28696e70757429207b0a20202020202020202020202020207768656e20696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c206973207b0a20202020202020202020202020202020566572696669636174696f6e4b657943726564656e7469616c285f29202d3e2046616c73650a2020202020202020202020202020202053637269707443726564656e7469616c28616464725f7061796d656d6e7429202d3e0a202020202020202020202020202020202020616464725f7061796d656e74203d3d20617374657269615f76616c696461746f725f616464726573730a20202020202020202020202020207d0a2020202020202020202020207d2c0a20202020202020202020290049011672656465656d65723a205368697052656465656d657200490110646174756d3a2053686970446174756d0049013265787065637420617374657269615f646174756d3a2041737465726961446174756d203d20617374657269615f646174756d00490159657870656374205b736869705f73746174655d203d0a202020202020202020207472616e73616374696f6e2e66696e645f7363726970745f6f757470757473286f7574707574732c2073686970796172645f706f6c696379290049012965787065637420736869705f646174756d3a2053686970446174756d203d20736869705f646174756d00490120657870656374205b285f2c202d31295d203d206d696e7465645f746f6b656e730049011a72656465656d65723a20536869707961726452656465656d6572005734ae7155ceaab9e5573eae815d0aba257481"; const PELLET_PARAMETERIZED: &str = "590d270100003232323232323232323232323232222325333333012002153232323233300e30013010375400c2a6601e92011c52756e6e696e672032206172672076616c696461746f72206d696e7400132325333010323232323253330153008301737540082646464a666030601660346ea80284c94ccc0654ccc0654ccc064c030c06cdd5191980080080391299980f8008a60103d87a800013232533301d3013323330073756600260426ea8c004c084dd50019bae3024302137540306eb8c004c084dd500c118121812800898091981100125eb804cc010010004c08c008c0840045288a5014a22a660349201296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a02a666032002294454cc06924011d6d7573745f6d696e745f6675656c5f746f6b656e73203f2046616c73650014a02940c038ccc00400800d2201044655454c001533301833710666002004006911044655454c00480005288a9980ca491d6d7573745f6275726e5f6675656c5f746f6b656e73203f2046616c73650014a044464a666036601e603a6ea8004520001375a6042603c6ea8004c94ccc06cc03cc074dd50008a60103d87a80001323300100137566044603e6ea8008894ccc084004530103d87a8000132323253330203371e00e6eb8c08800c4c054cc094dd4000a5eb804cc014014008dd698110011812801181180099198008008021129998100008a6103d87a80001323232533301f3371e00e6eb8c08400c4c050cc090dd3000a5eb804cc014014008dd5981080118120011811000991980080080191299980e0008a5eb7bdb1804c8c8c8c94ccc070cdc7a441000021003133021337606ea4008dd3000998030030019bab301e003375c60380046040004603c0026eb8c06cc060dd50020a9980b24922657870656374204d696e74286675656c5f706f6c69637929203d20707572706f736500163756603460366036603660360046eb0c064004c054dd5180c001180b980c00098099baa008149854cc0452411856616c696461746f722072657475726e65642066616c73650013656325333010300300115333014301337540042930a998088078b0a99980818020008a99980a18099baa002149854cc04403c5854cc04403c58c044dd5000a99999980b00388038a998078068b0a998078068b0a998078068b0a998078068b0a99807a491d52756e6e696e672033206172672076616c696461746f72207370656e64001332323223232253330153232323232533301a300e301c37540082646464a66603a6020603e6ea80044c8c8c94ccc080c050c088dd5000899191919192999812980c18139baa0131323232533302c001153302902316132533302d3030002132533302a3370e900218161baa00113232323232323253330315333031300d33016019232330010013233001001325333035302930373754002297adef6c6013756607660706ea8004cc04cdd5980b181b9baa30163037375400601c44a666072002297ae013303a3037303b00133002002303c00122533303800114a0264a66606a66e3cccdc6240006e35221045348495000375c607600491104534849500014a22660060060026076002294454cc0c924011d6d7573745f696e7075745f736869705f746f6b656e203f2046616c73650014a02a666062a666062006294454cc0c92411d6d7573745f686f6c645f61646d696e5f746f6b656e203f2046616c73650014a02a666062a666062008294454cc0c92411d6d7573745f686176655f656e6f7567685f6675656c203f2046616c73650014a02a666062a666062004294454cc0c9241206d7573745f70726f766964655f6675656c5f616d6f756e74203f2046616c73650014a02a666062002294454cc0c924011b6d7573745f70726573657276655f646174756d203f2046616c73650014a029405280a5014a066ebc014088cdc39998069bab30113032375400e01e9101044655454c003370201801460446660186eacc040c0c4dd50031bae3014303137540506eb8c040c0c4dd501419b8900800a3301d00102853333330330011001153302c02716153302c02716153302c02716153302c027163030302d37540022a660569213365787065637420496e6c696e65446174756d286f75745f646174756d29203d2070656c6c65745f6f75747075742e646174756d0016302f30303030302c37540022a660540482c605c002646600200201e44a66605a002297ae013232533302b3375e6022605c6ea8008c044c0b8dd5180698171baa00e133030002330040040011330040040013031002302f001375c6058605a605a60526ea8060dd6981598141baa0131533302530013300a00d253330263330265333026301930283754601860526ea8c030c0a4dd5180418149baa00114a02945282511301c3330043756601060526ea8c020c0a4dd50009bae300c302937540406eb8c020c0a4dd50100a5014a22a6604c921296f7074696f6e2e69735f736f6d652861646d696e5f746f6b656e5f696e70757429203f2046616c73650014a04a66604a6030604e6ea80045288a503330013756600a604c6ea8c014c098dd5003001a45044655454c00222325333026301a302837540022900009bad302c3029375400264a66604c603460506ea8004530103d87a8000132330010013756605a60546ea8008894ccc0b0004530103d87a80001323232533302b3371e00e6eb8c0b400c4c080cc0c0dd4000a5eb804cc014014008dd6981680118180011817000998020018011119198008008019129998148008a60103d87a8000132323253330283371e00c6eb8c0a800c4c074cc0b4dd3000a5eb804cc014014008dd59815001181680118158009bae3026302337540022a660429215b6578706563742053637269707443726564656e7469616c286675656c5f706f6c69637929203d0a20202020202070656c6c65745f696e7075742e6f75747075742e616464726573732e7061796d656e745f63726564656e7469616c0016300530223754600a60446ea8c004c088dd5001118129813000981198101baa001153301e49013a65787065637420536f6d652870656c6c65745f696e70757429203d2066696e645f696e70757428696e707574732c2070656c6c65745f726566290016323300200523375e600860426ea8004008c088c07cdd50031119198008008019129998118008a60103d87a8000132325333021300500213016330260024bd7009980200200098138011812800918108008a9980da48122657870656374205370656e642870656c6c65745f72656629203d20707572706f736500163758603e604060400046eb0c078004c068dd5180e801180e180e800980c1baa001149854cc0592411856616c696461746f722072657475726e65642066616c7365001365632533301430070011325333019001153301601216132533301a301d002149854cc05c04c58c94cccccc07800454cc05c04c5854cc05c04c5854cc05c04c584dd68008a9980b8098b180d800980b9baa00215333014300800115333018301737540042930a9980a8088b0a9980a8088b180a9baa001533333301a0011001153301300f16153301300f16153301300f16153301300f163300100200e225333011300430133754004264a66602c0022a660260042c26464a6660300022a6602a0082c26464a6660340022a6602e00c2c264a666036603c0042930a9980c0038b19299999980f8008a9980c0038b0a9980c0038b0a9980c0038b0a9980c0038b09bae001301c001301c00232533333301d0011533016005161533016005161533016005161375a0022a6602c00a2c6034002603400464a6666660360022a660280062c2a660280062c2a660280062c26eb400454cc05000c58c060004c050dd50010a998090008b299999980b00388038a998078060b0a998078060b0a998078060b0a998078060b180a18089baa006370e90001b8748008dd2a40006e212000153300b00116153300b00116153300b00116153300b0011649191496e636f72726563742072656465656d6572207479706520666f722076616c696461746f72207370656e642e0a2020202020202020202020202020202020202020446f75626c6520636865636b20796f7520686176652077726170706564207468652072656465656d657220747970652061732073706563696669656420696e20796f757220706c757475732e6a736f6e00490195657870656374205b70656c6c65745f6f75747075745d203d0a2020202020202020202066696c746572280a2020202020202020202020206f7574707574732c0a202020202020202020202020666e286f757470757429207b206f75747075742e61646472657373203d3d2070656c6c65745f696e7075742e6f75747075742e61646472657373207d2c0a202020202020202020202900490129657870656374206f75745f646174756d3a2050656c6c6574446174756d203d206f75745f646174756d0049011872656465656d65723a2050656c6c657452656465656d657200490112646174756d3a2050656c6c6574446174756d0049011672656465656d65723a204675656c52656465656d6572005734ae7155ceaab9e5573eae815d0aba257481"; @@ -55,6 +52,10 @@ pub async fn create_ship( ) -> anyhow::Result<()> { log::debug!("The args are:: {:?}", args); + let params_json: String = std::fs::read_to_string(DEPLOY_PARAMS_PATH)?; + let params: ScriptsParams = + serde_json::from_str(¶ms_json).map_err(|e| anyhow!("Invalid params JSON: {}", e))?; + let asteria_script_hex: &str = &std::fs::read_to_string(ASTERIA_PATH)?; let spacetime_script_hex: &str = &std::fs::read_to_string(SPACETIME_PATH)?; let pellet_script_hex: &str = &std::fs::read_to_string(PELLET_PATH)?; @@ -177,13 +178,15 @@ pub async fn create_ship( let outputs = vec![ Output { address: owner_pubkey, - value: owner_value - Value::Coin(SHIP_FEE) - Value::Coin(10) + value: owner_value + - Value::Coin(params.ship_mint_lovelace_fee) + - Value::Coin(10) + Value::from((spacetime_hash, pilot_name.clone(), 1)), datum_option: None, }, Output { address: asteria_address, - value: asteria_input.value.clone() + Value::Coin(SHIP_FEE), + value: asteria_input.value.clone() + Value::Coin(params.ship_mint_lovelace_fee), datum_option: Some(Datum(PlutusData::from(asteria_output_datum.clone()).0)), }, Output {