diff --git a/Cargo.lock b/Cargo.lock index 5bb1e2c5..290056da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,9 +75,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "arrayvec" @@ -125,7 +125,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" dependencies = [ "concurrent-queue", - "event-listener 4.0.0", + "event-listener 4.0.3", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -137,11 +137,11 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" dependencies = [ - "async-lock 3.2.0", + "async-lock 3.3.0", "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "slab", ] @@ -153,10 +153,10 @@ checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ "async-channel 2.1.1", "async-executor", - "async-io 2.2.2", - "async-lock 3.2.0", + "async-io 2.3.1", + "async-lock 3.3.0", "blocking", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "once_cell", "tokio", ] @@ -183,18 +183,18 @@ dependencies = [ [[package]] name = "async-io" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afaa937395a620e33dc6a742c593c01aced20aa376ffb0f628121198578ccc7" +checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65" dependencies = [ - "async-lock 3.2.0", + "async-lock 3.3.0", "cfg-if 1.0.0", "concurrent-queue", "futures-io", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "parking", - "polling 3.3.1", - "rustix 0.38.28", + "polling 3.3.2", + "rustix 0.38.30", "slab", "tracing", "windows-sys 0.52.0", @@ -211,11 +211,11 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ - "event-listener 4.0.0", + "event-listener 4.0.3", "event-listener-strategy", "pin-project-lite", ] @@ -266,24 +266,24 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] name = "async-task" -version = "4.6.0" +version = "4.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d90cd0b264dfdd8eb5bad0a2c217c1f88fa96a8573f40e7b12de23fb468f46" +checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -364,6 +364,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "bech32" version = "0.7.3" @@ -404,9 +410,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bitmaps" @@ -451,20 +457,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ "async-channel 2.1.1", - "async-lock 3.2.0", + "async-lock 3.3.0", "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "piper", "tracing", ] [[package]] name = "borsh" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9897ef0f1bd2362169de6d7e436ea2237dc1085d7d1e4db75f4be34d86f309d1" +checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667" dependencies = [ "borsh-derive", "cfg_aliases", @@ -472,15 +478,15 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478b41ff04256c5c8330f3dfdaaae2a5cc976a8e75088bafa4625b0d0208de8c" +checksum = "7aadb5b6ccbd078890f6d7003694e33816e6b784358f18e15e7e6d9f065a57cd" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", "syn_derive", ] @@ -524,37 +530,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" -[[package]] -name = "cardano-multiplatform-lib" -version = "3.1.3" -source = "git+https://github.com/dcSpark/cardano-multiplatform-lib?branch=metadata-and-addr#74462e5c442648b81da8e3dbb7781d817690565b" -dependencies = [ - "base64", - "bech32 0.7.3", - "cbor_event", - "cfg-if 1.0.0", - "clear_on_drop", - "cryptoxide", - "digest 0.9.0", - "ed25519-bip32", - "fraction", - "hex", - "itertools", - "js-sys", - "linked-hash-map", - "noop_proc_macro", - "num-bigint 0.4.4", - "num-integer", - "rand", - "rand_os", - "schemars", - "serde", - "serde_json", - "sha2 0.10.8", - "unicode-segmentation", - "wasm-bindgen", -] - [[package]] name = "cardano-net" version = "0.2.1" @@ -570,6 +545,22 @@ dependencies = [ "trust-dns-resolver", ] +[[package]] +name = "cardano-projected-nft" +version = "0.1.0" +source = "git+https://github.com/dcSpark/projected-nft-whirlpool.git?rev=13f81e8666743fefd14c5e1affb1cd828d8c473b#13f81e8666743fefd14c5e1affb1cd828d8c473b" +dependencies = [ + "cbor_event", + "cml-chain 0.1.0", + "cml-core 0.1.0", + "cml-crypto 0.1.0", + "hex", + "schemars", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "cardano-sdk" version = "0.2.5" @@ -582,7 +573,7 @@ dependencies = [ "cryptoxide", "ed25519-bip32", "hex", - "strum", + "strum 0.24.1", "thiserror", ] @@ -592,8 +583,11 @@ version = "2.4.1" dependencies = [ "anyhow", "async-trait", - "cardano-multiplatform-lib", "clap 3.2.25", + "cml-chain 5.0.0", + "cml-core 5.0.0", + "cml-crypto 5.0.0", + "cml-multi-era", "ctrlc", "dcspark-blockchain-source", "dcspark-core", @@ -603,7 +597,6 @@ dependencies = [ "migration", "multiverse", "oura", - "pallas", "serde", "serde_json", "serde_yaml", @@ -630,9 +623,9 @@ dependencies = [ [[package]] name = "cbored-derive" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b022e0f030c53dd61dd217b64e663d348004f598361d6a9ff6db2faf0584578e" +checksum = "2b6c2917d304b928214344fdbda3cfe5ccaea066ef3fc047e6fabb65cce982d1" dependencies = [ "proc-macro2", "quote", @@ -668,9 +661,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", @@ -678,7 +671,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-targets 0.52.0", ] [[package]] @@ -742,40 +735,79 @@ dependencies = [ ] [[package]] -name = "clear_on_drop" -version = "0.2.5" +name = "cml-chain" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38508a63f4979f0048febc9966fadbd48e5dab31fd0ec6a3f151bbf4a74f7423" +checksum = "d07a94cfb4c3837a0cc97323ec281cc6ede491279f8d80faf69005902023807d" dependencies = [ - "cc", + "base64 0.21.7", + "bech32 0.7.3", + "cbor_event", + "cml-core 0.1.0", + "cml-crypto 0.1.0", + "derivative", + "fraction", + "getrandom", + "hex", + "itertools", + "linked-hash-map", + "num 0.4.1", + "num-bigint 0.4.4", + "num-integer", + "rand", + "schemars", + "serde", + "serde_json", + "thiserror", + "unicode-segmentation", + "wasm-bindgen", ] [[package]] -name = "cloudabi" -version = "0.0.3" +name = "cml-chain" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +checksum = "9771caeea0ff074be4d59235eb261806d1e2a33d42dad909396f908eaa8cea81" dependencies = [ - "bitflags 1.3.2", + "base64 0.21.7", + "bech32 0.7.3", + "cbor_event", + "cml-core 5.0.0", + "cml-crypto 5.0.0", + "derivative", + "fraction", + "getrandom", + "hex", + "itertools", + "linked-hash-map", + "num 0.4.1", + "num-bigint 0.4.4", + "num-integer", + "rand", + "schemars", + "serde", + "serde_json", + "thiserror", + "unicode-segmentation", + "wasm-bindgen", ] [[package]] -name = "cml-chain" +name = "cml-core" version = "0.1.0" -source = "git+https://github.com/dcSpark/cardano-multiplatform-lib?rev=acca172633d0570a7432058aa5b0717ad2f0c6d7#acca172633d0570a7432058aa5b0717ad2f0c6d7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34899789d0bf57c079c0a77f7f6bdd6428d52bdeb1ec466b132802dbd46ebc15" dependencies = [ - "base64", + "base64 0.13.1", "bech32 0.7.3", "cbor_event", - "cml-core", - "cml-crypto", + "cfg-if 1.0.0", "derivative", "fraction", "getrandom", "hex", "itertools", "linked-hash-map", - "num 0.4.1", "num-bigint 0.4.4", "num-integer", "rand", @@ -788,10 +820,11 @@ dependencies = [ [[package]] name = "cml-core" -version = "0.1.0" -source = "git+https://github.com/dcSpark/cardano-multiplatform-lib?rev=acca172633d0570a7432058aa5b0717ad2f0c6d7#acca172633d0570a7432058aa5b0717ad2f0c6d7" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710010ebd36f8562462929605c5bb5eb472e444f4abee17bc27214f80f1fed52" dependencies = [ - "base64", + "base64 0.13.1", "bech32 0.7.3", "cbor_event", "cfg-if 1.0.0", @@ -814,12 +847,14 @@ dependencies = [ [[package]] name = "cml-crypto" version = "0.1.0" -source = "git+https://github.com/dcSpark/cardano-multiplatform-lib?rev=acca172633d0570a7432058aa5b0717ad2f0c6d7#acca172633d0570a7432058aa5b0717ad2f0c6d7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02775162430e97004d49882d64a095b055dd28052bc88fc8978e7155ee7ec603" dependencies = [ + "base64 0.21.7", "bech32 0.7.3", "cbor_event", "cfg-if 1.0.0", - "cml-core", + "cml-core 0.1.0", "cryptoxide", "derivative", "digest 0.9.0", @@ -833,6 +868,50 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cml-crypto" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b82642c8b143e7c019fcf73b5f8676825e8f90e7d0b8e3dae6aa3170c3fd0e6" +dependencies = [ + "base64 0.21.7", + "bech32 0.7.3", + "cbor_event", + "cfg-if 1.0.0", + "cml-core 5.0.0", + "cryptoxide", + "derivative", + "digest 0.9.0", + "ed25519-bip32", + "hex", + "rand", + "schemars", + "serde", + "serde_json", + "sha2 0.9.9", + "thiserror", +] + +[[package]] +name = "cml-multi-era" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8c41a87f93aa47c69a88bf9b7f0b28f13efe8968a0c3fd01412146ce6aab825" +dependencies = [ + "bech32 0.7.3", + "cbor_event", + "cml-chain 5.0.0", + "cml-core 5.0.0", + "cml-crypto 5.0.0", + "derivative", + "hex", + "linked-hash-map", + "schemars", + "serde", + "serde_json", + "wasm-bindgen", +] + [[package]] name = "concurrent-queue" version = "2.4.0" @@ -854,7 +933,7 @@ dependencies = [ "pathdiff", "serde", "serde_json", - "toml", + "toml 0.5.11", "yaml-rust", ] @@ -872,9 +951,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -905,45 +984,37 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if 1.0.0", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.16" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2fe95351b870527a5d09bf563ed3c97c0cffb87cf1c78a591bf48bb218d9aa" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if 1.0.0", "crossbeam-utils", - "memoffset", ] [[package]] name = "crossbeam-queue" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9bcf5bdbfdd6030fb4a1c497b5d5fc5921aa2f60d359a17e249c0e6df3de153" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if 1.0.0", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.17" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crossterm" @@ -998,12 +1069,12 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" +checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" dependencies = [ "nix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1062,9 +1133,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -1162,7 +1233,6 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" name = "entity" version = "0.0.0" dependencies = [ - "pallas", "sea-orm", "serde", ] @@ -1181,9 +1251,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", @@ -1216,9 +1286,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "4.0.0" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" dependencies = [ "concurrent-queue", "parking", @@ -1231,7 +1301,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ - "event-listener 4.0.0", + "event-listener 4.0.3", "pin-project-lite", ] @@ -1291,12 +1361,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "funty" version = "2.0.0" @@ -1305,9 +1369,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1320,9 +1384,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1330,15 +1394,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1358,9 +1422,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" @@ -1379,9 +1443,9 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeee267a1883f7ebef3700f262d2d54de95dfaf38189015a74fdc4e0c7ad8143" +checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" dependencies = [ "fastrand 2.0.1", "futures-core", @@ -1392,32 +1456,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1452,9 +1516,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -1465,13 +1529,13 @@ dependencies = [ [[package]] name = "ghost" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef81e7cedce6ab54cd5dc7b3400c442c8d132fe03200a1be0637db7ef308ff17" +checksum = "b0e085ded9f1267c32176b40921b9754c474f7dd96f7e808d4a982e48aa1e854" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -1560,9 +1624,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" [[package]] name = "hex" @@ -1607,9 +1671,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1657,16 +1721,16 @@ checksum = "978d142c8028edf52095703af2fad11d6f611af1246685725d6b850634647085" dependencies = [ "bitmaps", "imbl-sized-chunks", - "rand_core 0.6.4", + "rand_core", "rand_xoshiro", "version_check", ] [[package]] name = "imbl-sized-chunks" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6957ea0b2541c5ca561d3ef4538044af79f8a05a1eb3a3b148936aaceaa1076" +checksum = "144006fb58ed787dcae3f54575ff4349755b00ccc99f4b4873860b654be1ed63" dependencies = [ "bitmaps", ] @@ -1683,9 +1747,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1716,7 +1780,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.4", "libc", "windows-sys 0.48.0", ] @@ -1741,13 +1805,13 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ - "hermit-abi 0.3.3", - "rustix 0.38.28", - "windows-sys 0.48.0", + "hermit-abi 0.3.4", + "rustix 0.38.30", + "windows-sys 0.52.0", ] [[package]] @@ -1767,9 +1831,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -1791,9 +1855,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.151" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libredox" @@ -1801,7 +1865,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", "redox_syscall 0.4.1", ] @@ -1820,9 +1884,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -1890,18 +1954,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "merge" @@ -2023,7 +2078,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cfg-if 1.0.0", "libc", ] @@ -2038,12 +2093,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "noop_proc_macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2194,15 +2243,15 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.4", "libc", ] [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -2243,8 +2292,8 @@ dependencies = [ "prometheus_exporter", "serde", "serde_json", - "strum", - "strum_macros", + "strum 0.24.1", + "strum_macros 0.24.3", "unicode-truncate", ] @@ -2326,7 +2375,7 @@ dependencies = [ "cryptoxide", "hex", "pallas-codec", - "rand_core 0.6.4", + "rand_core", "serde", "thiserror", ] @@ -2492,10 +2541,10 @@ dependencies = [ "anyhow", "clap 3.2.25", "dot", - "strum", - "strum_macros", + "strum 0.25.0", + "strum_macros 0.25.3", "tasks", - "toml", + "toml 0.8.8", "tracing", "tracing-subscriber", ] @@ -2518,14 +2567,14 @@ dependencies = [ [[package]] name = "polling" -version = "3.3.1" +version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf63fa624ab313c11656b4cda960bfc46c410187ad493c41f6ba2d8c1e991c9e" +checksum = "545c980a3880efd47b2e262f6a4bb6daad6555cf3367aa9c4e52895f69537a41" dependencies = [ "cfg-if 1.0.0", "concurrent-queue", "pin-project-lite", - "rustix 0.38.28", + "rustix 0.38.30", "tracing", "windows-sys 0.52.0", ] @@ -2544,11 +2593,10 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-crate" -version = "2.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_datetime", "toml_edit", ] @@ -2584,29 +2632,13 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] -[[package]] -name = "projected-nft-sdk" -version = "0.1.0" -source = "git+https://github.com/dcSpark/projected-nft-whirlpool.git?rev=a350ccfcbdef22b73c93561c6816bd42b13f00ff#a350ccfcbdef22b73c93561c6816bd42b13f00ff" -dependencies = [ - "cbor_event", - "cml-chain", - "cml-core", - "cml-crypto", - "hex", - "schemars", - "serde", - "serde_derive", - "serde_json", -] - [[package]] name = "prometheus" version = "0.13.3" @@ -2661,9 +2693,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -2682,7 +2714,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -2692,24 +2724,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.6.4" @@ -2719,35 +2736,20 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "wasm-bindgen", - "winapi", -] - [[package]] name = "rand_xoshiro" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" dependencies = [ - "rand_core 0.6.4", + "rand_core", ] [[package]] name = "rayon" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" dependencies = [ "either", "rayon-core", @@ -2755,23 +2757,14 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_syscall" version = "0.2.16" @@ -2803,13 +2796,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.5", "regex-syntax 0.8.2", ] @@ -2824,9 +2817,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -2859,7 +2852,10 @@ name = "reparse" version = "0.1.0" dependencies = [ "anyhow", - "cardano-multiplatform-lib", + "cml-chain 5.0.0", + "cml-core 5.0.0", + "cml-crypto 5.0.0", + "cml-multi-era", "dotenv", "entity", "futures", @@ -2910,7 +2906,7 @@ dependencies = [ "rkyv_derive", "seahash", "tinyvec", - "uuid 1.6.1", + "uuid 1.7.0", ] [[package]] @@ -2985,14 +2981,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "libc", - "linux-raw-sys 0.4.12", + "linux-raw-sys 0.4.13", "windows-sys 0.52.0", ] @@ -3002,7 +2998,7 @@ version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" dependencies = [ - "base64", + "base64 0.13.1", "log", "ring", "sct", @@ -3210,22 +3206,22 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -3241,22 +3237,31 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "serde_yaml" -version = "0.9.27" +version = "0.9.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" +checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "itoa", "ryu", "serde", @@ -3409,9 +3414,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" @@ -3468,7 +3473,7 @@ checksum = "e48c61941ccf5ddcada342cd59e3e5173b007c509e1e8e990dafc830294d9dc5" dependencies = [ "ahash", "atoi", - "base64", + "base64 0.13.1", "bitflags 1.3.2", "byteorder", "bytes", @@ -3635,9 +3640,15 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" dependencies = [ - "strum_macros", + "strum_macros 0.24.3", ] +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" + [[package]] name = "strum_macros" version = "0.24.3" @@ -3651,6 +3662,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.48", +] + [[package]] name = "subtle" version = "2.5.0" @@ -3670,9 +3694,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.41" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -3688,7 +3712,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -3715,25 +3739,26 @@ name = "tasks" version = "0.0.0" dependencies = [ "anyhow", - "cardano-multiplatform-lib", - "cfg-if 0.1.10", - "cml-chain", - "cml-core", - "cml-crypto", + "cardano-projected-nft", + "cfg-if 1.0.0", + "cml-chain 5.0.0", + "cml-core 5.0.0", + "cml-crypto 5.0.0", + "cml-multi-era", "cryptoxide", "entity", "hex", "inventory", "markdown-gen", "nameof", - "pallas", "paste", - "projected-nft-sdk", + "schemars", "sea-orm", "serde", + "serde_json", "shred", "tokio", - "toml", + "toml 0.8.8", "tracing", "tracing-subscriber", "urlencoding", @@ -3741,9 +3766,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -3765,22 +3790,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.51" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.51" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -3810,16 +3835,16 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "itoa", "powerfmt", "serde", "time-core", - "time-macros 0.2.15", + "time-macros 0.2.16", ] [[package]] @@ -3840,9 +3865,9 @@ dependencies = [ [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" dependencies = [ "time-core", ] @@ -3869,7 +3894,7 @@ dependencies = [ "ascii", "chunked_transfer", "log", - "time 0.3.30", + "time 0.3.31", "url", ] @@ -3890,9 +3915,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.0" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ "backtrace", "bytes", @@ -3915,7 +3940,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -3946,23 +3971,40 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ - "indexmap 1.9.3", "serde", ] +[[package]] +name = "toml" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +dependencies = [ + "indexmap 2.2.1", + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", + "serde", + "serde_spanned", "toml_datetime", "winnow", ] @@ -3987,7 +4029,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -4091,9 +4133,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -4178,9 +4220,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" [[package]] name = "valuable" @@ -4190,9 +4232,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.4.2" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72e1902dde2bd6441347de2b70b7f5d59bf157c6c62f0c44572607a1d55bbe" +checksum = "126e423afe2dd9ac52142e7e9d5ce4135d7e13776c529d27fd6bc49f19e3280b" [[package]] name = "vec_map" @@ -4247,9 +4289,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -4288,9 +4330,9 @@ checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -4364,11 +4406,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.0", ] [[package]] @@ -4505,9 +4547,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.28" +version = "0.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2" +checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" dependencies = [ "memchr", ] diff --git a/docs/docs/pitfalls.md b/docs/docs/pitfalls.md index 430ae021..d1b9ed29 100644 --- a/docs/docs/pitfalls.md +++ b/docs/docs/pitfalls.md @@ -23,7 +23,5 @@ sidebar_position: 1 ## Risks with using this codebase: -- **Missing functionality in binary data parsing libraries**: This codebase parses raw CBOR (binary data) from the Cardano blockchain using two libraries: Pallas and CML. It has happened in the past that one of these libraries is missing some feature of the Cardano blockchain which could cause Carp to fail if these ever appear on-chain -- **Incompatibility bugs between parsing libraries**: This project uses both Pallas and CML. Although both libraries implement some overlapping features, they are occasionally implemented differently. This should not cause any issues, but subtle implementation differences may cause issues leading to bugs in Carp -- **Cardano ledger bugs** (yes, this happens): There has been multiple occasions where the Cardano node itself has a bug in it causing the data generated not to be parsable by Pallas/CML until patched. -- **Byron-era limitations**: CML (at the time of writing) doesn't support most of Byron-era structures. We use Pallas inside Carp so they should appear in the SQL database properly, but they won't necessarily be parsable if you're reading from the database using CML. There is also some Byron-era features we didn't expose like "Epoch Boundary Blocks" (EBBs) +- **Missing functionality in binary data parsing libraries**: This codebase parses raw CBOR (binary data) from the Cardano blockchain using CML. It has happened in the past that the library is missing some feature of the Cardano blockchain which could cause Carp to fail if these ever appear on-chain. +- **Cardano ledger bugs** (yes, this happens): There has been multiple occasions where the Cardano node itself has a bug in it causing the data generated not to be parsable by CML until patched. diff --git a/indexer/Cargo.toml b/indexer/Cargo.toml index c4995877..a378edb6 100644 --- a/indexer/Cargo.toml +++ b/indexer/Cargo.toml @@ -21,13 +21,15 @@ tasks = { path = "tasks" } # [indexer] anyhow = { version = "1.0.69" } async-trait = { version = "0.1.64" } -cardano-multiplatform-lib = { git = "https://github.com/dcSpark/cardano-multiplatform-lib", branch = "metadata-and-addr" } +cml-chain = { version = "5.0.0" } +cml-core = { version = "5.0.0" } +cml-crypto = { version = "5.0.0" } +cml-multi-era = { version = "5.0.0" } clap = { version = "3.1", features = ["derive"] } ctrlc = { version = "3.2.4", features = ["termination"] } dotenv = { version = "0.15.0" } hex = { version = "0.4.3" } oura = { git = "https://github.com/txpipe/oura.git", rev = "27fb7e876471b713841d96e292ede40101b151d7" } -pallas = { version = "0.18.2" } serde = { version = "1.0.152", features = ["derive", "rc"] } serde_json = { version = "1.0.92" } serde_yaml = { version = "0.9.17" } diff --git a/indexer/configs/cardano_node.yml b/indexer/configs/cardano_node.yml index b39261bb..e83d5e3a 100644 --- a/indexer/configs/cardano_node.yml +++ b/indexer/configs/cardano_node.yml @@ -1,12 +1,12 @@ source: type: cardano_net - relay: + relay: - relays-new.cardano-mainnet.iohk.io - 3001 # - preview-node.world.dev.cardano.org # - 30002 # - preprod-node.world.dev.cardano.org - # - 30000 + # - 30000 sink: type: cardano diff --git a/indexer/entity/Cargo.toml b/indexer/entity/Cargo.toml index f82df5f3..78547141 100644 --- a/indexer/entity/Cargo.toml +++ b/indexer/entity/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -pallas = { version = "0.18.2" } sea-orm = { git = "https://github.com/dcSpark/sea-orm", branch = "insert-many-returning", features = [ "runtime-tokio-rustls", "sqlx-postgres", diff --git a/indexer/entity/src/block.rs b/indexer/entity/src/block.rs index b149fe02..000219a8 100644 --- a/indexer/entity/src/block.rs +++ b/indexer/entity/src/block.rs @@ -1,4 +1,3 @@ -use pallas::ledger::traverse::Era; use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; @@ -31,6 +30,7 @@ pub enum EraValue { Mary, Alonzo, Babbage, + Conway, } impl From for i32 { @@ -42,6 +42,7 @@ impl From for i32 { EraValue::Mary => 3, EraValue::Alonzo => 4, EraValue::Babbage => 5, + EraValue::Conway => 6, } } } @@ -57,20 +58,8 @@ impl TryFrom for EraValue { 3 => Ok(EraValue::Mary), 4 => Ok(EraValue::Alonzo), 5 => Ok(EraValue::Babbage), + 6 => Ok(EraValue::Conway), _ => Err(()), } } } - -impl From for Era { - fn from(item: EraValue) -> Self { - match item { - EraValue::Byron => Era::Byron, - EraValue::Shelley => Era::Shelley, - EraValue::Allegra => Era::Allegra, - EraValue::Mary => Era::Mary, - EraValue::Alonzo => Era::Alonzo, - EraValue::Babbage => Era::Babbage, - } - } -} diff --git a/indexer/plan-visualizer/Cargo.toml b/indexer/plan-visualizer/Cargo.toml index 24d376b4..5b28e10c 100644 --- a/indexer/plan-visualizer/Cargo.toml +++ b/indexer/plan-visualizer/Cargo.toml @@ -12,8 +12,8 @@ tasks = { path = "../tasks" } anyhow = { version = "1.0.69" } clap = { version = "3.1", features = ["derive"] } dot = { git = "https://github.com/dcSpark/dot-rust", branch = "subgraph" } -strum = { version = "0.24" } -strum_macros = { version = "0.24" } -toml = { version = "0.5", features = ["preserve_order"] } +strum = { version = "0.25.0" } +strum_macros = { version = "0.25.3" } +toml = { version = "0.8.6", features = ["preserve_order"] } tracing = { version = "0.1.37" } tracing-subscriber = { version = "0.3.16" } diff --git a/indexer/reparse/Cargo.toml b/indexer/reparse/Cargo.toml index eda819b7..89fe41c7 100644 --- a/indexer/reparse/Cargo.toml +++ b/indexer/reparse/Cargo.toml @@ -10,7 +10,10 @@ entity = { path = "../entity" } # [reparse] anyhow = { version = "1.0.69" } -cardano-multiplatform-lib = { git = "https://github.com/dcSpark/cardano-multiplatform-lib", branch = "metadata-and-addr" } +cml-chain = { version = "5.0.0" } +cml-core = { version = "5.0.0" } +cml-crypto = { version = "5.0.0" } +cml-multi-era = { version = "5.0.0" } dotenv = { version = "0.15.0" } futures = { version = "0.3.21" } hex = { version = "0.4.0" } diff --git a/indexer/reparse/src/reparse.rs b/indexer/reparse/src/reparse.rs index 9f63734e..af32c407 100644 --- a/indexer/reparse/src/reparse.rs +++ b/indexer/reparse/src/reparse.rs @@ -1,3 +1,4 @@ +use cml_core::serialization::FromBytes; use entity::{ prelude::*, sea_orm::{prelude::*, JoinType, QueryOrder, QuerySelect}, @@ -34,8 +35,7 @@ async fn reparse_txs(conn: &DatabaseConnection, start_index: u64) -> Result<(), for tx in txs { // TODO: this will fail on all Byron txs // https://github.com/dcSpark/cardano-multiplatform-lib/issues/61 - if let Err(e) = &cardano_multiplatform_lib::Transaction::from_bytes(tx.payload.clone()) - { + if let Err(e) = &cml_chain::transaction::Transaction::from_bytes(tx.payload.clone()) { println!( "\nFailed tx at tx hash {}. {:?} {}\n", hex::encode(&tx.hash), @@ -65,9 +65,7 @@ async fn reparse_addresses(conn: &DatabaseConnection, start_index: u64) -> Resul (100.0 * addresses.first().unwrap().id as f64) / (address_count as f64) ); for addr in addresses { - if let Err(e) = - &cardano_multiplatform_lib::address::Address::from_bytes(addr.payload.clone()) - { + if let Err(e) = &cml_chain::address::Address::from_bytes(addr.payload.clone()) { let bad_tx = Transaction::find() .join( JoinType::InnerJoin, @@ -119,7 +117,7 @@ async fn reparse_tx_out(conn: &DatabaseConnection, start_index: u64) -> Result<( // TODO: this will fail on all Byron txs // https://github.com/dcSpark/cardano-multiplatform-lib/issues/61 if let Err(e) = - &cardano_multiplatform_lib::TransactionOutput::from_bytes(tx_out.payload.clone()) + &cml_chain::transaction::TransactionOutput::from_bytes(tx_out.payload.clone()) { let bad_tx = Transaction::find() .join( diff --git a/indexer/src/benchmark.rs b/indexer/src/benchmark.rs deleted file mode 100644 index 6a79c050..00000000 --- a/indexer/src/benchmark.rs +++ /dev/null @@ -1,63 +0,0 @@ -use entity::{ - prelude::*, - sea_orm::{prelude::*, ColumnTrait, DatabaseTransaction, TransactionTrait}, -}; -use migration::DbErr; -use oura::pipelining::StageReceiver; - -pub struct Config<'a> { - pub conn: &'a DatabaseConnection, -} - -impl<'a> Config<'a> { - pub async fn bootstrap(&self, _input: StageReceiver) -> anyhow::Result<()> { - tracing::info!("{}", "Starting to process blocks"); - - self.conn - .transaction::<_, (), DbErr>(|txn| Box::pin(benchmark(txn))) - .await?; - - Ok(()) - } -} - -async fn benchmark(txn: &DatabaseTransaction) -> Result<(), DbErr> { - println!( - "{:?}", - "8200581cff57a0bbcaaada72b6e3d6d9044c420d1a8dd97794884d39021f1e".to_owned() - + &format!("{:02}", 0) - ); - - let creds = (0..100).map(|i| { - hex::decode( - "8200581cff57a0bbcaaada72b6e3d6d9044c420d1a8dd97794884d39021f1e".to_owned() - + &format!("{:02}", i), - ) - .unwrap() - }); - - let time_counter = std::time::Instant::now(); - - // for i in 0..100 { - // StakeCredential::find() - // .filter( - // StakeCredentialColumn::Credential.eq(hex::decode( - // "8200581cff57a0bbcaaada72b6e3d6d9044c420d1a8dd97794884d39021f1ea3", - // ) - // .unwrap()), - // ) - // // note: we know this exists ("credential" is unique) and "all" is faster than "one" if we know the result exists - // .all(txn) - // .await?; - // } - - let mut base = StakeCredential::find(); - for cred in creds { - base = base.filter(StakeCredentialColumn::Credential.eq(cred)) - } - base.all(txn).await?; - - println!("{:?}", time_counter.elapsed()); - // ~38 - Ok(()) -} diff --git a/indexer/src/genesis.rs b/indexer/src/genesis.rs index 2ed90fc1..8d5ed3cc 100644 --- a/indexer/src/genesis.rs +++ b/indexer/src/genesis.rs @@ -4,7 +4,10 @@ use std::fs; use std::sync::{Arc, Mutex}; use tasks::dsl::database_task::BlockGlobalInfo; -use cardano_multiplatform_lib::genesis::byron::{config::GenesisData, parse::parse}; +use cml_chain::genesis::byron::config::GenesisData; +use cml_chain::genesis::byron::parse::parse_genesis_data; + +use cml_crypto::RawBytesEncoding; use entity::sea_orm::{DatabaseConnection, DatabaseTransaction, TransactionTrait}; use migration::DbErr; use tasks::utils::TaskPerfAggregator; @@ -40,7 +43,9 @@ pub async fn process_genesis( let mut time_counter = std::time::Instant::now(); let file = fs::File::open(genesis_path).expect("Failed to open genesis file"); - let genesis_file: Box = Box::new(parse(file)); + let genesis_file: Box = Box::new( + parse_genesis_data(file).map_err(|err| anyhow!("can't parse genesis data: {:?}", err))?, + ); tracing::info!( "Finished parsing genesis file after {:?}", @@ -77,10 +82,10 @@ pub async fn insert_genesis( exec_plan: Arc, task_perf_aggregator: Arc>, ) -> Result<(), DbErr> { - let genesis_hash = genesis_file.genesis_prev.to_bytes(); + let genesis_hash = genesis_file.genesis_prev.to_raw_bytes(); tracing::info!( "Starting sync based on genesis hash {}", - hex::encode(genesis_hash.clone()) + hex::encode(genesis_hash) ); let block_global_info = BlockGlobalInfo { diff --git a/indexer/src/sinks/cardano.rs b/indexer/src/sinks/cardano.rs index 1e9f4551..7b45cc64 100644 --- a/indexer/src/sinks/cardano.rs +++ b/indexer/src/sinks/cardano.rs @@ -4,6 +4,7 @@ use crate::sink::Sink; use crate::types::{MultiEraBlock, StoppableService}; use crate::{genesis, DbConfig, SinkConfig}; use async_trait::async_trait; + use dcspark_blockchain_source::cardano::Point; use dcspark_core::{BlockId, SlotNumber}; use entity::sea_orm::Database; @@ -254,14 +255,14 @@ impl StoppableService for CardanoSink { } } -fn to_era_value(x: pallas::ledger::traverse::Era) -> EraValue { +fn to_era_value(x: &MultiEraBlock) -> EraValue { match x { - pallas::ledger::traverse::Era::Byron => EraValue::Byron, - pallas::ledger::traverse::Era::Shelley => EraValue::Shelley, - pallas::ledger::traverse::Era::Allegra => EraValue::Allegra, - pallas::ledger::traverse::Era::Mary => EraValue::Mary, - pallas::ledger::traverse::Era::Alonzo => EraValue::Alonzo, - pallas::ledger::traverse::Era::Babbage => EraValue::Babbage, + MultiEraBlock::Byron(_) => EraValue::Byron, + MultiEraBlock::Shelley(_) => EraValue::Shelley, + MultiEraBlock::Allegra(_) => EraValue::Allegra, + MultiEraBlock::Mary(_) => EraValue::Mary, + MultiEraBlock::Alonzo(_) => EraValue::Alonzo, + MultiEraBlock::Babbage(_) => EraValue::Babbage, _ => unreachable!("all known eras are handled"), } } @@ -279,18 +280,18 @@ async fn insert_block( let block_parse_counter = std::time::Instant::now(); let block_payload = hex::decode(cbor_hex.clone()).unwrap(); - let multi_block = MultiEraBlock::decode(&block_payload).unwrap(); + let multi_block = MultiEraBlock::from_explicit_network_cbor_bytes(&block_payload).unwrap(); let block_global_info = BlockGlobalInfo { - era: to_era_value(multi_block.era()), + era: to_era_value(&multi_block), epoch, epoch_slot, }; perf_aggregator.block_parse += block_parse_counter.elapsed(); - match &multi_block.era() { - pallas::ledger::traverse::Era::Byron => { + match &multi_block { + MultiEraBlock::Byron(_byron) => { process_byron_block( txn, (&cbor_hex, &multi_block, &block_global_info), diff --git a/indexer/src/types.rs b/indexer/src/types.rs index 66d1e6fa..1cebd95f 100644 --- a/indexer/src/types.rs +++ b/indexer/src/types.rs @@ -1,6 +1,6 @@ use async_trait::async_trait; -pub type MultiEraBlock<'b> = pallas::ledger::traverse::MultiEraBlock<'b>; +pub type MultiEraBlock = cml_multi_era::MultiEraBlock; #[async_trait] pub trait StoppableService { diff --git a/indexer/tasks/Cargo.toml b/indexer/tasks/Cargo.toml index 5c561edf..6adbe901 100644 --- a/indexer/tasks/Cargo.toml +++ b/indexer/tasks/Cargo.toml @@ -12,24 +12,25 @@ entity = { path = "../entity" } # [tasks] anyhow = { version = "1.0.69" } -cardano-multiplatform-lib = { git = "https://github.com/dcSpark/cardano-multiplatform-lib", branch = "metadata-and-addr" } -cml-chain = { git = "https://github.com/dcSpark/cardano-multiplatform-lib", rev = "acca172633d0570a7432058aa5b0717ad2f0c6d7" } -cml-core = { git = "https://github.com/dcSpark/cardano-multiplatform-lib", rev = "acca172633d0570a7432058aa5b0717ad2f0c6d7" } -cml-crypto = { git = "https://github.com/dcSpark/cardano-multiplatform-lib", rev = "acca172633d0570a7432058aa5b0717ad2f0c6d7" } -projected-nft-sdk = { git = "https://github.com/dcSpark/projected-nft-whirlpool.git", rev = "a350ccfcbdef22b73c93561c6816bd42b13f00ff" } -cfg-if = { version = "0.1.10" } +cml-chain = { version = "5.0.0" } +cml-core = { version = "5.0.0" } +cml-crypto = { version = "5.0.0" } +cml-multi-era = { version = "5.0.0" } +cardano-projected-nft = { git = "https://github.com/dcSpark/projected-nft-whirlpool.git", rev = "13f81e8666743fefd14c5e1affb1cd828d8c473b" } +cfg-if = { version = "1.0.0" } cryptoxide = { version = "0.4.2" } hex = { version = "0.4.3" } inventory = { version = "0.2.3" } markdown-gen = { git = "https://github.com/dcSpark/markdown-gen-rs", branch = "hbina-add-ability-to-write-raw-str" } nameof = { version = "1.2.2" } -pallas = { version = "0.18.2" } paste = { version = "1.0.11" } sea-orm = { git = "https://github.com/dcSpark/sea-orm", branch = "insert-many-returning", features = [ "macros" ], default-features = false } serde = { version = "1.0.152", features = ["derive"] } +serde_json = { version = "1.0.108" } +schemars = { version = "0.8.8" } shred = { git = "https://github.com/dcSpark/shred", branch = "builder-getters" } tokio = { version = "1.16.1", features = ["full"] } -toml = { version = "0.5", features = ["preserve_order"] } +toml = { version = "0.8.6", features = ["preserve_order"] } urlencoding = { version = "2.1.2" } tracing-subscriber = { version = "0.3.16" } tracing = { version = "0.1.37" } diff --git a/indexer/tasks/src/byron/byron_address.rs b/indexer/tasks/src/byron/byron_address.rs index c2787d9c..7b1f1704 100644 --- a/indexer/tasks/src/byron/byron_address.rs +++ b/indexer/tasks/src/byron/byron_address.rs @@ -1,7 +1,6 @@ -use pallas::ledger::primitives::{ - byron::{self}, - Fragment, -}; +use cml_core::serialization::ToBytes; +use cml_multi_era::byron::block::ByronBlock; +use cml_multi_era::MultiEraBlock; use super::byron_txs::ByronTransactionTask; use crate::config::EmptyConfig::EmptyConfig; @@ -18,14 +17,7 @@ carp_task! { write [byron_addresses]; should_add_task |block, _properties| { // recall: txs may have no outputs if they just burn all inputs as fee - match block.1 { - MultiEraBlock::Byron(main_block) => { - main_block - .body - .tx_payload.iter().any(|payload| payload.transaction.outputs.len() > 0) - } - _ => false, - } + block.1.transaction_bodies().iter().any(|tx| !tx.outputs().is_empty()) }; execute |previous_data, task| handle_addresses( task.db_tx, @@ -39,16 +31,21 @@ carp_task! { async fn handle_addresses( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, byron_txs: &[TransactionModel], ) -> Result, AddressInBlock>, DbErr> { match &block.1 { MultiEraBlock::Byron(main_block) => { - let tx_outputs: Vec<_> = main_block - .body - .tx_payload + let payload = match main_block { + ByronBlock::Main(main) => main.body.tx_payload.clone(), + ByronBlock::EpochBoundary(_) => { + return Ok(BTreeMap::, AddressInBlock>::default()); + } + }; + + let tx_outputs: Vec<_> = payload .iter() - .map(|payload| &payload.transaction.outputs) + .map(|payload| &payload.byron_tx.outputs) .zip(byron_txs) .collect(); @@ -60,7 +57,7 @@ async fn handle_addresses( for (address, tx_id) in tx_outputs .iter() .flat_map(|pair| pair.0.iter().zip(std::iter::repeat(pair.1.id))) - .map(|(output, tx_id)| (output.address.encode_fragment().unwrap(), tx_id)) + .map(|(output, tx_id)| (output.address.to_bytes(), tx_id)) { // we want to keep track of the first tx for each address queued_address.entry(address).or_insert(tx_id); diff --git a/indexer/tasks/src/byron/byron_block.rs b/indexer/tasks/src/byron/byron_block.rs index e79b3cf1..b6667a95 100644 --- a/indexer/tasks/src/byron/byron_block.rs +++ b/indexer/tasks/src/byron/byron_block.rs @@ -1,9 +1,12 @@ use crate::config::PayloadAndReadonlyConfig::PayloadAndReadonlyConfig; use crate::dsl::task_macro::*; use crate::era_common::block_from_hash; +use cml_core::serialization::ToBytes; +use cml_crypto::{blake2b256, RawBytesEncoding}; +use cml_multi_era::byron::block::ByronBlock; +use cml_multi_era::MultiEraBlock; use entity::{block::EraValue, sea_orm::Set}; use hex::ToHex; -use pallas::ledger::primitives::{byron, Fragment}; carp_task! { name ByronBlockTask; @@ -29,15 +32,26 @@ carp_task! { async fn handle_block( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, readonly: bool, include_payload: bool, ) -> Result { - let hash = block.1.hash().to_vec(); + let hash = block.1.hash(); + if readonly { return block_from_hash(db_tx, &hash).await; } + let block_epoch = match block.1 { + MultiEraBlock::Byron(byron) => match byron { + ByronBlock::EpochBoundary(byron) => byron.header.consensus_data.epoch_id, + ByronBlock::Main(byron) => byron.header.consensus_data.byron_slot_id.epoch, + }, + _ => { + return Err(DbErr::Custom("Non-byron block in byron task".to_string())); + } + }; + let block_payload = if include_payload { hex::decode(block.0).unwrap() } else { @@ -45,10 +59,10 @@ async fn handle_block( }; let block = BlockActiveModel { era: Set(EraValue::Byron.into()), - hash: Set(hash), - height: Set(block.1.number() as i32), - epoch: Set(block.1.header().as_byron().unwrap().consensus_data.0.epoch as i32), - slot: Set(block.1.slot() as i32), + hash: Set(hash.to_vec()), + height: Set(block.1.header().block_number() as i32), + epoch: Set(block_epoch as i32), + slot: Set(block.1.header().slot() as i32), payload: Set(Some(block_payload)), ..Default::default() }; diff --git a/indexer/tasks/src/byron/byron_executor.rs b/indexer/tasks/src/byron/byron_executor.rs index 0d679878..3cf1e91a 100644 --- a/indexer/tasks/src/byron/byron_executor.rs +++ b/indexer/tasks/src/byron/byron_executor.rs @@ -6,14 +6,12 @@ use crate::execution_plan::ExecutionPlan; use crate::utils::find_task_registry_entry; use crate::utils::TaskPerfAggregator; use entity::sea_orm::{prelude::*, DatabaseTransaction}; -use pallas::ledger::primitives::byron::{self}; -use pallas::ledger::traverse::MultiEraBlock; use shred::{DispatcherBuilder, World}; use tokio::runtime::Handle; pub async fn process_byron_block( txn: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, exec_plan: &ExecutionPlan, perf_aggregator: Arc>, ) -> Result<(), DbErr> { diff --git a/indexer/tasks/src/byron/byron_inputs.rs b/indexer/tasks/src/byron/byron_inputs.rs index 436bb4bc..26021502 100644 --- a/indexer/tasks/src/byron/byron_inputs.rs +++ b/indexer/tasks/src/byron/byron_inputs.rs @@ -1,5 +1,8 @@ use crate::dsl::task_macro::*; -use pallas::ledger::primitives::byron::{self, TxIn}; +use cml_multi_era::byron::block::ByronBlock; +use cml_multi_era::byron::transaction::{ByronTx, ByronTxIn}; +use cml_multi_era::utils::MultiEraTransactionInput; +use cml_multi_era::MultiEraBlock; use super::byron_outputs::ByronOutputTask; use crate::config::EmptyConfig::EmptyConfig; @@ -29,20 +32,25 @@ carp_task! { async fn handle_inputs( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, MultiEraBlock, BlockGlobalInfo>, byron_txs: &[TransactionModel], ) -> Result, DbErr> { - let flattened_inputs: Vec<(Vec, i64)> = block - .1 - .txs() - .iter() - .zip(byron_txs) - .map(|(tx, cardano_tx_in_db)| { - let inputs: Vec = - tx.inputs().iter().map(|x| x.output_ref()).collect(); + let txs = match block.1 { + MultiEraBlock::Byron(ByronBlock::Main(block)) => block.body.tx_payload.iter().map(|tx| { + tx.byron_tx + .inputs + .iter() + .cloned() + .map(MultiEraTransactionInput::Byron) + }), + _ => { + return Ok(vec![]); + } + }; - (inputs, cardano_tx_in_db.id) - }) + let flattened_inputs: Vec<(Vec<_>, i64)> = txs + .zip(byron_txs) + .map(|(inputs, cardano_tx_in_db)| (inputs.collect::>(), cardano_tx_in_db.id)) .collect(); let outputs_for_inputs = diff --git a/indexer/tasks/src/byron/byron_outputs.rs b/indexer/tasks/src/byron/byron_outputs.rs index 75534713..8a73d50d 100644 --- a/indexer/tasks/src/byron/byron_outputs.rs +++ b/indexer/tasks/src/byron/byron_outputs.rs @@ -2,15 +2,11 @@ use super::byron_address::ByronAddressTask; use crate::config::EmptyConfig::EmptyConfig; use crate::dsl::database_task::BlockGlobalInfo; use crate::{dsl::task_macro::*, era_common::get_truncated_address}; +use cml_chain::byron::ByronTxOut; +use cml_core::serialization::ToBytes; +use cml_multi_era::byron::block::ByronBlock; +use cml_multi_era::MultiEraBlock; use entity::sea_orm::Set; -use pallas::ledger::traverse::MultiEraOutput; -use pallas::{ - codec::utils::MaybeIndefArray, - ledger::primitives::{ - byron::{self, TxOut}, - Fragment, - }, -}; carp_task! { name ByronOutputTask; @@ -22,7 +18,7 @@ carp_task! { write [byron_outputs]; should_add_task |block, _properties| { // recall: txs may have no outputs if they just burn all inputs as fee - block.1.txs().iter().any(|tx| tx.outputs().len() > 0) + block.1.transaction_bodies().iter().any(|tx| !tx.outputs().is_empty()) }; execute |previous_data, task| handle_outputs( task.db_tx, @@ -37,20 +33,20 @@ carp_task! { async fn handle_outputs( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, byron_txs: &[TransactionModel], byron_addresses: &BTreeMap, AddressInBlock>, ) -> Result, DbErr> { - let tx_outputs: Vec<_> = block - .1 - .as_byron() - .unwrap() - .body - .tx_payload - .iter() - .map(|payload| &payload.transaction.outputs) - .zip(byron_txs) - .collect(); + let tx_outputs: Vec<_> = match block.1 { + MultiEraBlock::Byron(ByronBlock::Main(block)) => block + .body + .tx_payload + .iter() + .map(|payload| &payload.byron_tx.outputs) + .zip(byron_txs) + .collect(), + _ => return Ok(vec![]), + }; if tx_outputs.is_empty() { return Ok(vec![]); @@ -63,7 +59,7 @@ async fn handle_outputs( async fn insert_byron_outputs( txn: &DatabaseTransaction, address_map: &BTreeMap, AddressInBlock>, - outputs: &[(&MaybeIndefArray, &TransactionModel)], + outputs: &[(&Vec, &TransactionModel)], ) -> Result, DbErr> { let result = TransactionOutput::insert_many( outputs @@ -71,11 +67,9 @@ async fn insert_byron_outputs( .flat_map(|pair| pair.0.iter().enumerate().zip(std::iter::repeat(pair.1))) .map( |((output_index, output), tx_id)| TransactionOutputActiveModel { - payload: Set(output.encode_fragment().unwrap()), + payload: Set(output.to_bytes()), address_id: Set(address_map - .get(get_truncated_address( - &output.address.encode_fragment().unwrap(), - )) + .get(get_truncated_address(&output.address.to_bytes())) .unwrap() .model .id), diff --git a/indexer/tasks/src/byron/byron_txs.rs b/indexer/tasks/src/byron/byron_txs.rs index 3da63c4c..aef93c48 100644 --- a/indexer/tasks/src/byron/byron_txs.rs +++ b/indexer/tasks/src/byron/byron_txs.rs @@ -1,6 +1,8 @@ use crate::{dsl::task_macro::*, era_common::transactions_from_hashes, utils::blake2b256}; +use cml_core::serialization::ToBytes; +use cml_multi_era::byron::block::ByronBlock; +use cml_multi_era::MultiEraBlock; use entity::sea_orm::Set; -use pallas::ledger::primitives::{byron, Fragment}; use super::byron_block::ByronBlockTask; use crate::config::PayloadAndReadonlyConfig::PayloadAndReadonlyConfig; @@ -31,7 +33,7 @@ carp_task! { async fn handle_tx( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, database_block: &BlockModel, readonly: bool, include_payload: bool, @@ -41,22 +43,34 @@ async fn handle_tx( } if readonly { - let tx_hashes = block - .1 - .txs() - .iter() - .map(|tx| tx.hash().to_vec()) - .collect::>(); + let tx_hashes = match block.1 { + MultiEraBlock::Byron(ByronBlock::Main(main)) => main + .body + .tx_payload + .iter() + .map(|tx| tx.byron_tx.hash().to_vec()) + .collect::>>(), + _ => vec![], + }; let txs = transactions_from_hashes(db_tx, &tx_hashes).await; return txs; } + let transactions = match block.1 { + MultiEraBlock::Byron(ByronBlock::Main(main)) => main.body.tx_payload.clone(), + _ => vec![], + }; + let transaction_inserts = - Transaction::insert_many(block.1.txs().iter().enumerate().map(|(idx, tx)| { - let tx_payload = if include_payload { tx.encode() } else { vec![] }; + Transaction::insert_many(transactions.iter().enumerate().map(|(idx, tx)| { + let tx_payload = if include_payload { + tx.to_bytes() + } else { + vec![] + }; TransactionActiveModel { - hash: Set(tx.hash().to_vec()), + hash: Set(tx.byron_tx.hash().to_vec()), block_id: Set(database_block.id), tx_index: Set(idx as i32), payload: Set(tx_payload), diff --git a/indexer/tasks/src/config/AddressConfig.rs b/indexer/tasks/src/config/AddressConfig.rs index 3648a934..150ad401 100644 --- a/indexer/tasks/src/config/AddressConfig.rs +++ b/indexer/tasks/src/config/AddressConfig.rs @@ -1,7 +1,3 @@ -use pallas::ledger::addresses::Address; -use pallas::ledger::primitives::alonzo::PlutusScript; -use pallas::ledger::primitives::babbage::PlutusV2Script; - #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] pub struct AddressConfig { pub address: String, diff --git a/indexer/tasks/src/dsl/database_task.rs b/indexer/tasks/src/dsl/database_task.rs index ca9858fc..0cb81b13 100644 --- a/indexer/tasks/src/dsl/database_task.rs +++ b/indexer/tasks/src/dsl/database_task.rs @@ -1,7 +1,6 @@ use crate::utils::TaskPerfAggregator; -use cardano_multiplatform_lib::genesis::byron::config::GenesisData; +use cml_chain::genesis::byron::config::GenesisData; use entity::{block::EraValue, prelude::*, sea_orm::DatabaseTransaction}; -use pallas::ledger::traverse::MultiEraBlock; use shred::DispatcherBuilder; use std::sync::{Arc, Mutex}; @@ -67,12 +66,14 @@ pub struct GenesisTaskRegistryEntry { #[derive(Copy, Clone)] pub struct ByronTaskRegistryEntry { - pub builder: &'static (dyn for<'a> TaskBuilder<'a, MultiEraBlock<'a>, BlockGlobalInfo> + Sync), + pub builder: &'static (dyn for<'a> TaskBuilder<'a, cml_multi_era::MultiEraBlock, BlockGlobalInfo> + + Sync), } #[derive(Copy, Clone)] pub struct MultieraTaskRegistryEntry { - pub builder: &'static (dyn for<'a> TaskBuilder<'a, MultiEraBlock<'a>, BlockGlobalInfo> + Sync), + pub builder: &'static (dyn for<'a> TaskBuilder<'a, cml_multi_era::MultiEraBlock, BlockGlobalInfo> + + Sync), } inventory::collect!(TaskRegistryEntry); diff --git a/indexer/tasks/src/dsl/example_task.rs b/indexer/tasks/src/dsl/example_task.rs index 376a1e97..af02aff7 100644 --- a/indexer/tasks/src/dsl/example_task.rs +++ b/indexer/tasks/src/dsl/example_task.rs @@ -42,7 +42,7 @@ carp_task! { async fn handle_dummy( _db_tx: &DatabaseTransaction, - _block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + _block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, ) -> Result<(), DbErr> { Ok(()) } diff --git a/indexer/tasks/src/dsl/task_macro.rs b/indexer/tasks/src/dsl/task_macro.rs index d482b39e..8ec1f8c8 100644 --- a/indexer/tasks/src/dsl/task_macro.rs +++ b/indexer/tasks/src/dsl/task_macro.rs @@ -8,8 +8,7 @@ pub use crate::{ era_common::AddressInBlock, utils::TaskPerfAggregator, }; -pub use cardano_multiplatform_lib::genesis::byron::config::GenesisData; -pub use pallas::ledger::traverse::MultiEraBlock; +pub use cml_chain::genesis::byron::config::GenesisData; pub use paste::paste; pub use shred::{DispatcherBuilder, Read, ResourceId, System, SystemData, World, Write}; pub use std::sync::{Arc, Mutex}; @@ -19,10 +18,10 @@ macro_rules! era_to_block { GenesisData }; (byron) => { - MultiEraBlock<'a> + cml_multi_era::MultiEraBlock }; (multiera) => { - MultiEraBlock<'a> + cml_multi_era::MultiEraBlock }; } diff --git a/indexer/tasks/src/era_common.rs b/indexer/tasks/src/era_common.rs index 896b22d8..50997d1a 100644 --- a/indexer/tasks/src/era_common.rs +++ b/indexer/tasks/src/era_common.rs @@ -1,5 +1,7 @@ use std::collections::BTreeSet; +use cml_crypto::RawBytesEncoding; +use cml_multi_era::byron::transaction::ByronTxIn; use entity::{ block::EraValue, prelude::*, @@ -8,7 +10,6 @@ use entity::{ QueryOrder, QuerySelect, Set, }, }; -use pallas::ledger::traverse::Era; use std::collections::BTreeMap; static ADDRESS_TRUNCATE: usize = 500; // 1000 in hex @@ -120,11 +121,11 @@ pub async fn insert_addresses( pub struct OutputWithTxData { pub model: TransactionOutputModel, pub tx_hash: Vec, - pub era: Era, + pub era: EraValue, } pub async fn get_outputs_for_inputs( - inputs: &[(Vec, i64)], + inputs: &[(Vec, i64)], txn: &DatabaseTransaction, ) -> Result, DbErr> { // avoid querying the DB if there were no inputs @@ -140,10 +141,18 @@ pub async fn get_outputs_for_inputs( // so we know all these pairs are disjoint amongst all transactions // https://github.com/dcSpark/carp/issues/46 for input in inputs.iter().flat_map(|inputs| inputs.0.iter()) { + let index = match input.index() { + None => return Err(DbErr::Custom("no output index".to_string())), + Some(index) => index, + }; + let hash = match input.hash() { + None => return Err(DbErr::Custom("no output hash".to_string())), + Some(hash) => *hash, + }; output_conditions = output_conditions.add( Condition::all() - .add(TransactionOutputColumn::OutputIndex.eq(input.index())) - .add(TransactionColumn::Hash.eq(input.hash().to_vec())), + .add(TransactionOutputColumn::OutputIndex.eq(index)) + .add(TransactionColumn::Hash.eq(hash.to_raw_bytes().to_vec())), ); } @@ -194,9 +203,7 @@ pub async fn get_outputs_for_inputs( output_index: output.output_index, }, tx_hash: output.tx_hash.clone(), - era: >::try_into(output.era) - .unwrap() - .into(), + era: >::try_into(output.era).unwrap(), }) .collect::>()) } @@ -224,7 +231,7 @@ pub fn gen_input_to_output_map( } pub async fn insert_inputs( - inputs: &[(Vec, i64)], + inputs: &[(Vec, i64)], input_to_output_map: &BTreeMap, BTreeMap>, txn: &DatabaseTransaction, ) -> Result, DbErr> { @@ -239,11 +246,13 @@ pub async fn insert_inputs( .iter() .flat_map(|pair| pair.0.iter().enumerate().zip(std::iter::repeat(pair.1))) .map(|((idx, input), tx_id)| { - let tx_outputs = match input_to_output_map.get(&input.hash().to_vec()) { + let input_hash = input.hash().unwrap().to_raw_bytes().to_vec(); + let input_index = input.index().unwrap() as i64; + let tx_outputs = match input_to_output_map.get(&input_hash) { Some(outputs) => outputs, - None => panic!("Failed to find transaction {}", &hex::encode(input.hash())), + None => panic!("Failed to find transaction {}", &hex::encode(input_hash)), }; - let output = &tx_outputs[&(input.index() as i64)]; + let output = &tx_outputs[&input_index]; TransactionInputActiveModel { utxo_id: Set(output.model.id), address_id: Set(output.model.address_id), diff --git a/indexer/tasks/src/genesis/genesis_block.rs b/indexer/tasks/src/genesis/genesis_block.rs index a0dcd221..c2dabbce 100644 --- a/indexer/tasks/src/genesis/genesis_block.rs +++ b/indexer/tasks/src/genesis/genesis_block.rs @@ -1,5 +1,7 @@ use crate::config::PayloadConfig::PayloadConfig; use crate::dsl::task_macro::*; +use cml_core::serialization::ToBytes; +use cml_crypto::RawBytesEncoding; use entity::{block::EraValue, sea_orm::Set}; use hex::ToHex; @@ -29,7 +31,7 @@ async fn handle_block( block: BlockInfo<'_, GenesisData, BlockGlobalInfo>, include_payload: bool, ) -> Result { - let genesis_hash = block.1.genesis_prev.to_bytes(); + let genesis_hash = block.1.genesis_prev.to_raw_bytes().to_vec(); let block_payload = if include_payload { hex::decode(block.0).unwrap() diff --git a/indexer/tasks/src/genesis/genesis_executor.rs b/indexer/tasks/src/genesis/genesis_executor.rs index 642a28fd..6c9f7c7e 100644 --- a/indexer/tasks/src/genesis/genesis_executor.rs +++ b/indexer/tasks/src/genesis/genesis_executor.rs @@ -5,7 +5,7 @@ use crate::dsl::database_task::{BlockGlobalInfo, BlockInfo}; use crate::execution_plan::ExecutionPlan; use crate::utils::find_task_registry_entry; use crate::utils::TaskPerfAggregator; -use cardano_multiplatform_lib::genesis::byron::config::GenesisData; +use cml_chain::genesis::byron::config::GenesisData; use entity::sea_orm::{prelude::*, DatabaseTransaction}; use shred::{DispatcherBuilder, World}; use tokio::runtime::Handle; diff --git a/indexer/tasks/src/genesis/genesis_txs.rs b/indexer/tasks/src/genesis/genesis_txs.rs index 21e14525..9e9db956 100644 --- a/indexer/tasks/src/genesis/genesis_txs.rs +++ b/indexer/tasks/src/genesis/genesis_txs.rs @@ -1,11 +1,12 @@ extern crate shred; use crate::config::PayloadConfig::PayloadConfig; -use cardano_multiplatform_lib::{ +use cml_chain::{ byron::ByronAddress, genesis::byron::{config::GenesisData, parse::redeem_pubkey_to_txid}, - ledger::common::value::Value, }; +use cml_core::serialization::ToBytes; +use cml_crypto::RawBytesEncoding; use entity::{ prelude::*, sea_orm::{DatabaseTransaction, DbErr, EntityTrait, Set}, @@ -63,7 +64,7 @@ async fn handle_txs( // note: genesis file is a JSON structure, so there shouldn't be duplicate addresses // even across avvm and non-avvm it should be unique, otherwise two txs with the same tx hash would exist let mut addresses: Vec AddressActiveModel>> = vec![]; - let mut outputs: Vec = vec![]; + let mut outputs: Vec = vec![]; for (pub_key, amount) in block.1.avvm_distr.iter() { let (tx_hash, byron_addr) = redeem_pubkey_to_txid(pub_key, Some(block.1.protocol_magic)); @@ -77,7 +78,7 @@ async fn handle_txs( let tx_index = transactions.len() as i32; transactions.push(TransactionActiveModel { block_id: Set(database_block.id), - hash: Set(tx_hash.to_bytes().to_vec()), + hash: Set(tx_hash.to_raw_bytes().to_vec()), is_valid: Set(true), payload: Set(payload), tx_index: Set(tx_index), @@ -91,9 +92,9 @@ async fn handle_txs( ..Default::default() })); - outputs.push(cardano_multiplatform_lib::byron::ByronTxout::new( - &byron_addr, - amount, + outputs.push(cml_chain::byron::ByronTxOut::new( + byron_addr.clone(), + *amount, )); } @@ -128,8 +129,9 @@ async fn handle_txs( ..Default::default() })); - outputs.push(cardano_multiplatform_lib::byron::ByronTxout::new( - byron_addr, amount, + outputs.push(cml_chain::byron::ByronTxOut::new( + byron_addr.clone(), + *amount, )); } diff --git a/indexer/tasks/src/multiera/dex/common.rs b/indexer/tasks/src/multiera/dex/common.rs index 9e97985e..ef2d4ae6 100644 --- a/indexer/tasks/src/multiera/dex/common.rs +++ b/indexer/tasks/src/multiera/dex/common.rs @@ -5,24 +5,24 @@ use crate::{ asset_from_pair, get_plutus_datum_for_output, get_shelley_payment_hash, }, }; +use cml_chain::json::plutus_datums::{ + decode_plutus_datum_to_json_str, decode_plutus_datum_to_json_value, + CardanoNodePlutusDatumSchema, +}; use entity::dex_swap::Operation; use entity::sea_orm::{DatabaseTransaction, Set}; -use pallas::{ - codec::utils::KeepRaw, - ledger::{ - primitives::alonzo, - traverse::{MultiEraBlock, MultiEraOutput, MultiEraTx}, - }, -}; use std::collections::{BTreeMap, BTreeSet}; /// Returns an output and it's datum only if the output's payment hash is in `payment_hashes` /// and the plutus datum is known. -pub fn filter_outputs_and_datums_by_hash<'b>( - outputs: &[MultiEraOutput<'b>], +pub fn filter_outputs_and_datums_by_hash( + outputs: &[cml_multi_era::utils::MultiEraTransactionOutput], payment_hashes: &[&str], - plutus_data: &[&KeepRaw], -) -> Vec<(MultiEraOutput<'b>, alonzo::PlutusData)> { + plutus_data: &[cml_chain::plutus::PlutusData], +) -> Vec<( + cml_multi_era::utils::MultiEraTransactionOutput, + cml_chain::plutus::PlutusData, +)> { let payment_hashes = payment_hashes.iter().map(|&s| Some(s)).collect::>(); outputs .iter() @@ -38,16 +38,20 @@ pub fn filter_outputs_and_datums_by_hash<'b>( /// Returns an output and it's datum only if the output's address is in `addresses` /// and the plutus datum is known. -pub fn filter_outputs_and_datums_by_address<'b>( - outputs: &[MultiEraOutput<'b>], +pub fn filter_outputs_and_datums_by_address( + outputs: &[cml_multi_era::utils::MultiEraTransactionOutput], addresses: &[&str], - plutus_data: &[&KeepRaw], -) -> Vec<(MultiEraOutput<'b>, alonzo::PlutusData)> { - let addresses = addresses.iter().map(|&s| Some(s)).collect::>(); + plutus_data: &[cml_chain::plutus::PlutusData], +) -> Vec<( + cml_multi_era::utils::MultiEraTransactionOutput, + cml_chain::plutus::PlutusData, +)> { + let addresses = addresses.to_vec(); outputs .iter() .filter_map(|o| { - if addresses.contains(&o.address().ok().and_then(|a| a.to_bech32().ok()).as_deref()) { + let address_string = o.address().to_bech32(None).unwrap_or_default(); + if addresses.contains(&address_string.as_str()) { get_plutus_datum_for_output(o, plutus_data).map(|datum| (o.clone(), datum)) } else { None @@ -58,7 +62,7 @@ pub fn filter_outputs_and_datums_by_address<'b>( pub struct QueuedMeanPrice { pub tx_id: i64, - pub address: Vec, // pallas::crypto::hash::Hash<32> + pub address: Vec, pub dex_type: DexType, pub asset1: AssetPair, pub asset2: AssetPair, @@ -68,7 +72,7 @@ pub struct QueuedMeanPrice { pub struct QueuedSwap { pub tx_id: i64, - pub address: Vec, // pallas::crypto::hash::Hash<32> + pub address: Vec, pub dex_type: DexType, pub asset1: AssetPair, pub asset2: AssetPair, @@ -82,7 +86,8 @@ pub trait Dex { fn queue_mean_price( &self, queued_prices: &mut Vec, - tx: &MultiEraTx, + tx: &cml_multi_era::MultiEraTransactionBody, + tx_witness: &cml_chain::transaction::TransactionWitnessSet, tx_id: i64, ) -> Result<(), String>; @@ -90,7 +95,8 @@ pub trait Dex { fn queue_swap( &self, queued_swaps: &mut Vec, - tx: &MultiEraTx, + tx: &cml_multi_era::MultiEraTransactionBody, + tx_witness: &cml_chain::transaction::TransactionWitnessSet, tx_id: i64, multiera_used_inputs_to_outputs_map: &BTreeMap, BTreeMap>, ) -> Result<(), String>; @@ -109,7 +115,8 @@ impl Dex for Empty { fn queue_mean_price( &self, _queued_prices: &mut Vec, - _tx: &MultiEraTx, + _tx: &cml_multi_era::MultiEraTransactionBody, + _tx_witness: &cml_chain::transaction::TransactionWitnessSet, _tx_id: i64, ) -> Result<(), String> { unimplemented!(); @@ -118,7 +125,8 @@ impl Dex for Empty { fn queue_swap( &self, _queued_swaps: &mut Vec, - _tx: &MultiEraTx, + _tx: &cml_multi_era::MultiEraTransactionBody, + _tx_witness: &cml_chain::transaction::TransactionWitnessSet, _tx_id: i64, _multiera_used_inputs_to_outputs_map: &BTreeMap, BTreeMap>, ) -> Result<(), String> { @@ -158,7 +166,7 @@ impl DexType { pub async fn handle_mean_price( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], multiera_addresses: &BTreeMap, AddressInBlock>, pool_type: DexType, @@ -167,11 +175,18 @@ pub async fn handle_mean_price( let pool = pool_type; let mean_value_trait = pool.as_trait(); let mut queued_prices = Vec::::default(); - for (tx_body, cardano_transaction) in block.1.txs().iter().zip(multiera_txs) { + for ((tx_body, tx_witness_set), cardano_transaction) in block + .1 + .transaction_bodies() + .iter() + .zip(block.1.transaction_witness_sets()) + .zip(multiera_txs) + { if cardano_transaction.is_valid { let result = mean_value_trait.queue_mean_price( &mut queued_prices, tx_body, + &tx_witness_set, cardano_transaction.id, ); if result.is_err() { @@ -260,7 +275,7 @@ pub fn reduce_ada_amount(pair: &AssetPair, amount: u64) -> u64 { pub async fn handle_swap( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], multiera_addresses: &BTreeMap, AddressInBlock>, multiera_used_inputs_to_outputs_map: &BTreeMap, BTreeMap>, @@ -269,11 +284,18 @@ pub async fn handle_swap( // 1) Parse swaps let swap_trait = dex_type.as_trait(); let mut queued_swaps = Vec::::default(); - for (tx_body, cardano_transaction) in block.1.txs().iter().zip(multiera_txs) { + for ((tx_body, tx_witness_set), cardano_transaction) in block + .1 + .transaction_bodies() + .iter() + .zip(block.1.transaction_witness_sets()) + .zip(multiera_txs) + { if cardano_transaction.is_valid { let result = swap_trait.queue_swap( &mut queued_swaps, tx_body, + &tx_witness_set, cardano_transaction.id, multiera_used_inputs_to_outputs_map, ); @@ -344,3 +366,36 @@ pub async fn handle_swap( Ok(()) } + +pub fn datum_to_json(datum: &cml_chain::plutus::PlutusData) -> Result { + let value = + decode_plutus_datum_to_json_str(datum, CardanoNodePlutusDatumSchema::DetailedSchema) + .map_err(|err| format!("can't decode datum as json: {err}"))?; + serde_json::from_str(&value).map_err(|err| format!("can't decode json: {err}")) +} + +#[cfg(test)] +mod tests { + use crate::multiera::dex::common::datum_to_json; + use cml_chain::plutus::PlutusData; + use cml_core::serialization::FromBytes; + + #[test] + fn datum_json() { + let bytes = hex::decode("d8799fd8799f581cc72d0438330ed1346f4437fcc1c263ea38e933c1124c8d0f2abc6312484b574943343838331b0000018c5e40eb10ffff").unwrap(); + let data = PlutusData::from_bytes(bytes).unwrap(); + + let datum_json = datum_to_json(&data); + assert!(datum_json.is_ok(), "{:?}", datum_json.err()); + + let datum_json = datum_json.unwrap(); + println!("{:?}", datum_json); + let item = datum_json["fields"][0]["fields"][0]["bytes"] + .as_str() + .unwrap(); + assert_eq!( + item, + "c72d0438330ed1346f4437fcc1c263ea38e933c1124c8d0f2abc6312" + ); + } +} diff --git a/indexer/tasks/src/multiera/dex/minswap_v1.rs b/indexer/tasks/src/multiera/dex/minswap_v1.rs index 141bfc12..604d01f7 100644 --- a/indexer/tasks/src/multiera/dex/minswap_v1.rs +++ b/indexer/tasks/src/multiera/dex/minswap_v1.rs @@ -1,15 +1,16 @@ +use cml_chain::byron::ByronTxOut; +use cml_core::serialization::{FromBytes, Serialize}; +use cml_crypto::RawBytesEncoding; +use entity::block::EraValue; +use sea_orm::DbErr; use std::collections::BTreeMap; -use pallas::ledger::{ - addresses::Address, - primitives::ToCanonicalJson, - traverse::{MultiEraOutput, MultiEraTx}, -}; - use super::common::{ build_asset, filter_outputs_and_datums_by_address, filter_outputs_and_datums_by_hash, reduce_ada_amount, Dex, DexType, MinSwapV1, QueuedMeanPrice, QueuedSwap, }; +use crate::multiera::dex::common::datum_to_json; +use crate::multiera::utils::common::output_from_bytes; use crate::{era_common::OutputWithTxData, multiera::utils::common::get_asset_amount}; use entity::dex_swap::Operation; @@ -24,18 +25,19 @@ impl Dex for MinSwapV1 { fn queue_mean_price( &self, queued_prices: &mut Vec, - tx: &MultiEraTx, + tx: &cml_multi_era::MultiEraTransactionBody, + tx_witness: &cml_chain::transaction::TransactionWitnessSet, tx_id: i64, ) -> Result<(), String> { // Note: there should be at most one pool output if let Some((output, datum)) = filter_outputs_and_datums_by_hash( &tx.outputs(), &[POOL_SCRIPT_HASH1, POOL_SCRIPT_HASH2], - &tx.plutus_data(), + &tx_witness.plutus_datums.clone().unwrap_or_default(), ) .first() { - let datum = datum.to_json(); + let datum = datum_to_json(datum)?; let parse_asset_item = |i, j| -> Result, &str> { let item = datum["fields"][i]["fields"][j]["bytes"] @@ -52,7 +54,7 @@ impl Dex for MinSwapV1 { queued_prices.push(QueuedMeanPrice { tx_id, - address: output.address().unwrap().to_vec(), + address: output.address().to_raw_bytes().to_vec(), dex_type: DexType::MinSwapV1, asset1, asset2, @@ -66,7 +68,8 @@ impl Dex for MinSwapV1 { fn queue_swap( &self, queued_swaps: &mut Vec, - tx: &MultiEraTx, + tx: &cml_multi_era::MultiEraTransactionBody, + tx_witness: &cml_chain::transaction::TransactionWitnessSet, tx_id: i64, multiera_used_inputs_to_outputs_map: &BTreeMap, BTreeMap>, ) -> Result<(), String> { @@ -74,12 +77,13 @@ impl Dex for MinSwapV1 { if let Some((main_output, main_datum)) = filter_outputs_and_datums_by_hash( &tx.outputs(), &[POOL_SCRIPT_HASH1, POOL_SCRIPT_HASH2], - &tx.plutus_data(), + &tx_witness.plutus_datums.clone().unwrap_or_default(), ) .first() { - let main_datum = main_datum.to_json(); - let mut free_utxos: Vec = tx.outputs(); + let main_datum = datum_to_json(main_datum)?; + + let mut free_utxos: Vec = tx.outputs(); // Extract asset information from plutus data of pool input let parse_asset_item = |i, j| -> Result, &str> { @@ -92,21 +96,22 @@ impl Dex for MinSwapV1 { let asset1 = build_asset(parse_asset_item(0, 0)?, parse_asset_item(0, 1)?); let asset2 = build_asset(parse_asset_item(1, 0)?, parse_asset_item(1, 1)?); - let inputs: Vec = tx + let inputs: Vec = tx .inputs() .iter() .map(|i| { - let output = &multiera_used_inputs_to_outputs_map[&i.hash().to_vec()] - [&(i.index() as i64)]; - MultiEraOutput::decode(output.era, &output.model.payload).unwrap() + let output = &multiera_used_inputs_to_outputs_map + [&i.hash().unwrap().to_raw_bytes().to_vec()] + [&(i.index().unwrap() as i64)]; + output_from_bytes(output).unwrap() }) .collect::>(); for (input, input_datum) in filter_outputs_and_datums_by_address( &inputs, &[BATCH_ORDER_ADDRESS1, BATCH_ORDER_ADDRESS2], - &tx.plutus_data(), + &tx_witness.plutus_datums.clone().unwrap_or_default(), ) { - let input_datum = input_datum.to_json(); + let input_datum = datum_to_json(&input_datum)?; // identify operation: 0 = swap let operation = input_datum["fields"][3]["constructor"] @@ -127,7 +132,7 @@ impl Dex for MinSwapV1 { let target_asset = build_asset(parse_asset_item(0, 0)?, parse_asset_item(0, 1)?); // Get transaction output - let output_address_items = vec![ + let output_address_items = [ String::from("01"), // mainnet input_datum["fields"][1]["fields"][0]["fields"][0]["bytes"] .as_str() @@ -139,13 +144,14 @@ impl Dex for MinSwapV1 { .ok_or("Failed to parse output address item")? .to_string(), ]; - let output_address = Address::from_hex(&output_address_items.join("")) - .map_err(|_e| "Failed to parse output address")?; + let output_address = + cml_chain::address::Address::from_hex(&output_address_items.join("")) + .map_err(|_e| "Failed to parse output address")?; // Get coresponding UTxO with result let utxo_pos = free_utxos .iter() - .position(|o| o.address().ok() == Some(output_address.clone())) + .position(|o| o.address() == output_address.clone()) .ok_or("Failed to find utxo")?; let utxo = free_utxos[utxo_pos].clone(); free_utxos.remove(utxo_pos); @@ -169,7 +175,7 @@ impl Dex for MinSwapV1 { } queued_swaps.push(QueuedSwap { tx_id, - address: main_output.address().unwrap().to_vec(), + address: main_output.address().to_raw_bytes().to_vec(), dex_type: DexType::MinSwapV1, asset1: asset1.clone(), asset2: asset2.clone(), diff --git a/indexer/tasks/src/multiera/dex/sundaeswap_v1.rs b/indexer/tasks/src/multiera/dex/sundaeswap_v1.rs index 76ef1eaa..ec6b4a87 100644 --- a/indexer/tasks/src/multiera/dex/sundaeswap_v1.rs +++ b/indexer/tasks/src/multiera/dex/sundaeswap_v1.rs @@ -1,15 +1,18 @@ +use cml_chain::byron::ByronTxOut; +use cml_core::serialization::{FromBytes, Serialize}; +use cml_crypto::RawBytesEncoding; +use cml_multi_era::utils::MultiEraTransactionOutput; use std::collections::BTreeMap; -use pallas::ledger::{ - addresses::Address, - primitives::ToCanonicalJson, - traverse::{MultiEraOutput, MultiEraTx}, -}; +use entity::block::EraValue; +use sea_orm::DbErr; use super::common::{ build_asset, filter_outputs_and_datums_by_address, filter_outputs_and_datums_by_hash, reduce_ada_amount, Dex, DexType, QueuedMeanPrice, QueuedSwap, SundaeSwapV1, }; +use crate::multiera::dex::common::datum_to_json; +use crate::multiera::utils::common::output_from_bytes; use crate::{era_common::OutputWithTxData, multiera::utils::common::get_asset_amount}; use entity::dex_swap::Operation; @@ -22,15 +25,19 @@ impl Dex for SundaeSwapV1 { fn queue_mean_price( &self, queued_prices: &mut Vec, - tx: &MultiEraTx, + tx: &cml_multi_era::MultiEraTransactionBody, + tx_witness: &cml_chain::transaction::TransactionWitnessSet, tx_id: i64, ) -> Result<(), String> { // Note: there should be at most one pool output - if let Some((output, datum)) = - filter_outputs_and_datums_by_hash(&tx.outputs(), &[POOL_SCRIPT_HASH], &tx.plutus_data()) - .first() + if let Some((output, datum)) = filter_outputs_and_datums_by_hash( + &tx.outputs(), + &[POOL_SCRIPT_HASH], + &tx_witness.plutus_datums.clone().unwrap_or_default(), + ) + .first() { - let datum = datum.to_json(); + let datum = datum_to_json(datum)?; let parse_asset_item = |i, j| -> Result, &str> { let item = datum["fields"][0]["fields"][i]["fields"][j]["bytes"] @@ -47,7 +54,7 @@ impl Dex for SundaeSwapV1 { queued_prices.push(QueuedMeanPrice { tx_id, - address: output.address().unwrap().to_vec(), + address: output.address().to_raw_bytes().to_vec(), dex_type: DexType::SundaeSwapV1, asset1, asset2, @@ -61,17 +68,22 @@ impl Dex for SundaeSwapV1 { fn queue_swap( &self, queued_swaps: &mut Vec, - tx: &MultiEraTx, + tx: &cml_multi_era::MultiEraTransactionBody, + tx_witness: &cml_chain::transaction::TransactionWitnessSet, tx_id: i64, multiera_used_inputs_to_outputs_map: &BTreeMap, BTreeMap>, ) -> Result<(), String> { // Note: there should be at most one pool output - if let Some((main_output, main_datum)) = - filter_outputs_and_datums_by_hash(&tx.outputs(), &[POOL_SCRIPT_HASH], &tx.plutus_data()) - .first() + if let Some((main_output, main_datum)) = filter_outputs_and_datums_by_hash( + &tx.outputs(), + &[POOL_SCRIPT_HASH], + &tx_witness.plutus_datums.clone().unwrap_or_default(), + ) + .first() { - let main_datum = main_datum.to_json(); - let mut free_utxos: Vec = tx.outputs(); + let main_datum = datum_to_json(main_datum)?; + + let mut free_utxos: Vec = tx.outputs(); // Extract asset information from plutus data of pool input let parse_asset_item = |i, j| -> Result, &str> { @@ -84,21 +96,22 @@ impl Dex for SundaeSwapV1 { let asset1 = build_asset(parse_asset_item(0, 0)?, parse_asset_item(0, 1)?); let asset2 = build_asset(parse_asset_item(1, 0)?, parse_asset_item(1, 1)?); - let inputs: Vec = tx + let inputs: Vec = tx .inputs() .iter() .map(|i| { - let output = &multiera_used_inputs_to_outputs_map[&i.hash().to_vec()] - [&(i.index() as i64)]; - MultiEraOutput::decode(output.era, &output.model.payload).unwrap() + let output = &multiera_used_inputs_to_outputs_map + [&i.hash().unwrap().to_raw_bytes().to_vec()] + [&(i.index().unwrap() as i64)]; + output_from_bytes(output).unwrap() }) .collect::>(); for (input, input_datum) in filter_outputs_and_datums_by_hash( &inputs, &[REQUEST_SCRIPT_HASH], - &tx.plutus_data(), + &tx_witness.plutus_datums.clone().unwrap_or_default(), ) { - let input_datum = input_datum.to_json(); + let input_datum = datum_to_json(&input_datum)?; // identify operation: 0 = swap let operation = input_datum["fields"][3]["constructor"] @@ -110,7 +123,7 @@ impl Dex for SundaeSwapV1 { } // Get transaction output - let output_address_items = vec![ + let output_address_items = [ String::from("01"), // mainnet input_datum["fields"][1]["fields"][0]["fields"][0]["fields"][0]["fields"][0] ["bytes"] @@ -123,13 +136,14 @@ impl Dex for SundaeSwapV1 { .ok_or("Failed to parse output address item")? .to_string(), ]; - let output_address = Address::from_hex(&output_address_items.join("")) - .map_err(|_e| "Failed to parse output address")?; + let output_address = + cml_chain::address::Address::from_hex(&output_address_items.join("")) + .map_err(|_e| "Failed to parse output address")?; // Get coresponding UTxO with result let utxo_pos = free_utxos .iter() - .position(|o| o.address().ok() == Some(output_address.clone())) + .position(|o| o.address() == output_address.clone()) .ok_or("Failed to find utxo")?; let utxo = free_utxos[utxo_pos].clone(); free_utxos.remove(utxo_pos); @@ -154,7 +168,7 @@ impl Dex for SundaeSwapV1 { } queued_swaps.push(QueuedSwap { tx_id, - address: main_output.address().unwrap().to_vec(), + address: main_output.address().to_raw_bytes().to_vec(), dex_type: DexType::SundaeSwapV1, asset1: asset1.clone(), asset2: asset2.clone(), diff --git a/indexer/tasks/src/multiera/dex/wingriders_v1.rs b/indexer/tasks/src/multiera/dex/wingriders_v1.rs index 3f24ac8e..28563ee4 100644 --- a/indexer/tasks/src/multiera/dex/wingriders_v1.rs +++ b/indexer/tasks/src/multiera/dex/wingriders_v1.rs @@ -1,14 +1,18 @@ +use cml_chain::byron::ByronTxOut; +use cml_core::serialization::{FromBytes, Serialize}; +use cml_crypto::RawBytesEncoding; +use cml_multi_era::utils::MultiEraTransactionOutput; use std::collections::BTreeMap; -use pallas::ledger::{ - primitives::ToCanonicalJson, - traverse::{MultiEraOutput, MultiEraTx}, -}; +use entity::block::EraValue; +use sea_orm::DbErr; use super::common::{ build_asset, filter_outputs_and_datums_by_hash, reduce_ada_amount, Dex, DexType, QueuedMeanPrice, QueuedSwap, WingRidersV1, }; +use crate::multiera::dex::common::datum_to_json; +use crate::multiera::utils::common::output_from_bytes; use crate::{ era_common::OutputWithTxData, multiera::utils::common::{get_asset_amount, get_plutus_datum_for_output}, @@ -24,15 +28,19 @@ impl Dex for WingRidersV1 { fn queue_mean_price( &self, queued_prices: &mut Vec, - tx: &MultiEraTx, + tx: &cml_multi_era::MultiEraTransactionBody, + tx_witness: &cml_chain::transaction::TransactionWitnessSet, tx_id: i64, ) -> Result<(), String> { // Note: there should be at most one pool output - if let Some((output, datum)) = - filter_outputs_and_datums_by_hash(&tx.outputs(), &[POOL_SCRIPT_HASH], &tx.plutus_data()) - .first() + if let Some((output, datum)) = filter_outputs_and_datums_by_hash( + &tx.outputs(), + &[POOL_SCRIPT_HASH], + &tx_witness.plutus_datums.clone().unwrap_or_default(), + ) + .first() { - let datum = datum.to_json(); + let datum = datum_to_json(datum)?; let treasury1 = datum["fields"][1]["fields"][2]["int"] .as_u64() @@ -60,7 +68,7 @@ impl Dex for WingRidersV1 { queued_prices.push(QueuedMeanPrice { tx_id, - address: output.address().unwrap().to_vec(), + address: output.address().to_raw_bytes().to_vec(), dex_type: DexType::WingRidersV1, asset1, asset2, @@ -74,20 +82,24 @@ impl Dex for WingRidersV1 { fn queue_swap( &self, queued_swaps: &mut Vec, - tx: &MultiEraTx, + tx: &cml_multi_era::MultiEraTransactionBody, + tx_witness: &cml_chain::transaction::TransactionWitnessSet, tx_id: i64, multiera_used_inputs_to_outputs_map: &BTreeMap, BTreeMap>, ) -> Result<(), String> { // Note: there should be at most one pool output - if let Some((pool_output, _)) = - filter_outputs_and_datums_by_hash(&tx.outputs(), &[POOL_SCRIPT_HASH], &tx.plutus_data()) - .first() + if let Some((pool_output, _)) = filter_outputs_and_datums_by_hash( + &tx.outputs(), + &[POOL_SCRIPT_HASH], + &tx_witness.plutus_datums.clone().unwrap_or_default(), + ) + .first() { - let redeemers = tx.redeemers().ok_or("No redeemers")?; + let redeemers = tx_witness.redeemers.clone().ok_or("No redeemers")?; // Get pool input from redemeers let pool_input_redeemer = redeemers.first().ok_or("No redeemers")?; - let pool_input = pool_input_redeemer.data.to_json()["fields"][0]["int"] + let pool_input = datum_to_json(&pool_input_redeemer.data)?["fields"][0]["int"] .as_i64() .ok_or("Failed to parse pool input index")?; @@ -96,7 +108,7 @@ impl Dex for WingRidersV1 { .iter() .find(|&r| r.index as i64 == pool_input) .ok_or("Failed to find main redeemer")?; - let redeemer = redeemer.data.to_json(); + let redeemer = datum_to_json(&redeemer.data)?; // Extract input list from redemeer let redeemer_map: Vec = redeemer["fields"][2]["list"] @@ -110,13 +122,14 @@ impl Dex for WingRidersV1 { .as_i64() .ok_or("Failed to parse main transaction")? as usize; // Restore inputs - let inputs: Vec = tx + let inputs: Vec = tx .inputs() .iter() .map(|i| { - let output = &multiera_used_inputs_to_outputs_map[&i.hash().to_vec()] - [&(i.index() as i64)]; - MultiEraOutput::decode(output.era, &output.model.payload).unwrap() + let output = &multiera_used_inputs_to_outputs_map + [&i.hash().unwrap().to_raw_bytes().to_vec()] + [&(i.index().unwrap() as i64)]; + output_from_bytes(output).unwrap() }) .collect::>(); // Zip outputs with redemeer index @@ -125,9 +138,14 @@ impl Dex for WingRidersV1 { let input = inputs.get(redeemer).ok_or("Failed to pair output")?.clone(); // get information about swap from pool plutus data - let parent_datum = get_plutus_datum_for_output(&inputs[parent], &tx.plutus_data()) - .unwrap() - .to_json(); + let parent_datum = get_plutus_datum_for_output( + &inputs[parent], + &tx_witness.plutus_datums.clone().unwrap_or_default(), + ) + .unwrap(); + + let parent_datum = datum_to_json(&parent_datum)?; + let parse_asset_item = |i, j| -> Result, &str> { let item = parent_datum["fields"][1]["fields"][0]["fields"][i]["fields"][j] ["bytes"] @@ -140,9 +158,12 @@ impl Dex for WingRidersV1 { let asset2 = build_asset(parse_asset_item(1, 0)?, parse_asset_item(1, 1)?); // get actual plutus datum - let input_datum = get_plutus_datum_for_output(&input, &tx.plutus_data()) - .unwrap() - .to_json(); + let input_datum = get_plutus_datum_for_output( + &input, + &tx_witness.plutus_datums.clone().unwrap_or_default(), + ) + .unwrap(); + let input_datum = datum_to_json(&input_datum)?; // identify operation: 0 = swap let operation = input_datum["fields"][1]["constructor"] .as_i64() @@ -170,7 +191,7 @@ impl Dex for WingRidersV1 { } queued_swaps.push(QueuedSwap { tx_id, - address: pool_output.address().unwrap().to_vec(), + address: pool_output.address().to_raw_bytes().to_vec(), dex_type: DexType::WingRidersV1, asset1, asset2, diff --git a/indexer/tasks/src/multiera/multiera_address.rs b/indexer/tasks/src/multiera/multiera_address.rs index 4043c2ac..9699e304 100644 --- a/indexer/tasks/src/multiera/multiera_address.rs +++ b/indexer/tasks/src/multiera/multiera_address.rs @@ -1,17 +1,20 @@ use std::collections::{BTreeMap, BTreeSet}; -use cardano_multiplatform_lib::{ +use cml_chain::certs::Credential; +use cml_chain::{ address::{BaseAddress, EnterpriseAddress, PointerAddress, RewardAddress}, byron::ByronAddress, }; +use cml_core::serialization::{FromBytes, Serialize, ToBytes}; +use cml_crypto::RawBytesEncoding; +use cml_multi_era::allegra::MIRAction; +use cml_multi_era::byron::block::ByronBlock; +use cml_multi_era::utils::MultiEraCertificate; +use cml_multi_era::MultiEraBlock; use entity::{ prelude::*, sea_orm::{prelude::*, DatabaseTransaction}, }; -use pallas::ledger::{ - primitives::{alonzo::Certificate, Fragment}, - traverse::{MultiEraBlock, MultiEraCert, MultiEraOutput, MultiEraTx}, -}; use std::ops::Deref; use crate::types::{AddressCredentialRelationValue, TxCredentialRelationValue}; @@ -24,6 +27,7 @@ use crate::config::EmptyConfig::EmptyConfig; use crate::dsl::database_task::BlockGlobalInfo; use crate::dsl::task_macro::*; +use crate::utils::blake2b256; carp_task! { name MultieraAddressTask; @@ -52,7 +56,7 @@ carp_task! { async fn handle_addresses( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], vkey_relation_map: &mut RelationMap, ) -> Result< @@ -65,15 +69,17 @@ async fn handle_addresses( let mut queued_address_credential = BTreeSet::::default(); let mut queued_address = BTreeMap::, i64>::default(); - for (tx_body, cardano_transaction) in block.1.txs().iter().zip(multiera_txs) { - for cert in tx_body.certs() { - queue_certificate( - vkey_relation_map, - &mut queued_address_credential, - &mut queued_address, - cardano_transaction.id, - &cert, - ); + for (tx_body, cardano_transaction) in block.1.transaction_bodies().iter().zip(multiera_txs) { + if let Some(certs) = tx_body.certs() { + for cert in certs { + queue_certificate( + vkey_relation_map, + &mut queued_address_credential, + &mut queued_address, + cardano_transaction.id, + &cert, + ); + } } for output in tx_body.outputs() { @@ -102,19 +108,14 @@ async fn handle_addresses( ); } - for withdrawal in tx_body.withdrawals().collect::>() { - let reward_addr = RewardAddress::from_address( - &cardano_multiplatform_lib::address::Address::from_bytes(withdrawal.0.into()) - .unwrap(), - ) - .unwrap(); + for (reward_addr, _) in tx_body.withdrawals().cloned().unwrap_or_default().iter() { queue_address_credential( vkey_relation_map, &mut queued_address_credential, &mut queued_address, cardano_transaction.id, - &reward_addr.to_address().to_bytes(), - &reward_addr.payment_cred(), + &reward_addr.clone().to_address().to_raw_bytes(), + reward_addr.payment.clone(), TxCredentialRelationValue::Withdrawal, AddressCredentialRelationValue::PaymentKey, ); @@ -131,15 +132,15 @@ fn queue_certificate( queued_address_credential: &mut BTreeSet, queued_address: &mut BTreeMap, i64>, tx_id: i64, - cert: &MultiEraCert, + cert: &MultiEraCertificate, ) { // TODO: what's the policy for handling options? At the moment of writing, all certificates // are "alonzo-compatible", but that might change in a future HF. Should Carp skip data that // it doesn't understand or instead panic? For now, opting to panic as it seems to be what's // used for other options. - match cert.as_alonzo().unwrap() { - Certificate::StakeDelegation(credential, pool) => { - let credential = credential.encode_fragment().unwrap(); + match cert { + MultiEraCertificate::StakeDelegation(delegation) => { + let credential = delegation.stake_credential.to_cbor_bytes(); vkey_relation_map.add_relation( tx_id, @@ -149,16 +150,12 @@ fn queue_certificate( vkey_relation_map.add_relation( tx_id, - RelationMap::keyhash_to_pallas( - &cardano_multiplatform_lib::crypto::Ed25519KeyHash::from_bytes(pool.to_vec()) - .unwrap(), - ) - .as_slice(), + delegation.pool.to_raw_bytes(), TxCredentialRelationValue::DelegationTarget, ); } - Certificate::StakeRegistration(credential) => { - let credential = credential.encode_fragment().unwrap(); + MultiEraCertificate::StakeRegistration(registration) => { + let credential = registration.stake_credential.to_cbor_bytes(); vkey_relation_map.add_relation( tx_id, @@ -166,8 +163,8 @@ fn queue_certificate( TxCredentialRelationValue::StakeRegistration, ); } - Certificate::StakeDeregistration(credential) => { - let credential = credential.encode_fragment().unwrap(); + MultiEraCertificate::StakeDeregistration(deregistration) => { + let credential = deregistration.stake_credential.to_cbor_bytes(); vkey_relation_map.add_relation( tx_id, @@ -175,16 +172,8 @@ fn queue_certificate( TxCredentialRelationValue::StakeDeregistration, ); } - Certificate::PoolRegistration { - operator, - pool_owners, - reward_account, - .. - } => { - let operator_credential = - pallas::ledger::primitives::alonzo::StakeCredential::AddrKeyhash(*operator) - .encode_fragment() - .unwrap(); + MultiEraCertificate::PoolRegistration(registration) => { + let operator_credential = registration.pool_params.operator.to_raw_bytes().to_vec(); vkey_relation_map.add_relation( tx_id, @@ -192,28 +181,21 @@ fn queue_certificate( TxCredentialRelationValue::PoolOperator, ); - let reward_addr = RewardAddress::from_address( - &cardano_multiplatform_lib::address::Address::from_bytes(reward_account.to_vec()) - .unwrap(), - ) - .unwrap(); + let reward_addr = registration.pool_params.reward_account.clone(); queue_address_credential( vkey_relation_map, queued_address_credential, queued_address, tx_id, - &reward_addr.to_address().to_bytes(), - &reward_addr.payment_cred(), + &reward_addr.clone().to_address().to_raw_bytes(), + reward_addr.payment, TxCredentialRelationValue::PoolReward, AddressCredentialRelationValue::PaymentKey, ); - for &owner in pool_owners.iter() { - let owner_credential = - pallas::ledger::primitives::alonzo::StakeCredential::AddrKeyhash(owner) - .encode_fragment() - .unwrap(); + for &owner in registration.pool_params.pool_owners.iter() { + let owner_credential = owner.to_raw_bytes().to_vec(); vkey_relation_map.add_relation( tx_id, @@ -222,27 +204,25 @@ fn queue_certificate( ); } } - Certificate::PoolRetirement(key_hash, _) => { - let operator_credential = - pallas::ledger::primitives::alonzo::StakeCredential::AddrKeyhash(*key_hash) - .encode_fragment() - .unwrap(); + MultiEraCertificate::PoolRetirement(retirement) => { + let operator_credential = retirement.pool.to_raw_bytes().to_vec(); vkey_relation_map.add_relation( tx_id, &operator_credential, TxCredentialRelationValue::PoolOperator, ); } - Certificate::GenesisKeyDelegation(_, _, _) => { + MultiEraCertificate::GenesisKeyDelegation(_) => { // genesis keys aren't stake credentials } - Certificate::MoveInstantaneousRewardsCert(mir) => { - if let pallas::ledger::primitives::alonzo::InstantaneousRewardTarget::StakeCredentials( - credential_pairs, - ) = &mir.target + MultiEraCertificate::MoveInstantaneousRewardsCert(mir) => { + if let MIRAction::ToStakeCredentials { + to_stake_credentials, + .. + } = &mir.move_instantaneous_reward.action { - for pair in credential_pairs.deref() { - let credential = pair.0.encode_fragment().unwrap(); + for pair in to_stake_credentials.deref() { + let credential = pair.0.to_cbor_bytes(); vkey_relation_map.add_relation( tx_id, @@ -252,6 +232,18 @@ fn queue_certificate( } } } + MultiEraCertificate::RegCert(_) => {} + MultiEraCertificate::UnregCert(_) => {} + MultiEraCertificate::VoteDelegCert(_) => {} + MultiEraCertificate::StakeVoteDelegCert(_) => {} + MultiEraCertificate::StakeRegDelegCert(_) => {} + MultiEraCertificate::VoteRegDelegCert(_) => {} + MultiEraCertificate::StakeVoteRegDelegCert(_) => {} + MultiEraCertificate::AuthCommitteeHotCert(_) => {} + MultiEraCertificate::ResignCommitteeColdCert(_) => {} + MultiEraCertificate::RegDrepCert(_) => {} + MultiEraCertificate::UnregDrepCert(_) => {} + MultiEraCertificate::UpdateDrepCert(_) => {} }; } @@ -260,21 +252,15 @@ fn queue_output( queued_credentials: &mut RelationMap, queued_address_credential: &mut BTreeSet, queued_address: &mut BTreeMap, i64>, - tx_body: &MultiEraTx, + _tx_body: &cml_multi_era::MultiEraTransactionBody, tx_id: i64, - output: &MultiEraOutput, + output: &cml_multi_era::utils::MultiEraTransactionOutput, output_relation: TxCredentialRelationValue, output_stake_relation: TxCredentialRelationValue, ) { - use cardano_multiplatform_lib::address::Address; + use cml_chain::address::Address; - let pallas_address = output - .address() - .map_err(|e| panic!("{:?} {:?}", e, hex::encode(tx_body.hash()))) - .unwrap(); - let addr = Address::from_bytes(pallas_address.to_vec()) - .map_err(|e| panic!("{:?} {:?}", e, hex::encode(tx_body.hash()))) - .unwrap(); + let addr = output.address(); let address_relation = AddressCredentialRelationValue::PaymentKey; @@ -286,8 +272,8 @@ fn queue_output( queued_address_credential, queued_address, tx_id, - &addr.to_bytes(), - &base_addr.payment_cred(), + &addr.to_raw_bytes(), + base_addr.payment, output_relation, address_relation, ); @@ -300,8 +286,8 @@ fn queue_output( queued_address_credential, queued_address, tx_id, - &addr.to_bytes(), - &base_addr.stake_cred(), + &addr.to_raw_bytes(), + base_addr.stake, output_stake_relation, AddressCredentialRelationValue::StakeKey, ); @@ -312,14 +298,14 @@ fn queue_output( queued_address_credential, queued_address, tx_id, - &addr.to_bytes(), - &reward_addr.payment_cred(), + &addr.to_raw_bytes(), + reward_addr.payment, output_relation, address_relation, ); } else if ByronAddress::from_address(&addr).is_some() { queued_address - .entry(addr.to_bytes()) + .entry(addr.to_raw_bytes()) .and_modify(|old_id| { if tx_id < *old_id { *old_id = tx_id @@ -332,8 +318,8 @@ fn queue_output( queued_address_credential, queued_address, tx_id, - &addr.to_bytes(), - &enterprise_addr.payment_cred(), + &addr.to_raw_bytes(), + enterprise_addr.payment, output_relation, address_relation, ); @@ -343,13 +329,16 @@ fn queue_output( queued_address_credential, queued_address, tx_id, - &addr.to_bytes(), - &ptr_addr.payment_cred(), + &addr.to_raw_bytes(), + ptr_addr.payment, output_relation, address_relation, ); } else { - panic!("Unexpected address type {}", hex::encode(addr.to_bytes())); + panic!( + "Unexpected address type {}", + hex::encode(addr.to_raw_bytes()) + ); } } @@ -360,7 +349,7 @@ fn queue_address_credential( queued_address: &mut BTreeMap, i64>, tx_id: i64, address: &[u8], - credential: &cardano_multiplatform_lib::address::StakeCredential, + credential: Credential, tx_relation: TxCredentialRelationValue, address_relation: AddressCredentialRelationValue, ) { @@ -372,10 +361,10 @@ fn queue_address_credential( } }) .or_insert(tx_id); - vkey_relation_map.add_relation(tx_id, &credential.to_bytes(), tx_relation); + vkey_relation_map.add_relation(tx_id, credential.to_raw_bytes(), tx_relation); queued_address_credential.insert(QueuedAddressCredentialRelation { address: address.to_vec(), - stake_credential: credential.to_bytes(), + stake_credential: credential.to_raw_bytes().to_vec(), address_relation, }); } diff --git a/indexer/tasks/src/multiera/multiera_address_credential_relations.rs b/indexer/tasks/src/multiera/multiera_address_credential_relations.rs index ac1cd16a..abba6ac1 100644 --- a/indexer/tasks/src/multiera/multiera_address_credential_relations.rs +++ b/indexer/tasks/src/multiera/multiera_address_credential_relations.rs @@ -39,7 +39,7 @@ carp_task! { #[derive(PartialEq, Eq, PartialOrd, Ord)] pub struct QueuedAddressCredentialRelation { pub address: Vec, - pub stake_credential: Vec, // pallas::crypto::hash::Hash<32> + pub stake_credential: Vec, pub address_relation: AddressCredentialRelationValue, } diff --git a/indexer/tasks/src/multiera/multiera_address_delegation.rs b/indexer/tasks/src/multiera/multiera_address_delegation.rs index a74faaae..6586c426 100644 --- a/indexer/tasks/src/multiera/multiera_address_delegation.rs +++ b/indexer/tasks/src/multiera/multiera_address_delegation.rs @@ -2,18 +2,13 @@ use crate::{ multiera::multiera_stake_credentials::MultieraStakeCredentialTask, types::{AddressCredentialRelationValue, TxCredentialRelationValue}, }; -use cardano_multiplatform_lib::{ - address::{BaseAddress, EnterpriseAddress, PointerAddress, RewardAddress}, - byron::ByronAddress, -}; +use cml_core::serialization::Serialize; +use cml_crypto::RawBytesEncoding; +use cml_multi_era::utils::MultiEraCertificate; use entity::{ prelude::*, sea_orm::{prelude::*, DatabaseTransaction}, }; -use pallas::ledger::{ - primitives::{alonzo::Certificate, Fragment}, - traverse::{MultiEraBlock, MultiEraCert, MultiEraOutput, MultiEraTx}, -}; use sea_orm::{Order, QueryOrder, Set}; use std::collections::{BTreeMap, BTreeSet}; use std::ops::Deref; @@ -50,22 +45,30 @@ carp_task! { async fn handle( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], multiera_stake_credential: &BTreeMap, StakeCredentialModel>, ) -> Result<(), DbErr> { - for (tx_body, cardano_transaction) in block.1.txs().iter().zip(multiera_txs) { - for cert in tx_body.certs() { + for (tx_body, cardano_transaction) in block.1.transaction_bodies().iter().zip(multiera_txs) { + let certs = match tx_body.certs() { + None => continue, + Some(certs) => certs, + }; + for cert in certs { { let tx_id = cardano_transaction.id; let cert = &cert; - let (credential, pool) = match cert.as_alonzo().unwrap() { - Certificate::StakeDelegation(credential, pool) => (credential, Some(pool)), - Certificate::StakeDeregistration(credential) => (credential, None), + let (credential, pool) = match cert { + MultiEraCertificate::StakeDelegation(delegation) => { + (delegation.stake_credential.clone(), Some(delegation.pool)) + } + MultiEraCertificate::StakeDeregistration(deregistration) => { + (deregistration.stake_credential.clone(), None) + } _ => continue, }; - let credential = credential.encode_fragment().unwrap(); + let credential = credential.to_cbor_bytes(); let stake_credential_id = multiera_stake_credential .get(&credential.to_vec()) @@ -80,7 +83,7 @@ async fn handle( .one(db_tx) .await?; - let pool = pool.map(|pool| pool.to_vec()); + let pool = pool.map(|pool| pool.to_raw_bytes().to_vec()); if let Some((previous, pool)) = previous_entry .as_ref() diff --git a/indexer/tasks/src/multiera/multiera_asset_mint.rs b/indexer/tasks/src/multiera/multiera_asset_mint.rs index 580477b8..b55f3fac 100644 --- a/indexer/tasks/src/multiera/multiera_asset_mint.rs +++ b/indexer/tasks/src/multiera/multiera_asset_mint.rs @@ -1,3 +1,4 @@ +use cml_chain::assets::Mint; use std::collections::{BTreeMap, BTreeSet}; use super::utils::common::asset_from_pair; @@ -5,18 +6,14 @@ use super::{multiera_txs::MultieraTransactionTask, utils::user_asset::AssetName} use crate::config::ReadonlyConfig::ReadonlyConfig; use crate::dsl::database_task::BlockGlobalInfo; use crate::utils::blake2b160; -use cardano_multiplatform_lib::crypto::ScriptHash; +use cml_chain::crypto::ScriptHash; +use cml_core::serialization::Serialize; +use cml_crypto::RawBytesEncoding; use entity::sea_orm::QueryOrder; use entity::{ prelude::*, sea_orm::{prelude::*, Condition, DatabaseTransaction, Set}, }; -use pallas::ledger::primitives::Fragment; -use pallas::ledger::traverse::MultiEraBlock; -use pallas::{ - codec::utils::KeyValuePairs, - ledger::primitives::alonzo::{self, AuxiliaryData, Metadatum, MetadatumLabel}, -}; use crate::dsl::task_macro::*; @@ -29,7 +26,7 @@ carp_task! { read [multiera_block, multiera_txs]; write [multiera_assets]; should_add_task |block, _properties| { - block.1.txs().iter().any(|tx| tx.mint().len() > 0) + block.1.transaction_bodies().iter().any(|tx| tx.mint().map(|mint| mint.len() > 0).unwrap_or(false)) }; execute |previous_data, task| handle_mints( task.db_tx, @@ -44,17 +41,21 @@ carp_task! { async fn handle_mints( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], readonly: bool, ) -> Result, DbErr> { let mut queued_mints = Vec::<(i64, (Vec, Vec), i64)>::default(); - for (tx_body, cardano_transaction) in block.1.txs().iter().zip(multiera_txs) { - for (policy_id, assets) in tx_body.mint().as_alonzo().iter().flat_map(|x| x.iter()) { + for (tx_body, cardano_transaction) in block.1.transaction_bodies().iter().zip(multiera_txs) { + let mint = match tx_body.mint() { + None => continue, + Some(mint) => mint, + }; + for (policy_id, assets) in mint.iter() { for (asset_name, amount) in assets.iter() { queued_mints.push(( cardano_transaction.id, - (policy_id.to_vec(), asset_name.to_vec()), + (policy_id.to_raw_bytes().to_vec(), asset_name.get().clone()), *amount, )); } diff --git a/indexer/tasks/src/multiera/multiera_asset_utxo.rs b/indexer/tasks/src/multiera/multiera_asset_utxo.rs index 3d12be5d..36e5eaec 100644 --- a/indexer/tasks/src/multiera/multiera_asset_utxo.rs +++ b/indexer/tasks/src/multiera/multiera_asset_utxo.rs @@ -7,20 +7,18 @@ use crate::multiera::dex::common::filter_outputs_and_datums_by_address; use crate::multiera::multiera_txs::MultieraTransactionTask; use crate::multiera::multiera_used_inputs::MultieraUsedInputTask; use crate::multiera::multiera_used_outputs::MultieraOutputTask; +use crate::multiera::utils::common::output_from_bytes; use crate::types::AddressCredentialRelationValue; -use cardano_multiplatform_lib::error::DeserializeError; -use cml_core::serialization::{FromBytes, ToBytes}; +use cml_core::serialization::{Deserialize, FromBytes, Serialize, ToBytes}; use cml_crypto::RawBytesEncoding; +use cml_multi_era::utils::{MultiEraTransactionInput, MultiEraTransactionOutput}; +use entity::block::EraValue; use entity::sea_orm::Condition; use entity::transaction_output::Model; use entity::{ prelude::*, sea_orm::{prelude::*, DatabaseTransaction, Set}, }; -use pallas::ledger::primitives::babbage::DatumOption; -use pallas::ledger::primitives::Fragment; -use pallas::ledger::traverse::{Asset, MultiEraInput, MultiEraOutput}; -use projected_nft_sdk::{Owner, State, Status}; use sea_orm::{FromQueryResult, JoinType, QuerySelect, QueryTrait}; use std::collections::{BTreeSet, HashMap}; @@ -48,7 +46,7 @@ carp_task! { async fn handle( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], multiera_outputs: &[TransactionOutputModel], multiera_used_inputs_to_outputs_map: &BTreeMap, BTreeMap>, @@ -71,11 +69,28 @@ async fn handle( .map(|output| ((output.tx_id, output.output_index), output)) .collect(); - for (tx_body, cardano_transaction) in block.1.txs().iter().zip(multiera_txs) { - for input in tx_body.inputs().iter().chain(tx_body.collateral().iter()) { + for (tx_body, cardano_transaction) in block.1.transaction_bodies().iter().zip(multiera_txs) { + let collateral_inputs = tx_body + .collateral_inputs() + .cloned() + .unwrap_or_default() + .into_iter() + .map(MultiEraTransactionInput::Shelley) + .collect::>(); + + for input in tx_body.inputs().iter().chain(collateral_inputs.iter()) { let utxo = multiera_used_inputs_to_outputs_map - .get(input.hash().as_ref()) - .and_then(|by_index| by_index.get(&(input.index() as i64))); + .get( + input + .hash() + .ok_or(DbErr::Custom("can't get hash of input".to_string()))? + .to_raw_bytes(), + ) + .and_then(|by_index| { + input + .index() + .and_then(|index| by_index.get(&(index as i64))) + }); let utxo = if let Some(utxo) = utxo { utxo @@ -94,34 +109,46 @@ async fn handle( continue; }; - let output = MultiEraOutput::decode(utxo.era, &utxo.model.payload).unwrap(); - - for asset in output.non_ada_assets() { - let (policy_id, asset_name, value) = match asset { - Asset::Ada(_) => continue, - Asset::NativeAsset(policy_id, asset_name, value) => { - (policy_id, asset_name, value) - } - }; + let output = output_from_bytes(utxo)?; + let output = match output { + MultiEraTransactionOutput::Byron(_) => { + continue; + } + MultiEraTransactionOutput::Shelley(shelley) => shelley, + }; + for (policy_id, asset_name, value) in + output + .amount() + .multiasset + .iter() + .flat_map(|(policy_id, assets)| { + assets + .iter() + .map(|(asset_name, value)| (*policy_id, asset_name, value)) + }) + { // 0 values were allowed in the serialization of multiassets // before conway. We need to filter these here, because the // asset may not actually be in the assets table. - if value == 0 { + if *value == 0 { continue; } condition = condition.add( Condition::all() - .add(entity::native_asset::Column::PolicyId.eq(policy_id.as_ref())) - .add(entity::native_asset::Column::AssetName.eq(asset_name.clone())), + .add( + entity::native_asset::Column::PolicyId + .eq(policy_id.to_raw_bytes().to_vec()), + ) + .add(entity::native_asset::Column::AssetName.eq(asset_name.get().clone())), ); queued_inserts.push(PartialEntry { utxo_id: utxo.model.id, amount: None, tx_id: cardano_transaction.id, - asset: (policy_id.as_ref().to_vec(), asset_name), + asset: (policy_id.to_raw_bytes().to_vec(), asset_name.get().clone()), }); } } @@ -132,13 +159,7 @@ async fn handle( .chain(tx_body.collateral_return().iter()) .enumerate() { - let address = output - .address() - .map_err(|err| DbErr::Custom(format!("invalid pallas address: {}", err)))? - .to_vec(); - - let address = cardano_multiplatform_lib::address::Address::from_bytes(address) - .map_err(|err| DbErr::Custom(format!("cml can't parse address: {}", err)))?; + let address = output.address(); if address.payment_cred().is_none() { continue; @@ -152,32 +173,45 @@ async fn handle( Some(output) => output, }; - for asset in output.non_ada_assets() { - let (policy_id, asset_name, value) = match asset { - Asset::Ada(_) => continue, - Asset::NativeAsset(policy_id, asset_name, value) => { - (policy_id, asset_name, value) - } - }; + let output = match output { + MultiEraTransactionOutput::Byron(_) => { + continue; + } + MultiEraTransactionOutput::Shelley(shelley) => shelley, + }; + for (policy_id, asset_name, value) in + output + .amount() + .multiasset + .iter() + .flat_map(|(policy_id, assets)| { + assets + .iter() + .map(|(asset_name, value)| (*policy_id, asset_name, value)) + }) + { // 0 values were allowed in the serialization of multiassets // before conway. We need to filter these here, because the // asset may not actually be in the assets table. - if value == 0 { + if *value == 0 { continue; } condition = condition.add( Condition::all() - .add(entity::native_asset::Column::PolicyId.eq(policy_id.as_ref())) - .add(entity::native_asset::Column::AssetName.eq(asset_name.clone())), + .add( + entity::native_asset::Column::PolicyId + .eq(policy_id.to_raw_bytes().to_vec()), + ) + .add(entity::native_asset::Column::AssetName.eq(asset_name.get().clone())), ); queued_inserts.push(PartialEntry { utxo_id: output_model.id, - amount: Some(value as i64), + amount: Some(*value as i64), tx_id: cardano_transaction.id, - asset: (policy_id.as_ref().to_vec(), asset_name), + asset: (policy_id.to_raw_bytes().to_vec(), asset_name.get().clone()), }); } } diff --git a/indexer/tasks/src/multiera/multiera_block.rs b/indexer/tasks/src/multiera/multiera_block.rs index 4acebbad..5f74d611 100644 --- a/indexer/tasks/src/multiera/multiera_block.rs +++ b/indexer/tasks/src/multiera/multiera_block.rs @@ -4,9 +4,6 @@ use crate::dsl::task_macro::*; use crate::era_common::block_from_hash; use crate::utils::blake2b256; use entity::sea_orm::{DatabaseTransaction, Set}; -use pallas::ledger::primitives::alonzo::{self}; -use pallas::ledger::primitives::Fragment; -use pallas::ledger::traverse::MultiEraBlock; carp_task! { name MultieraBlockTask; @@ -32,11 +29,11 @@ carp_task! { async fn handle_block( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, readonly: bool, include_payload: bool, ) -> Result { - let hash = blake2b256(block.1.header().cbor()); + let hash = block.1.hash(); if readonly { return block_from_hash(db_tx, &hash).await; } @@ -48,9 +45,9 @@ async fn handle_block( let block = BlockActiveModel { era: Set(block.2.era.into()), hash: Set(hash.to_vec()), - height: Set(block.1.number() as i32), + height: Set(block.1.header().block_number() as i32), epoch: Set(block.2.epoch.unwrap() as i32), - slot: Set(block.1.slot() as i32), + slot: Set(block.1.header().slot() as i32), payload: Set(Some(block_payload)), ..Default::default() }; diff --git a/indexer/tasks/src/multiera/multiera_cip25entry.rs b/indexer/tasks/src/multiera/multiera_cip25entry.rs index 4a1b7c56..6042e100 100644 --- a/indexer/tasks/src/multiera/multiera_cip25entry.rs +++ b/indexer/tasks/src/multiera/multiera_cip25entry.rs @@ -1,16 +1,13 @@ use std::collections::{BTreeMap, BTreeSet}; use crate::config::EmptyConfig::EmptyConfig; -use cardano_multiplatform_lib::crypto::ScriptHash; +use cml_chain::crypto::ScriptHash; +use cml_core::metadata::TransactionMetadatum; +use cml_core::serialization::FromBytes; use entity::{ prelude::*, sea_orm::{prelude::*, Condition, DatabaseTransaction, Set}, }; -use pallas::ledger::primitives::Fragment; -use pallas::{ - codec::utils::KeyValuePairs, - ledger::primitives::alonzo::{self, AuxiliaryData, Metadatum, MetadatumLabel}, -}; use super::{ multiera_asset_mint::MultieraAssetMintTask, @@ -30,7 +27,7 @@ carp_task! { read [multiera_assets, multiera_metadata]; write []; should_add_task |block, _properties| { - block.1.has_aux_data() + !block.1.auxiliary_data_set().is_empty() }; execute |previous_data, task| handle_entries( task.db_tx, @@ -62,9 +59,10 @@ async fn handle_entries( let mut to_insert: Vec = vec![]; for metadata in multiera_metadata { - if let Ok(pairs) = - &get_cip25_pairs(&Metadatum::decode_fragment(metadata.payload.as_slice()).unwrap()) - { + if let Ok(pairs) = &get_cip25_pairs( + &TransactionMetadatum::from_bytes(metadata.payload.clone()) + .map_err(|err| DbErr::Custom(format!("can't decode metadata: {err}")))?, + ) { for ((asset_name, payload), policy_id) in pairs .1 .iter() diff --git a/indexer/tasks/src/multiera/multiera_datum.rs b/indexer/tasks/src/multiera/multiera_datum.rs index d73478e4..21acf81c 100644 --- a/indexer/tasks/src/multiera/multiera_datum.rs +++ b/indexer/tasks/src/multiera/multiera_datum.rs @@ -1,3 +1,7 @@ +use cml_chain::transaction::DatumOption; +use cml_core::serialization::Serialize; +use cml_crypto::{DatumHash, RawBytesEncoding}; +use cml_multi_era::utils::MultiEraTransactionOutput; use std::collections::BTreeSet; use super::multiera_txs::MultieraTransactionTask; @@ -12,12 +16,6 @@ use entity::{ prelude::*, sea_orm::{prelude::*, Condition, DatabaseTransaction, JoinType, Set}, }; -use pallas::ledger::primitives::Fragment; -use pallas::ledger::traverse::ComputeHash; -use pallas::ledger::{ - primitives::babbage::{DatumHash, DatumOption}, - traverse::{MultiEraBlock, OutputRef}, -}; use crate::dsl::task_macro::*; @@ -30,9 +28,16 @@ dependencies [MultieraTransactionTask]; read [multiera_txs]; write []; should_add_task |block, _properties| { - block.1.txs().iter().any(|tx| { - !tx.plutus_data().is_empty() || tx.outputs().iter().any(|output| output.datum().is_some()) - }) + block.1.transaction_bodies().iter().any(|tx| { + tx.outputs().iter().any(|output| match output { + MultiEraTransactionOutput::Shelley(output) => output.datum().is_some(), + _ => false, + }) + }) || block.1.transaction_witness_sets().iter().any(|tx| { + tx.plutus_datums.clone() + .map(|datums| !datums.is_empty()) + .unwrap_or(false) + }) }; execute |previous_data, task| handle_datum( task.db_tx, @@ -46,45 +51,62 @@ merge_result |previous_data, _result| { async fn handle_datum( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], readonly: bool, ) -> Result<(), DbErr> { - let mut hash_to_tx = BTreeMap::::new(); + let mut hash_to_tx = BTreeMap::::new(); // recall: tx may contain datum hash only w/ datum only appearing in a later tx - let mut hash_to_data = BTreeMap::>::new(); - for (tx_body, cardano_transaction) in block.1.txs().iter().zip(multiera_txs) { - for datum in tx_body.plutus_data() { - let hash = datum.compute_hash(); + let mut hash_to_data = BTreeMap::>::new(); + for ((tx_body, tx_witness_set), cardano_transaction) in block + .1 + .transaction_bodies() + .iter() + .zip(block.1.transaction_witness_sets().iter()) + .zip(multiera_txs) + { + for datum in tx_witness_set + .plutus_datums + .clone() + .unwrap_or_default() + .iter() + { + let hash = datum.hash(); hash_to_tx .entry(hash) .or_insert_with(|| cardano_transaction.id); hash_to_data .entry(hash) - .or_insert_with(|| datum.encode_fragment().unwrap()); + .or_insert_with(|| datum.to_cbor_bytes()); } for output in tx_body.outputs().iter() { + let output = match output { + MultiEraTransactionOutput::Byron(_) => { + continue; + } + MultiEraTransactionOutput::Shelley(shelley) => shelley, + }; let datum_option = match output.datum() { - Some(datum) => DatumOption::from(datum.clone()), + Some(datum) => datum, None => { continue; } }; match datum_option { - DatumOption::Hash(hash) => { + DatumOption::Hash { datum_hash, .. } => { hash_to_tx - .entry(hash) + .entry(datum_hash) .or_insert_with(|| cardano_transaction.id); } - DatumOption::Data(datum) => { - let hash = datum.compute_hash(); + DatumOption::Datum { datum, .. } => { + let hash = datum.hash(); hash_to_tx .entry(hash) .or_insert_with(|| cardano_transaction.id); hash_to_data .entry(hash) - .or_insert_with(|| datum.0.encode_fragment().unwrap()); + .or_insert_with(|| datum.to_cbor_bytes()); } }; } @@ -98,17 +120,16 @@ async fn handle_datum( let mut existing_full_datums = BTreeSet::::new(); // 1) Get hashes that were already in the DB { - let mut found_hashes = - PlutusDataHash::find() - .join(JoinType::LeftJoin, PlutusDataHashRelation::PlutusData.def()) - .filter(Condition::any().add( - PlutusDataHashColumn::Hash.is_in(hash_to_tx.keys().map(|hash| hash.as_ref())), - )) - // TODO: would be more efficient to just select the ID field of PlutusData - // to avoid having to return large datum objects that we just ignore in the SQL query - .select_with(PlutusData) - .all(db_tx) - .await?; + let mut found_hashes = PlutusDataHash::find() + .join(JoinType::LeftJoin, PlutusDataHashRelation::PlutusData.def()) + .filter(Condition::any().add( + PlutusDataHashColumn::Hash.is_in(hash_to_tx.keys().map(|hash| hash.to_raw_bytes())), + )) + // TODO: would be more efficient to just select the ID field of PlutusData + // to avoid having to return large datum objects that we just ignore in the SQL query + .select_with(PlutusData) + .all(db_tx) + .await?; for (datum_hash, datums) in found_hashes.iter() { if !datums.is_empty() { @@ -125,12 +146,12 @@ async fn handle_datum( { let keys_to_add: Vec<&DatumHash> = hash_to_tx .keys() - .filter(|key| !hash_to_id.contains_key(key.as_ref())) + .filter(|key| !hash_to_id.contains_key(key.to_raw_bytes())) .collect(); let to_add: Vec = keys_to_add .iter() .map(|key| PlutusDataHashActiveModel { - hash: Set(key.to_vec()), + hash: Set(key.to_raw_bytes().to_vec()), first_tx: Set(*hash_to_tx.get(key).unwrap()), ..Default::default() }) @@ -141,7 +162,9 @@ async fn handle_datum( panic!( "{} in readonly mode, but unknown Plutus datum hashes were found: {:?}", "MultieraDatumTask", - keys_to_add.iter().map(|key| hex::encode(key.as_ref())) + keys_to_add + .iter() + .map(|key| hex::encode(key.to_raw_bytes())) ); } let mut new_entries = PlutusDataHash::insert_many(to_add) @@ -155,12 +178,12 @@ async fn handle_datum( // 3) Add datum { let to_add = hash_to_data.iter().fold(vec![], |mut acc, next| { - let datum_hash_id = hash_to_id.get(next.0.as_ref()).unwrap(); + let datum_hash_id = hash_to_id.get(next.0.to_raw_bytes()).unwrap(); match existing_full_datums.get(datum_hash_id) { None => { acc.push(PlutusDataActiveModel { id: Set(*datum_hash_id), - data: Set(next.1.encode_fragment().unwrap()), + data: Set(next.1.clone()), }); acc } diff --git a/indexer/tasks/src/multiera/multiera_executor.rs b/indexer/tasks/src/multiera/multiera_executor.rs index 2d6931b6..1d26b9f9 100644 --- a/indexer/tasks/src/multiera/multiera_executor.rs +++ b/indexer/tasks/src/multiera/multiera_executor.rs @@ -7,14 +7,12 @@ use crate::execution_plan::ExecutionPlan; use crate::utils::find_task_registry_entry; use crate::utils::TaskPerfAggregator; use entity::sea_orm::{prelude::*, DatabaseTransaction}; -use pallas::ledger::primitives::alonzo; -use pallas::ledger::traverse::MultiEraBlock; use shred::{DispatcherBuilder, World}; use tokio::runtime::Handle; pub async fn process_multiera_block( txn: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, exec_plan: &ExecutionPlan, perf_aggregator: Arc>, ) -> Result<(), DbErr> { diff --git a/indexer/tasks/src/multiera/multiera_metadata.rs b/indexer/tasks/src/multiera/multiera_metadata.rs index 28616900..4e3663ed 100644 --- a/indexer/tasks/src/multiera/multiera_metadata.rs +++ b/indexer/tasks/src/multiera/multiera_metadata.rs @@ -1,3 +1,6 @@ +use cml_chain::auxdata::AuxiliaryData; +use cml_core::metadata::Metadata; +use cml_core::serialization::Serialize; use std::collections::BTreeMap; use crate::config::ReadonlyConfig::ReadonlyConfig; @@ -7,12 +10,6 @@ use entity::{ prelude::*, sea_orm::{prelude::*, DatabaseTransaction, Set}, }; -use pallas::ledger::primitives::Fragment; -use pallas::ledger::traverse::{MultiEraBlock, MultiEraMeta}; -use pallas::{ - codec::utils::KeyValuePairs, - ledger::primitives::alonzo::{self, AuxiliaryData, Metadatum, MetadatumLabel}, -}; use super::multiera_txs::MultieraTransactionTask; @@ -27,7 +24,7 @@ carp_task! { read [multiera_txs]; write [multiera_metadata]; should_add_task |block, _properties| { - block.1.has_aux_data() + !block.1.auxiliary_data_set().is_empty() }; execute |previous_data, task| handle_metadata( task.db_tx, @@ -42,7 +39,7 @@ carp_task! { async fn handle_metadata( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], readonly: bool, ) -> Result, DbErr> { @@ -54,13 +51,20 @@ async fn handle_metadata( .await; } - let mut metadata_map = BTreeMap::::default(); + let mut metadata_map = BTreeMap::::default(); - let txs = block.1.txs(); + let tx_aux_data = block.1.auxiliary_data_set(); - for (idx, tx) in txs.iter().enumerate() { - let tx_id = &multiera_txs[idx].id; - let meta = tx.metadata(); + for (idx, metadata) in tx_aux_data.iter() { + let tx_id = &multiera_txs[*idx as usize].id; + let meta = match metadata { + AuxiliaryData::Conway(data) => match &data.metadata { + None => continue, + Some(metadata) => metadata.clone(), + }, + AuxiliaryData::Shelley(data) => data.clone(), + AuxiliaryData::ShelleyMA(data) => data.transaction_metadata.clone(), + }; if !meta.is_empty() { metadata_map.insert(*tx_id, meta); @@ -74,18 +78,12 @@ async fn handle_metadata( TransactionMetadata::insert_many( metadata_map .iter() - .flat_map(|(tx_id, metadata)| { - metadata - .as_alonzo() - .unwrap() - .iter() - .zip(std::iter::repeat(tx_id)) - }) + .flat_map(|(tx_id, metadata)| metadata.entries.iter().zip(std::iter::repeat(tx_id))) .map( |((label, metadata), tx_id)| TransactionMetadataActiveModel { tx_id: Set(*tx_id), label: Set(label.to_le_bytes().to_vec()), - payload: Set(metadata.encode_fragment().unwrap()), + payload: Set(metadata.to_cbor_bytes()), ..Default::default() }, ), diff --git a/indexer/tasks/src/multiera/multiera_minswap_v1_mean_price.rs b/indexer/tasks/src/multiera/multiera_minswap_v1_mean_price.rs index 47f16713..ba741232 100644 --- a/indexer/tasks/src/multiera/multiera_minswap_v1_mean_price.rs +++ b/indexer/tasks/src/multiera/multiera_minswap_v1_mean_price.rs @@ -12,7 +12,7 @@ carp_task! { read [multiera_txs, multiera_addresses]; write []; should_add_task |block, _properties| { - block.1.txs().iter().any(|tx| tx.outputs().len() > 0) + block.1.transaction_bodies().iter().any(|tx| !tx.outputs().is_empty()) }; execute |previous_data, task| handle_mean_price( task.db_tx, diff --git a/indexer/tasks/src/multiera/multiera_minswap_v1_swap.rs b/indexer/tasks/src/multiera/multiera_minswap_v1_swap.rs index 807db920..ae4c3496 100644 --- a/indexer/tasks/src/multiera/multiera_minswap_v1_swap.rs +++ b/indexer/tasks/src/multiera/multiera_minswap_v1_swap.rs @@ -12,7 +12,7 @@ carp_task! { read [multiera_txs, multiera_addresses, multiera_used_inputs_to_outputs_map]; write []; should_add_task |block, _properties| { - block.1.txs().iter().any(|tx| tx.outputs().len() > 0) + block.1.transaction_bodies().iter().any(|tx| !tx.outputs().is_empty()) }; execute |previous_data, task| handle_swap( task.db_tx, diff --git a/indexer/tasks/src/multiera/multiera_projected_nft.rs b/indexer/tasks/src/multiera/multiera_projected_nft.rs index 4f5b363e..36fd006e 100644 --- a/indexer/tasks/src/multiera/multiera_projected_nft.rs +++ b/indexer/tasks/src/multiera/multiera_projected_nft.rs @@ -1,11 +1,10 @@ -use cardano_multiplatform_lib::error::DeserializeError; -use cml_core::serialization::FromBytes; -use cml_crypto::RawBytesEncoding; -use pallas::ledger::primitives::alonzo::{Redeemer, RedeemerTag}; -use pallas::ledger::primitives::babbage::DatumOption; -use pallas::ledger::primitives::Fragment; -use pallas::ledger::traverse::{Asset, MultiEraOutput, MultiEraTx}; -use projected_nft_sdk::{Owner, Redeem, State, Status}; +use cardano_projected_nft::{Owner, Redeem, State, Status}; +use cml_chain::plutus::{Redeemer, RedeemerTag}; +use cml_chain::transaction::DatumOption; +use cml_core::serialization::{FromBytes, Serialize}; +use cml_crypto::{Ed25519KeyHash, RawBytesEncoding, TransactionHash}; +use cml_multi_era::utils::MultiEraTransactionOutput; +use cml_multi_era::MultiEraTransactionBody; use sea_orm::{FromQueryResult, JoinType, QuerySelect, QueryTrait}; use std::cmp::Ordering; use std::collections::{BTreeSet, HashMap, HashSet}; @@ -115,7 +114,7 @@ impl ProjectedNftInputsQueryOutputResult { async fn handle_projected_nft( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], multiera_outputs: &[TransactionOutputModel], multiera_used_inputs_to_outputs_map: &BTreeMap, BTreeMap>, @@ -129,11 +128,17 @@ async fn handle_projected_nft( let mut queued_projected_nft_records = vec![]; - for (tx_body, cardano_transaction) in block.1.txs().iter().zip(multiera_txs) { + for ((tx_body, tx_witness), cardano_transaction) in block + .1 + .transaction_bodies() + .iter() + .zip(block.1.transaction_witness_sets()) + .zip(multiera_txs) + { // redeemers are needed to identify which of the projected nfts are partial withdrawals - let redeemers = tx_body - .redeemers() - .map(get_projected_nft_redeemers) + let redeemers = tx_witness + .redeemers + .map(|redeemers| get_projected_nft_redeemers(&redeemers)) .unwrap_or(Ok(BTreeMap::new()))?; // partial withdrawals inputs -- inputs which have partial withdraw = true in the redeemer @@ -153,17 +158,11 @@ async fn handle_projected_nft( let mut projected_nft_outputs = Vec::::new(); for (output_index, output) in tx_body.outputs().iter().enumerate() { - let output_address = output - .address() - .map_err(|err| DbErr::Custom(format!("invalid pallas address: {}", err)))? - .to_vec(); + let output_address = output.address(); - let output_address = - cardano_multiplatform_lib::address::Address::from_bytes(output_address) - .map_err(|err| DbErr::Custom(format!("cml can't parse address: {}", err)))?; let output_payment_cred = match output_address.payment_cred() { None => continue, - Some(pk) => pk, + Some(pk) => pk.clone(), }; if output_payment_cred != projected_nft_contract_payment_cred { @@ -182,7 +181,7 @@ async fn handle_projected_nft( // parse the state and fetch projected nft details let projected_nft_data = - extract_operation_and_datum(output, output_model, &partial_withdrawals_inputs); + extract_operation_and_datum(output, output_model, &partial_withdrawals_inputs)?; // if projected nft data is unlocking output that is created via partial withdrawal // then we reduce associated partial withdrawal input balance by the amounts that are being unlocked @@ -351,9 +350,7 @@ fn handle_partial_withdraw( Ok(()) } -fn get_payment_cred( - address: String, -) -> Result { +fn get_payment_cred(address: String) -> Result { let config_address = hex::decode(address).map_err(|err| { DbErr::Custom(format!( "can't decode projected nft config address hex: {:?}", @@ -361,13 +358,13 @@ fn get_payment_cred( )) })?; - let config_address = cardano_multiplatform_lib::address::Address::from_bytes(config_address) + let config_address = cml_chain::address::Address::from_bytes(config_address) .map_err(|err| DbErr::Custom(format!("cml can't parse config address: {:?}", err)))?; match config_address.payment_cred() { None => Err(DbErr::Custom( "provided projected nft config address contains no payment cred".to_string(), )), - Some(pk) => Ok(pk), + Some(pk) => Ok(pk.clone()), } } @@ -426,7 +423,7 @@ async fn get_projected_nft_inputs( } fn handle_claims_and_partial_withdraws( - tx_body: &MultiEraTx, + tx_body: &MultiEraTransactionBody, cardano_transaction: &TransactionModel, redeemers: &BTreeMap, used_projected_nfts: &BTreeMap< @@ -438,20 +435,28 @@ fn handle_claims_and_partial_withdraws( let mut partially_withdrawn = BTreeMap::new(); let mut sorted_inputs = tx_body.inputs(); - sorted_inputs.sort_by(|left, right| match left.hash().cmp(right.hash()) { + sorted_inputs.sort_by(|left, right| match left.hash().cmp(&right.hash()) { Ordering::Less => Ordering::Less, Ordering::Equal => left.index().cmp(&right.index()), Ordering::Greater => Ordering::Greater, }); - for (input_index, input) in sorted_inputs.iter().enumerate() { - let entry = if let Some(entry) = used_projected_nfts.get(&input.hash().to_vec()) { + for (sorted_input_index, input) in sorted_inputs.iter().enumerate() { + let input_hash = match input.hash() { + None => continue, + Some(hash) => hash.to_raw_bytes().to_vec(), + }; + let input_index = match input.index() { + None => continue, + Some(index) => index, + }; + let entry = if let Some(entry) = used_projected_nfts.get(&input_hash) { entry } else { continue; }; - let projected_nfts = if let Some(projected_nfts) = entry.get(&(input.index() as i64)) { + let projected_nfts = if let Some(projected_nfts) = entry.get(&(input_index as i64)) { projected_nfts } else { continue; @@ -477,12 +482,12 @@ fn handle_claims_and_partial_withdraws( }); } if projected_nft.operation == i32::from(ProjectedNftOperation::Lock) { - let redeemer = match redeemers.get(&(input_index as i64)) { + let redeemer = match redeemers.get(&(sorted_input_index as i64)) { None => { tracing::warn!( "No redeemer found for {}, {}", hex::encode(cardano_transaction.hash.clone()), - input_index + sorted_input_index ); continue; } @@ -497,9 +502,9 @@ fn handle_claims_and_partial_withdraws( if !current_input_partial_withrawal.is_empty() { *partially_withdrawn - .entry(input.hash().to_vec()) + .entry(input_hash) .or_insert(BTreeMap::new()) - .entry(input.index() as i64) + .entry(input_index as i64) .or_default() = current_input_partial_withrawal; } } @@ -578,83 +583,81 @@ struct ProjectedNftData { } fn extract_operation_and_datum( - output: &MultiEraOutput, + output: &MultiEraTransactionOutput, output_model: entity::transaction_output::Model, partial_withdrawals: &BTreeMap< Vec, BTreeMap>, >, -) -> ProjectedNftData { +) -> Result { + let output = match output { + MultiEraTransactionOutput::Byron(_) => { + return Err(DbErr::Custom( + "got byron block in projected nft task".to_string(), + )); + } + MultiEraTransactionOutput::Shelley(shelley) => shelley.clone(), + }; let datum_option = match output.datum() { - Some(datum) => DatumOption::from(datum.clone()), + Some(datum) => datum, None => { - return ProjectedNftData { + return Ok(ProjectedNftData { operation: ProjectedNftOperation::NoDatum, ..Default::default() - }; + }); } }; let datum = match datum_option { - DatumOption::Hash(hash) => { - return ProjectedNftData { - plutus_data: hash.to_vec(), + DatumOption::Hash { datum_hash, .. } => { + return Ok(ProjectedNftData { + plutus_data: datum_hash.to_raw_bytes().to_vec(), // the contract expects inline datums only operation: ProjectedNftOperation::NotInlineDatum, ..Default::default() - }; + }); } - DatumOption::Data(datum) => datum.0.encode_fragment().unwrap(), + DatumOption::Datum { datum, .. } => datum, }; - let parsed = match cml_chain::plutus::PlutusData::from_bytes(datum.clone()) { - Ok(parsed) => parsed, - Err(_) => { - return ProjectedNftData { - plutus_data: datum, - operation: ProjectedNftOperation::ParseError, - ..Default::default() - } - } - }; + let datum_bytes = datum.to_cbor_bytes(); - let parsed = match projected_nft_sdk::State::try_from(parsed) { + let parsed = match cardano_projected_nft::State::try_from(datum_bytes.as_slice()) { Ok(parsed) => parsed, Err(_) => { - return ProjectedNftData { - plutus_data: datum, + return Ok(ProjectedNftData { + plutus_data: datum_bytes, operation: ProjectedNftOperation::ParseError, ..Default::default() - } + }); } }; let owner_address = match parsed.owner { - Owner::PKH(pkh) => pkh.to_raw_bytes().to_vec(), + Owner::PKH(pkh) => Ed25519KeyHash::from_hex(&pkh.to_hex()) + .map_err(|_err| DbErr::Custom("can't parse pkh".to_string()))? + .to_raw_bytes() + .to_vec(), Owner::NFT(_, _) => vec![], Owner::Receipt(_) => vec![], }; let non_ada_assets = output - .non_ada_assets() + .amount() + .multiasset .iter() - .map(|asset| match asset { - Asset::Ada(value) => AssetData { - policy_id: "".to_string(), - asset_name: "".to_string(), - amount: *value as i64, - }, - Asset::NativeAsset(policy_id, asset_name, value) => AssetData { - policy_id: hex::encode(policy_id), - asset_name: hex::encode(asset_name.clone()), + .flat_map(|(policy_id, assets)| { + assets.iter().map(|(asset_name, value)| AssetData { + policy_id: policy_id.to_hex(), + asset_name: hex::encode(asset_name.get()), amount: *value as i64, - }, + }) }) .collect::>(); - match parsed.status { + let result = match parsed.status { Status::Locked => ProjectedNftData { address: owner_address, - plutus_data: datum, + plutus_data: datum_bytes, operation: ProjectedNftOperation::Lock, hololocker_utxo_id: output_model.id, non_ada_assets, @@ -664,7 +667,10 @@ fn extract_operation_and_datum( out_ref, for_how_long, } => { - let out_ref_tx_id = out_ref.tx_id.to_raw_bytes().to_vec(); + let out_ref_tx_id = TransactionHash::from_hex(&out_ref.tx_id.to_hex()) + .map_err(|_err| DbErr::Custom("can't parse tx hash".to_string()))? + .to_raw_bytes() + .to_vec(); let partial_withdrawn_from = partial_withdrawals.get(&out_ref_tx_id).and_then(|inner| { if inner.contains_key(&(out_ref.index as i64)) { @@ -678,15 +684,25 @@ fn extract_operation_and_datum( previous_utxo_tx_hash: out_ref_tx_id, previous_utxo_tx_output_index: Some(out_ref.index as i64), address: owner_address, - plutus_data: datum, + plutus_data: datum_bytes, operation: ProjectedNftOperation::Unlocking, - for_how_long: Some(for_how_long as i64), + for_how_long: Some(match for_how_long.as_u64() { + None => { + return Err(DbErr::Custom(format!( + "for how long does not fit into u64 {}", + for_how_long + ))) + } + Some(ok) => ok as i64, + }), hololocker_utxo_id: output_model.id, partial_withdrawn_from_input: partial_withdrawn_from, non_ada_assets, } } - } + }; + + Ok(result) } fn get_projected_nft_redeemers(redeemers: &[Redeemer]) -> Result, DbErr> { @@ -697,11 +713,7 @@ fn get_projected_nft_redeemers(redeemers: &[Redeemer]) -> Result { result.insert(redeemer.index as i64, redeem); } diff --git a/indexer/tasks/src/multiera/multiera_reference_inputs.rs b/indexer/tasks/src/multiera/multiera_reference_inputs.rs index d978d42c..33b5faed 100644 --- a/indexer/tasks/src/multiera/multiera_reference_inputs.rs +++ b/indexer/tasks/src/multiera/multiera_reference_inputs.rs @@ -3,16 +3,17 @@ use std::collections::BTreeMap; use crate::dsl::database_task::BlockGlobalInfo; use crate::types::TxCredentialRelationValue; use crate::{config::ReadonlyConfig::ReadonlyConfig, era_common::OutputWithTxData}; -use cardano_multiplatform_lib::{ +use cml_chain::{ address::{BaseAddress, EnterpriseAddress, PointerAddress, RewardAddress}, byron::ByronAddress, }; +use cml_crypto::RawBytesEncoding; +use cml_multi_era::utils::MultiEraTransactionInput; use entity::sea_orm::QueryOrder; use entity::{ prelude::*, sea_orm::{prelude::*, Condition, DatabaseTransaction, Set}, }; -use pallas::ledger::traverse::{MultiEraBlock, MultiEraInput, OutputRef}; use super::{ multiera_used_inputs::add_input_relations, multiera_used_outputs::MultieraOutputTask, @@ -30,7 +31,7 @@ carp_task! { read [multiera_txs]; write [vkey_relation_map]; should_add_task |block, _properties| { - block.1.txs().iter().any(|tx| !tx.reference_inputs().is_empty()) + block.1.transaction_bodies().iter().any(|tx| !tx.reference_inputs().cloned().unwrap_or_default().is_empty()) }; execute |previous_data, task| handle_input( task.db_tx, @@ -44,25 +45,27 @@ carp_task! { } type QueuedInputs = Vec<( - Vec, + Vec, i64, // tx_id )>; async fn handle_input( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], vkey_relation_map: &mut RelationMap, readonly: bool, ) -> Result, DbErr> { let mut queued_inputs = QueuedInputs::default(); - let txs = block.1.txs(); + let txs = block.1.transaction_bodies(); for (tx_body, cardano_transaction) in txs.iter().zip(multiera_txs) { let refs = tx_body .reference_inputs() - .iter() - .map(|x| x.output_ref()) + .cloned() + .unwrap_or_default() + .into_iter() + .map(MultiEraTransactionInput::Shelley) .collect(); queued_inputs.push((refs, cardano_transaction.id)); } @@ -106,7 +109,7 @@ async fn handle_input( } pub async fn insert_reference_inputs( - inputs: &[(Vec, i64)], + inputs: &[(Vec, i64)], input_to_output_map: &BTreeMap, BTreeMap>, txn: &DatabaseTransaction, ) -> Result, DbErr> { @@ -121,7 +124,8 @@ pub async fn insert_reference_inputs( .iter() .flat_map(|pair| pair.0.iter().enumerate().zip(std::iter::repeat(pair.1))) .map(|((idx, input), tx_id)| { - let output = &input_to_output_map[&input.hash().to_vec()][&(input.index() as i64)]; + let output = &input_to_output_map[&input.hash().unwrap().to_raw_bytes().to_vec()] + [&(input.index().unwrap() as i64)]; TransactionReferenceInputActiveModel { utxo_id: Set(output.model.id), address_id: Set(output.model.address_id), diff --git a/indexer/tasks/src/multiera/multiera_stake_credentials.rs b/indexer/tasks/src/multiera/multiera_stake_credentials.rs index f8f315f6..62f1127b 100644 --- a/indexer/tasks/src/multiera/multiera_stake_credentials.rs +++ b/indexer/tasks/src/multiera/multiera_stake_credentials.rs @@ -1,6 +1,10 @@ +use cml_chain::transaction::utils::RequiredSignersSet; +use cml_chain::transaction::TransactionWitnessSet; +use cml_core::serialization::FromBytes; +use cml_crypto::RawBytesEncoding; use std::collections::{BTreeMap, BTreeSet}; +use std::hash::Hash; -use cardano_multiplatform_lib::RequiredSignersSet; use entity::{ prelude::*, sea_orm::{prelude::*, Condition, DatabaseTransaction, Set}, @@ -15,10 +19,6 @@ use super::{ use crate::config::EmptyConfig::EmptyConfig; use crate::dsl::database_task::BlockGlobalInfo; use crate::dsl::task_macro::*; -use pallas::ledger::{ - primitives::Fragment, - traverse::{MultiEraBlock, MultiEraTx}, -}; carp_task! { name MultieraStakeCredentialTask; @@ -44,45 +44,32 @@ carp_task! { }; } -pub fn to_witness_cbor(tx: &MultiEraTx) -> Vec { - match tx { - MultiEraTx::AlonzoCompatible(x, _) => x.transaction_witness_set.encode_fragment().unwrap(), - MultiEraTx::Babbage(x) => x.transaction_witness_set.encode_fragment().unwrap(), - MultiEraTx::Byron(x) => x.witness.encode_fragment().unwrap(), - _ => panic!("to_witness_cbor - Unhandled tx type"), - } -} - async fn handle_stake_credentials( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], vkey_relation_map: &mut RelationMap, ) -> Result, StakeCredentialModel>, DbErr> { - for (tx_body, cardano_transaction) in block.1.txs().iter().zip(multiera_txs) { + for ((tx_body, tx_witness), cardano_transaction) in block + .1 + .transaction_bodies() + .iter() + .zip(block.1.transaction_witness_sets().iter()) + .zip(multiera_txs) + { queue_witness( vkey_relation_map, cardano_transaction.id, - &cardano_multiplatform_lib::TransactionWitnessSet::from_bytes(to_witness_cbor(tx_body)) - .map_err(|e| { - panic!( - "{:?} {:?} {:?}", - e, - hex::encode(tx_body.hash()), - hex::encode(to_witness_cbor(tx_body)) - ) - }) - .unwrap(), + tx_witness.clone(), ); - for signer in tx_body.required_signers().collect::>() { - let owner_credential = - pallas::ledger::primitives::alonzo::StakeCredential::AddrKeyhash(*signer) - .encode_fragment() - .unwrap(); + for signer in tx_body.required_signers().cloned().unwrap_or_default() { + let owner_credential = cml_chain::certs::Credential::new_pub_key(signer) + .to_raw_bytes() + .to_vec(); vkey_relation_map.add_relation( cardano_transaction.id, - &owner_credential.clone(), + &owner_credential, TxCredentialRelationValue::RequiredSigner, ); } @@ -159,24 +146,22 @@ async fn insert_stake_credentials( fn queue_witness( vkey_relation_map: &mut RelationMap, tx_id: i64, - witness_set: &cardano_multiplatform_lib::TransactionWitnessSet, + witness_set: TransactionWitnessSet, ) { - if let Some(vkeys) = witness_set.vkeys() { - for i in 0..vkeys.len() { - let vkey = vkeys.get(i); + if let Some(vkeys) = witness_set.vkeywitnesses { + for vkey in vkeys { vkey_relation_map.add_relation( tx_id, - RelationMap::keyhash_to_pallas(&vkey.vkey().public_key().hash()).as_slice(), + vkey.vkey.hash().to_raw_bytes(), TxCredentialRelationValue::Witness, ); } } - if let Some(scripts) = witness_set.native_scripts() { - for i in 0..scripts.len() { - let script = scripts.get(i); + if let Some(scripts) = witness_set.native_scripts { + for script in scripts { vkey_relation_map.add_relation( tx_id, - RelationMap::scripthash_to_pallas(&script.hash()).as_slice(), + script.hash().to_raw_bytes(), TxCredentialRelationValue::Witness, ); @@ -184,29 +169,27 @@ fn queue_witness( for vkey_in_script in vkeys_in_script { vkey_relation_map.add_relation( tx_id, - RelationMap::keyhash_to_pallas(&vkey_in_script).as_slice(), + vkey_in_script.to_raw_bytes(), TxCredentialRelationValue::InNativeScript, ); } } } - if let Some(scripts) = &witness_set.plutus_v1_scripts() { - for i in 0..scripts.len() { - let script = scripts.get(i); + if let Some(scripts) = &witness_set.plutus_v1_scripts { + for script in scripts { vkey_relation_map.add_relation( tx_id, - RelationMap::scripthash_to_pallas(&script.hash()).as_slice(), + script.hash().to_raw_bytes(), TxCredentialRelationValue::Witness, ); } } - if let Some(scripts) = &witness_set.plutus_v2_scripts() { - for i in 0..scripts.len() { - let script = scripts.get(i); + if let Some(scripts) = &witness_set.plutus_v2_scripts { + for script in scripts { vkey_relation_map.add_relation( tx_id, - RelationMap::scripthash_to_pallas(&script.hash()).as_slice(), + script.hash().to_raw_bytes(), TxCredentialRelationValue::Witness, ); } diff --git a/indexer/tasks/src/multiera/multiera_sundaeswap_v1_mean_price.rs b/indexer/tasks/src/multiera/multiera_sundaeswap_v1_mean_price.rs index e3e458f2..87d6c179 100644 --- a/indexer/tasks/src/multiera/multiera_sundaeswap_v1_mean_price.rs +++ b/indexer/tasks/src/multiera/multiera_sundaeswap_v1_mean_price.rs @@ -12,7 +12,7 @@ carp_task! { read [multiera_txs, multiera_addresses]; write []; should_add_task |block, _properties| { - block.1.txs().iter().any(|tx| tx.outputs().len() > 0) + block.1.transaction_bodies().iter().any(|tx| !tx.outputs().is_empty()) }; execute |previous_data, task| handle_mean_price( task.db_tx, diff --git a/indexer/tasks/src/multiera/multiera_sundaeswap_v1_swap.rs b/indexer/tasks/src/multiera/multiera_sundaeswap_v1_swap.rs index 2481b02c..7fcdfe20 100644 --- a/indexer/tasks/src/multiera/multiera_sundaeswap_v1_swap.rs +++ b/indexer/tasks/src/multiera/multiera_sundaeswap_v1_swap.rs @@ -12,7 +12,7 @@ carp_task! { read [multiera_txs, multiera_addresses, multiera_used_inputs_to_outputs_map]; write []; should_add_task |block, _properties| { - block.1.txs().iter().any(|tx| tx.outputs().len() > 0) + block.1.transaction_bodies().iter().any(|tx| !tx.outputs().is_empty()) }; execute |previous_data, task| handle_swap( task.db_tx, diff --git a/indexer/tasks/src/multiera/multiera_txs.rs b/indexer/tasks/src/multiera/multiera_txs.rs index 3cd14be5..5d1d1b93 100644 --- a/indexer/tasks/src/multiera/multiera_txs.rs +++ b/indexer/tasks/src/multiera/multiera_txs.rs @@ -1,4 +1,5 @@ -use std::collections::BTreeSet; +use cml_core::serialization::Serialize; +use std::collections::{BTreeSet, HashSet}; use super::multiera_block::MultieraBlockTask; use crate::config::PayloadAndReadonlyConfig::PayloadAndReadonlyConfig; @@ -6,9 +7,6 @@ use crate::dsl::database_task::BlockGlobalInfo; use crate::dsl::task_macro::*; use crate::era_common::transactions_from_hashes; use entity::sea_orm::{DatabaseTransaction, QueryOrder, Set}; -use pallas::ledger::primitives::alonzo::{self}; -use pallas::ledger::primitives::Fragment; -use pallas::ledger::traverse::MultiEraBlock; carp_task! { name MultieraTransactionTask; @@ -35,7 +33,7 @@ carp_task! { async fn handle_tx( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, database_block: &BlockModel, readonly: bool, include_payload: bool, @@ -45,7 +43,7 @@ async fn handle_tx( db_tx, block .1 - .txs() + .transaction_bodies() .iter() .map(|tx_body| tx_body.hash().to_vec()) .collect::>() @@ -55,19 +53,30 @@ async fn handle_tx( return txs; } + let invalid_txs: HashSet = HashSet::from_iter( + block + .1 + .invalid_transactions() + .into_iter() + .map(|index| index as usize), + ); let txs: Vec = block .1 - .txs() + .transaction_bodies() .iter() .enumerate() .map(|(idx, tx)| { - let tx_payload = if include_payload { tx.encode() } else { vec![] }; + let tx_payload = if include_payload { + tx.to_cbor_bytes() + } else { + vec![] + }; TransactionActiveModel { hash: Set(tx.hash().to_vec()), block_id: Set(database_block.id), tx_index: Set(idx as i32), payload: Set(tx_payload), - is_valid: Set(tx.is_valid()), + is_valid: Set(!invalid_txs.contains(&idx)), ..Default::default() } }) diff --git a/indexer/tasks/src/multiera/multiera_unused_input.rs b/indexer/tasks/src/multiera/multiera_unused_input.rs index 798dc42b..9bddc303 100644 --- a/indexer/tasks/src/multiera/multiera_unused_input.rs +++ b/indexer/tasks/src/multiera/multiera_unused_input.rs @@ -4,11 +4,11 @@ use super::{ }; use crate::dsl::database_task::BlockGlobalInfo; use crate::{config::EmptyConfig::EmptyConfig, types::TxCredentialRelationValue}; +use cml_multi_era::utils::MultiEraTransactionInput; use entity::{ prelude::*, sea_orm::{prelude::*, DatabaseTransaction}, }; -use pallas::ledger::traverse::{MultiEraBlock, OutputRef}; use crate::dsl::task_macro::*; @@ -22,7 +22,7 @@ carp_task! { write [vkey_relation_map]; should_add_task |block, _properties| { // if any txs has collateral defined, then it has some unused input (either collateral or main inputs if tx failed) - block.1.txs().iter().any(|tx| tx.collateral().len() > 0) + block.1.transaction_bodies().iter().any(|tx| !tx.collateral_inputs().cloned().unwrap_or_default().is_empty()) }; execute |previous_data, task| handle_unused_input( task.db_tx, @@ -34,20 +34,20 @@ carp_task! { }; } -type QueuedInputs = Vec<(Vec, i64)>; +type QueuedInputs = Vec<(Vec, i64)>; async fn handle_unused_input( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], vkey_relation_map: &mut RelationMap, ) -> Result<(), DbErr> { let mut queued_unused_inputs = QueuedInputs::default(); - let txs = block.1.txs(); + let txs = block.1.transaction_bodies(); for (tx_body, cardano_transaction) in txs.iter().zip(multiera_txs) { if !cardano_transaction.is_valid { - let refs = tx_body.inputs().iter().map(|x| x.output_ref()).collect(); + let refs = tx_body.inputs(); queued_unused_inputs.push((refs, cardano_transaction.id)) } @@ -55,9 +55,11 @@ async fn handle_unused_input( // note: we consider collateral as just another kind of input instead of a separate table // you can use the is_valid field to know what kind of input it actually is let refs = tx_body - .collateral() - .iter() - .map(|x| x.output_ref()) + .collateral_inputs() + .cloned() + .unwrap_or_default() + .into_iter() + .map(MultiEraTransactionInput::Shelley) .collect(); queued_unused_inputs.push((refs, cardano_transaction.id)) } diff --git a/indexer/tasks/src/multiera/multiera_used_inputs.rs b/indexer/tasks/src/multiera/multiera_used_inputs.rs index 6f05d315..83a3fe43 100644 --- a/indexer/tasks/src/multiera/multiera_used_inputs.rs +++ b/indexer/tasks/src/multiera/multiera_used_inputs.rs @@ -4,15 +4,17 @@ use crate::dsl::database_task::BlockGlobalInfo; use crate::era_common::input_from_pointer; use crate::types::TxCredentialRelationValue; use crate::{config::ReadonlyConfig::ReadonlyConfig, era_common::OutputWithTxData}; -use cardano_multiplatform_lib::{ +use cml_chain::{ address::{BaseAddress, EnterpriseAddress, PointerAddress, RewardAddress}, byron::ByronAddress, }; +use cml_core::serialization::{FromBytes, ToBytes}; +use cml_crypto::RawBytesEncoding; +use cml_multi_era::utils::MultiEraTransactionInput; use entity::{ prelude::*, sea_orm::{prelude::*, DatabaseTransaction}, }; -use pallas::ledger::traverse::{MultiEraBlock, MultiEraInput, OutputRef}; use super::{multiera_used_outputs::MultieraOutputTask, relation_map::RelationMap}; @@ -44,13 +46,13 @@ carp_task! { } type QueuedInputs = Vec<( - Vec, + Vec, i64, // tx_id )>; async fn handle_input( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], vkey_relation_map: &mut RelationMap, readonly: bool, @@ -62,19 +64,21 @@ async fn handle_input( DbErr, > { let mut queued_inputs = QueuedInputs::default(); - let txs = block.1.txs(); + let txs = block.1.transaction_bodies(); for (tx_body, cardano_transaction) in txs.iter().zip(multiera_txs) { if cardano_transaction.is_valid { - let refs = tx_body.inputs().iter().map(|x| x.output_ref()).collect(); + let refs = tx_body.inputs(); queued_inputs.push((refs, cardano_transaction.id)); } if !cardano_transaction.is_valid { let refs = tx_body - .collateral() - .iter() - .map(|x| x.output_ref()) + .collateral_inputs() + .cloned() + .unwrap_or_default() + .into_iter() + .map(MultiEraTransactionInput::Shelley) .collect(); queued_inputs.push((refs, cardano_transaction.id)) } @@ -129,7 +133,7 @@ async fn handle_input( pub fn add_input_relations( vkey_relation_map: &mut RelationMap, - inputs: &[(Vec, i64)], + inputs: &[(Vec, i64)], outputs: &[&TransactionOutputModel], input_to_output_map: &BTreeMap, BTreeMap>, input_relation: TxCredentialRelationValue, @@ -138,25 +142,29 @@ pub fn add_input_relations( let mut output_to_input_tx = BTreeMap::::default(); for input_tx_pair in inputs.iter() { for input in input_tx_pair.0.iter() { - match input_to_output_map.get(&input.hash().to_vec()) { + match input_to_output_map.get(&input.hash().unwrap().to_raw_bytes().to_vec()) { Some(entry_for_tx) => { - let output = &entry_for_tx[&(input.index() as i64)]; + let output = &entry_for_tx[&(input.index().unwrap() as i64)]; output_to_input_tx.insert(output.model.id, input_tx_pair.1); } None => { - panic!("tx: {} index:{}", input.hash(), input.index()); + panic!( + "tx: {} index:{}", + input.hash().unwrap().to_hex(), + input.index().unwrap() + ); } } } } outputs.iter().for_each(|&output| { - match &cardano_multiplatform_lib::TransactionOutput::from_bytes(output.payload.clone()) { + match &cml_chain::transaction::TransactionOutput::from_bytes(output.payload.clone()) { Ok(payload) => { add_input_cred_relation( vkey_relation_map, output_to_input_tx[&output.id], - &payload.address(), + payload.address(), input_relation, input_stake_relation, ); @@ -171,45 +179,40 @@ pub fn add_input_relations( fn add_input_cred_relation( vkey_relation_map: &mut RelationMap, tx_id: i64, - addr: &cardano_multiplatform_lib::address::Address, + addr: &cml_chain::address::Address, input_relation: TxCredentialRelationValue, input_stake_relation: TxCredentialRelationValue, ) { if let Some(base_addr) = BaseAddress::from_address(addr) { // Payment Key { - vkey_relation_map.add_relation( - tx_id, - &base_addr.payment_cred().to_bytes(), - input_relation, - ); + vkey_relation_map.add_relation(tx_id, base_addr.payment.to_raw_bytes(), input_relation); } // Stake Key { vkey_relation_map.add_relation( tx_id, - &base_addr.stake_cred().to_bytes(), + base_addr.stake.to_raw_bytes(), input_stake_relation, ); } } else if let Some(reward_addr) = RewardAddress::from_address(addr) { - vkey_relation_map.add_relation( - tx_id, - &reward_addr.payment_cred().to_bytes(), - input_relation, - ); + vkey_relation_map.add_relation(tx_id, reward_addr.payment.to_raw_bytes(), input_relation); } else if ByronAddress::from_address(addr).is_some() { // Byron address has no credentials } else if let Some(enterprise_addr) = EnterpriseAddress::from_address(addr) { vkey_relation_map.add_relation( tx_id, - &enterprise_addr.payment_cred().to_bytes(), + enterprise_addr.payment.to_raw_bytes(), input_relation, ); } else if let Some(ptr_addr) = PointerAddress::from_address(addr) { - vkey_relation_map.add_relation(tx_id, &ptr_addr.payment_cred().to_bytes(), input_relation); + vkey_relation_map.add_relation(tx_id, ptr_addr.payment.to_raw_bytes(), input_relation); } else { - panic!("Unexpected address type {}", hex::encode(addr.to_bytes())); + panic!( + "Unexpected address type {}", + hex::encode(addr.to_raw_bytes()) + ); } } diff --git a/indexer/tasks/src/multiera/multiera_used_outputs.rs b/indexer/tasks/src/multiera/multiera_used_outputs.rs index 53b3f28e..ea503c6e 100644 --- a/indexer/tasks/src/multiera/multiera_used_outputs.rs +++ b/indexer/tasks/src/multiera/multiera_used_outputs.rs @@ -1,13 +1,12 @@ +use cml_core::serialization::{Serialize, ToBytes}; +use cml_multi_era::utils::MultiEraTransactionOutput; +use cml_multi_era::MultiEraTransactionBody; use std::collections::BTreeMap; use entity::{ prelude::*, sea_orm::{prelude::*, DatabaseTransaction, Set}, }; -use pallas::ledger::{ - primitives::Fragment, - traverse::{MultiEraBlock, MultiEraOutput, MultiEraTx}, -}; use super::multiera_address::MultieraAddressTask; use crate::config::ReadonlyConfig::ReadonlyConfig; @@ -26,7 +25,7 @@ carp_task! { write [multiera_outputs]; should_add_task |block, _properties| { // recall: txs may have no outputs if they just burn all inputs as fee - block.1.txs().iter().any(|tx| tx.outputs().len() > 0) + block.1.transaction_bodies().iter().any(|tx| !tx.outputs().is_empty()) }; execute |previous_data, task| handle_output( task.db_tx, @@ -46,38 +45,31 @@ struct QueuedOutput { tx_id: i64, idx: usize, payload: Vec, - address: Vec, // pallas::crypto::hash::Hash<32> + address: Vec, } async fn handle_output( db_tx: &DatabaseTransaction, - block: BlockInfo<'_, MultiEraBlock<'_>, BlockGlobalInfo>, + block: BlockInfo<'_, cml_multi_era::MultiEraBlock, BlockGlobalInfo>, multiera_txs: &[TransactionModel], addresses: &BTreeMap, AddressInBlock>, readonly: bool, ) -> Result, DbErr> { let mut queued_output = Vec::::default(); - for (tx_body, cardano_transaction) in block.1.txs().iter().zip(multiera_txs) { + for (tx_body, cardano_transaction) in block.1.transaction_bodies().iter().zip(multiera_txs) { let outputs = tx_body.outputs(); if cardano_transaction.is_valid { for (idx, output) in outputs.iter().enumerate() { - queue_output( - &mut queued_output, - tx_body, - cardano_transaction.id, - output, - idx, - ); + queue_output(&mut queued_output, cardano_transaction.id, output, idx); } } if !cardano_transaction.is_valid { - if let Some(output) = tx_body.collateral_return().as_ref() { + if let Some(output) = tx_body.collateral_return() { queue_output( &mut queued_output, - tx_body, cardano_transaction.id, - output, + &output, // only one collateral output is allowed // and its index is output.len() outputs.len(), @@ -103,19 +95,18 @@ async fn handle_output( fn queue_output( queued_output: &mut Vec, - tx_body: &MultiEraTx<'_>, tx_id: i64, - output: &MultiEraOutput, + output: &MultiEraTransactionOutput, idx: usize, ) { - let addr = output - .address() - .map_err(|e| panic!("{:?} {:?}", e, hex::encode(tx_body.hash()))) - .unwrap(); + let addr = output.address(); queued_output.push(QueuedOutput { - payload: output.encode(), - address: addr.to_vec(), + payload: match output { + MultiEraTransactionOutput::Byron(byron) => byron.to_bytes(), + MultiEraTransactionOutput::Shelley(shelley) => shelley.to_cbor_bytes(), + }, + address: addr.to_raw_bytes().to_vec(), tx_id, idx, }); diff --git a/indexer/tasks/src/multiera/multiera_wingriders_v1_mean_price.rs b/indexer/tasks/src/multiera/multiera_wingriders_v1_mean_price.rs index 2ccb0828..de7199ed 100644 --- a/indexer/tasks/src/multiera/multiera_wingriders_v1_mean_price.rs +++ b/indexer/tasks/src/multiera/multiera_wingriders_v1_mean_price.rs @@ -4,13 +4,8 @@ use super::utils::common::{ use super::{multiera_address::MultieraAddressTask, utils::common::asset_from_pair}; use crate::config::EmptyConfig::EmptyConfig; use crate::multiera::dex::common::{handle_mean_price, DexType}; -use pallas::ledger::primitives::alonzo; use crate::dsl::task_macro::*; -use pallas::ledger::{ - primitives::{alonzo::Certificate, Fragment}, - traverse::{MultiEraBlock, MultiEraCert, MultiEraOutput, MultiEraTx}, -}; carp_task! { name MultieraWingRidersV1MeanPriceTask; @@ -21,7 +16,7 @@ carp_task! { read [multiera_txs, multiera_addresses]; write []; should_add_task |block, _properties| { - block.1.txs().iter().any(|tx| tx.outputs().len() > 0) + block.1.transaction_bodies().iter().any(|tx| !tx.outputs().is_empty()) }; execute |previous_data, task| handle_mean_price( task.db_tx, diff --git a/indexer/tasks/src/multiera/multiera_wingriders_v1_swap.rs b/indexer/tasks/src/multiera/multiera_wingriders_v1_swap.rs index a856e50f..6fd1ba22 100644 --- a/indexer/tasks/src/multiera/multiera_wingriders_v1_swap.rs +++ b/indexer/tasks/src/multiera/multiera_wingriders_v1_swap.rs @@ -12,7 +12,7 @@ carp_task! { read [multiera_txs, multiera_addresses, multiera_used_inputs_to_outputs_map]; write []; should_add_task |block, _properties| { - block.1.txs().iter().any(|tx| tx.outputs().len() > 0) + block.1.transaction_bodies().iter().any(|tx| !tx.outputs().is_empty()) }; execute |previous_data, task| handle_swap( task.db_tx, diff --git a/indexer/tasks/src/multiera/relation_map.rs b/indexer/tasks/src/multiera/relation_map.rs index 89adf791..0f105899 100644 --- a/indexer/tasks/src/multiera/relation_map.rs +++ b/indexer/tasks/src/multiera/relation_map.rs @@ -1,34 +1,13 @@ use crate::types::TxCredentialRelationValue; -use pallas::crypto::hash::Hash; +use cml_chain::certs::Credential; +use cml_core::serialization::ToBytes; use std::collections::BTreeMap; #[derive(Default)] -pub struct RelationMap(pub BTreeMap, i32>>); +pub struct RelationMap(pub BTreeMap, i32>>); impl RelationMap { - pub fn bytes_to_pallas(bytes: &[u8]) -> Hash<32> { - let bytes: [u8; 32] = bytes.try_into().unwrap(); - Hash::<32>::from(bytes) - } - - pub fn keyhash_to_pallas( - keyhash: &cardano_multiplatform_lib::crypto::Ed25519KeyHash, - ) -> Hash<32> { - RelationMap::bytes_to_pallas( - &cardano_multiplatform_lib::address::StakeCredential::from_keyhash(keyhash).to_bytes(), - ) - } - - pub fn scripthash_to_pallas( - script_hash: &cardano_multiplatform_lib::crypto::ScriptHash, - ) -> Hash<32> { - RelationMap::bytes_to_pallas( - &cardano_multiplatform_lib::address::StakeCredential::from_scripthash(script_hash) - .to_bytes(), - ) - } - - pub fn for_transaction(&mut self, tx_id: i64) -> &mut BTreeMap, i32> { + pub fn for_transaction(&mut self, tx_id: i64) -> &mut BTreeMap, i32> { self.0.entry(tx_id).or_default() } @@ -41,7 +20,7 @@ impl RelationMap { let relation_int = i32::from(relation); let credential_map = self.for_transaction(tx_id); credential_map - .entry(RelationMap::bytes_to_pallas(stake_credential)) + .entry(stake_credential.to_vec()) .and_modify(|val| *val |= relation_int) .or_insert(relation_int); } diff --git a/indexer/tasks/src/multiera/utils/cip25_parse.rs b/indexer/tasks/src/multiera/utils/cip25_parse.rs index 99a70c39..ccfffc85 100644 --- a/indexer/tasks/src/multiera/utils/cip25_parse.rs +++ b/indexer/tasks/src/multiera/utils/cip25_parse.rs @@ -3,17 +3,18 @@ use std::collections::{BTreeMap, BTreeSet}; -use cardano_multiplatform_lib::crypto::ScriptHash; -use pallas::ledger::primitives::{alonzo::Metadatum, Fragment}; +use cml_chain::crypto::ScriptHash; +use cml_core::metadata::TransactionMetadatum; +use cml_core::serialization::{Serialize, ToBytes}; use super::user_asset::{AssetName, Cip25ParseError, Payload, PolicyId}; // Heuristic approach for filtering policy entries. This is the best I could // come up with. Is there a better, official way? -fn is_policy_key(key: &Metadatum) -> Option { +fn is_policy_key(key: &TransactionMetadatum) -> Option { match key { - Metadatum::Bytes(x) if x.len() == 28 => Some(x.to_vec()), - Metadatum::Text(x) if x.len() == 56 => hex::decode(x).ok(), + TransactionMetadatum::Bytes { bytes, .. } if bytes.len() == 28 => Some(bytes.clone()), + TransactionMetadatum::Text { text, .. } if text.len() == 56 => hex::decode(text).ok(), _ => None, } } @@ -21,36 +22,40 @@ fn is_policy_key(key: &Metadatum) -> Option { // Heuristic approach for filtering asset entries. Even less strict than when // searching for policies. In this case, we only check for valid data types. // There's probably a much more formal approach. -fn is_asset_key(key: &Metadatum) -> Option { +fn is_asset_key(key: &TransactionMetadatum) -> Option { match key { - Metadatum::Bytes(x) if x.len() <= 32 => Some(AssetName::from(x.as_slice())), - Metadatum::Text(x) if x.as_bytes().len() <= 32 => Some(AssetName::from(x.as_bytes())), + TransactionMetadatum::Bytes { bytes, .. } if bytes.len() <= 32 => Some(bytes.clone()), + TransactionMetadatum::Text { text, .. } if text.as_bytes().len() <= 32 => { + Some(text.as_bytes().to_vec()) + } _ => None, } } -fn search_cip25_version(content_721: &Metadatum) -> Option { +fn search_cip25_version(content_721: &TransactionMetadatum) -> Option { match content_721 { - Metadatum::Map(entries) => entries.iter().find_map(|(key, value)| match key { - Metadatum::Text(x) if x == "version" => match value { - Metadatum::Text(value) => Some(value.to_owned()), + TransactionMetadatum::Map(entries) => { + entries.entries.iter().find_map(|(key, value)| match key { + TransactionMetadatum::Text { text, .. } if text == "version" => match value { + TransactionMetadatum::Text { text, .. } => Some(text.clone()), + _ => None, + }, _ => None, - }, - _ => None, - }), + }) + } _ => None, } } fn get_cip25_assets( _version: &str, - content: &Metadatum, + content: &TransactionMetadatum, ) -> Result, Cip25ParseError> { let mut result = BTreeMap::::default(); - if let Metadatum::Map(entries) = content { - for (key, sub_content) in entries.iter() { + if let TransactionMetadatum::Map(entries) = content { + for (key, sub_content) in entries.entries.iter() { if let Some(asset) = &is_asset_key(key) { - result.insert(asset.clone(), sub_content.encode_fragment().unwrap()); + result.insert(asset.clone(), sub_content.to_cbor_bytes()); } } } else { @@ -64,13 +69,13 @@ fn get_cip25_assets( #[allow(clippy::type_complexity)] pub fn get_cip25_pairs( - content: &Metadatum, + content: &TransactionMetadatum, ) -> Result<(String, BTreeMap>), Cip25ParseError> { let version = search_cip25_version(content).unwrap_or_else(|| "1.0".to_string()); let mut result = BTreeMap::>::default(); - if let Metadatum::Map(entries) = content { - for (key, sub_content) in entries.iter() { + if let TransactionMetadatum::Map(entries) = content { + for (key, sub_content) in entries.entries.iter() { if let Some(policy_id) = is_policy_key(key) { if let Ok(asset_names) = get_cip25_assets(&version, sub_content) { result.insert(policy_id, asset_names); diff --git a/indexer/tasks/src/multiera/utils/common.rs b/indexer/tasks/src/multiera/utils/common.rs index e0742fe1..59a7c566 100644 --- a/indexer/tasks/src/multiera/utils/common.rs +++ b/indexer/tasks/src/multiera/utils/common.rs @@ -1,64 +1,84 @@ +use cml_chain::certs::Credential; +use cml_chain::transaction::DatumOption; +use cml_core::serialization::{Deserialize, Serialize, ToBytes}; +use cml_crypto::RawBytesEncoding; +use cml_multi_era::utils::{MultiEraTransactionInput, MultiEraTransactionOutput}; use std::collections::BTreeSet; +use crate::era_common::OutputWithTxData; +use entity::block::EraValue; use entity::{ prelude::*, sea_orm::{entity::*, prelude::*, Condition, DatabaseTransaction}, }; -use pallas::{ - codec::utils::KeepRaw, - crypto::hash::Hasher, - ledger::{ - addresses, - primitives::{alonzo, babbage::DatumOption}, - traverse::{Asset, MultiEraOutput}, - }, -}; use crate::types::AssetPair; +use crate::utils::blake2b256; + +pub fn get_shelley_payment_hash(address: cml_chain::address::Address) -> Option { + let payment = match address { + cml_chain::address::Address::Base(address) => address.payment, + // idk whether we should parse it here or not + cml_chain::address::Address::Ptr(address) => address.payment, + cml_chain::address::Address::Enterprise(address) => address.payment, + // reward address is a staking address + cml_chain::address::Address::Reward(_) => return None, + cml_chain::address::Address::Byron(_) => return None, + }; -pub fn get_shelley_payment_hash( - address: Result, -) -> Option { - if let Ok(addresses::Address::Shelley(shelley_address)) = address { - Some(hex::encode(shelley_address.payment().as_hash())) - } else { - None + match payment { + Credential::PubKey { hash, .. } => Some(hash.to_hex()), + Credential::Script { hash, .. } => Some(hash.to_hex()), } } -pub fn get_asset_amount(output: &MultiEraOutput, pair: &AssetPair) -> u64 { - output - .assets() - .iter() - .filter(|asset| match &asset { - Asset::Ada(_quantity) => pair.is_none(), - Asset::NativeAsset(policy_id, asset_name, _quantity) => { - pair == &Some((policy_id.to_vec(), asset_name.to_vec())) - } - }) - .map(|asset| match &asset { - Asset::Ada(quantity) => quantity, - Asset::NativeAsset(_, _, quantity) => quantity, - }) - .sum() +pub fn get_asset_amount( + output: &cml_multi_era::utils::MultiEraTransactionOutput, + pair: &AssetPair, +) -> u64 { + match pair { + None => output.amount().coin, + Some((pair_policy_id, pair_asset_name)) => output + .amount() + .multiasset + .iter() + .flat_map(|(policy_id, assets)| { + assets + .iter() + .map(|(asset_name, value)| (*policy_id, asset_name, value)) + }) + .filter(|(policy_id, asset_name, _value)| { + policy_id.to_raw_bytes() == pair_policy_id && asset_name.get() == pair_asset_name + }) + .map(|(_policy_id, _asset_name, value)| value) + .sum(), + } } pub fn get_plutus_datum_for_output( - output: &MultiEraOutput, - plutus_data: &[&KeepRaw], -) -> Option { + output: &cml_multi_era::utils::MultiEraTransactionOutput, + plutus_data: &[cml_chain::plutus::PlutusData], +) -> Option { + let output = match output { + MultiEraTransactionOutput::Byron(_) => { + return None; + } + MultiEraTransactionOutput::Shelley(output) => output, + }; + let datum_option = match output.datum() { - Some(datum) => DatumOption::from(datum), + Some(datum) => datum, None => { return None; } }; + match datum_option { - DatumOption::Data(datum) => Some(datum.0), - DatumOption::Hash(hash) => plutus_data + DatumOption::Datum { datum, .. } => Some(datum), + DatumOption::Hash { datum_hash, .. } => plutus_data .iter() - .find(|datum| Hasher::<256>::hash_cbor(datum) == hash) - .map(|&d| d.clone().unwrap()), + .find(|datum| datum.hash() == datum_hash) + .cloned(), } } @@ -82,3 +102,21 @@ pub async fn asset_from_pair( .await?; Ok(assets) } + +pub fn output_from_bytes(utxo: &OutputWithTxData) -> Result { + let output = match utxo.era { + EraValue::Byron => MultiEraTransactionOutput::Byron( + cml_chain::byron::ByronTxOut::from_cbor_bytes(&utxo.model.payload).map_err(|err| { + DbErr::Custom(format!("can't decode byron output payload: {err}")) + })?, + ), + _ => MultiEraTransactionOutput::Shelley( + cml_chain::transaction::TransactionOutput::from_cbor_bytes(&utxo.model.payload) + .map_err(|err| { + DbErr::Custom(format!("can't decode shelley output payload: {err}")) + })?, + ), + }; + + Ok(output) +} diff --git a/indexer/tasks/src/multiera/utils/user_asset.rs b/indexer/tasks/src/multiera/utils/user_asset.rs index 56455039..30d64f5f 100644 --- a/indexer/tasks/src/multiera/utils/user_asset.rs +++ b/indexer/tasks/src/multiera/utils/user_asset.rs @@ -1,4 +1,4 @@ -use cardano_multiplatform_lib::crypto::ScriptHash; +use cml_chain::crypto::ScriptHash; pub type AssetName = Vec; pub type PolicyId = Vec;