From ada94e8c5d4eecd755cca718f8eead7063684ce4 Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Tue, 2 Sep 2025 02:16:21 -0400 Subject: [PATCH] Get all processors to compile again Requires splitting `serai-cosign` into `serai-cosign` and `serai-cosign-types` so the processor don't require `serai-client/serai` (not correct yet). --- .github/workflows/tests.yml | 1 + Cargo.lock | 32 ++++----- Cargo.toml | 1 + coordinator/cosign/Cargo.toml | 2 + coordinator/cosign/src/lib.rs | 2 + coordinator/cosign/types/Cargo.toml | 25 +++++++ coordinator/cosign/types/LICENSE | 15 ++++ coordinator/cosign/types/src/lib.rs | 72 +++++++++++++++++++ processor/bin/Cargo.toml | 5 +- processor/bin/src/coordinator.rs | 8 +-- processor/bin/src/lib.rs | 2 +- processor/bitcoin/Cargo.toml | 1 - processor/bitcoin/src/primitives/output.rs | 13 ++-- processor/bitcoin/src/rpc.rs | 2 +- processor/bitcoin/src/scheduler.rs | 2 +- processor/ethereum/Cargo.toml | 1 - processor/ethereum/router/Cargo.toml | 1 - .../ethereum/router/contracts/IRouter.sol | 6 +- .../ethereum/router/contracts/Router.sol | 2 +- processor/ethereum/router/src/lib.rs | 24 ++++--- .../router/src/tests/in_instruction.rs | 27 +++---- processor/ethereum/src/main.rs | 2 +- processor/ethereum/src/primitives/mod.rs | 2 +- processor/ethereum/src/primitives/output.rs | 11 +-- processor/ethereum/src/rpc.rs | 2 +- processor/ethereum/src/scheduler.rs | 2 +- processor/frost-attempt-manager/Cargo.toml | 3 +- .../frost-attempt-manager/src/individual.rs | 2 +- processor/frost-attempt-manager/src/lib.rs | 2 +- processor/key-gen/Cargo.toml | 4 -- processor/key-gen/src/db.rs | 4 +- processor/key-gen/src/generators.rs | 2 +- processor/key-gen/src/lib.rs | 2 +- processor/messages/Cargo.toml | 3 +- processor/messages/src/lib.rs | 61 +++++++++------- processor/monero/Cargo.toml | 1 - processor/monero/src/primitives/output.rs | 11 ++- processor/monero/src/rpc.rs | 2 +- processor/monero/src/scheduler.rs | 2 +- processor/primitives/Cargo.toml | 1 - processor/primitives/src/lib.rs | 12 +--- processor/primitives/src/output.rs | 2 +- processor/primitives/src/payment.rs | 21 +++--- processor/scanner/Cargo.toml | 1 - processor/scanner/src/batch/db.rs | 8 +-- processor/scanner/src/batch/mod.rs | 37 ++++------ processor/scanner/src/db.rs | 30 ++++---- processor/scanner/src/eventuality/db.rs | 5 +- processor/scanner/src/lib.rs | 6 +- processor/scanner/src/report/db.rs | 2 +- processor/scanner/src/report/mod.rs | 12 ++-- processor/scanner/src/scan/mod.rs | 26 +++---- processor/scanner/src/substrate/db.rs | 2 +- processor/scanner/src/substrate/mod.rs | 4 +- processor/scheduler/primitives/Cargo.toml | 3 +- processor/scheduler/smart-contract/Cargo.toml | 3 +- .../scheduler/utxo/primitives/src/lib.rs | 2 +- .../scheduler/utxo/primitives/src/tree.rs | 5 +- processor/scheduler/utxo/standard/Cargo.toml | 3 +- processor/scheduler/utxo/standard/src/db.rs | 5 +- processor/scheduler/utxo/standard/src/lib.rs | 5 +- .../utxo/transaction-chaining/Cargo.toml | 3 +- .../utxo/transaction-chaining/src/db.rs | 2 +- .../utxo/transaction-chaining/src/lib.rs | 2 +- processor/signers/Cargo.toml | 3 +- processor/signers/src/batch/db.rs | 6 +- processor/signers/src/batch/mod.rs | 21 +++--- processor/signers/src/coordinator/mod.rs | 4 +- processor/signers/src/cosign/db.rs | 2 +- processor/signers/src/cosign/mod.rs | 6 +- processor/signers/src/db.rs | 2 +- processor/signers/src/lib.rs | 8 ++- processor/signers/src/slash_report.rs | 3 +- processor/signers/src/transaction/db.rs | 2 +- processor/signers/src/transaction/mod.rs | 2 +- substrate/client/Cargo.toml | 6 +- substrate/client/src/lib.rs | 14 ---- substrate/client/src/networks/bitcoin.rs | 11 ++- substrate/client/src/networks/ethereum.rs | 7 +- substrate/client/src/networks/monero.rs | 4 +- substrate/primitives/Cargo.toml | 6 +- substrate/primitives/src/address.rs | 8 ++- substrate/primitives/src/crypto.rs | 11 +++ .../primitives/src/instructions/in/batch.rs | 1 + .../primitives/src/instructions/in/mod.rs | 2 +- substrate/primitives/src/instructions/mod.rs | 5 +- substrate/primitives/src/network_id.rs | 16 ++--- 87 files changed, 413 insertions(+), 301 deletions(-) create mode 100644 coordinator/cosign/types/Cargo.toml create mode 100644 coordinator/cosign/types/LICENSE create mode 100644 coordinator/cosign/types/src/lib.rs diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index af93154e..bd93170c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -61,6 +61,7 @@ jobs: -p serai-monero-processor \ -p tendermint-machine \ -p tributary-sdk \ + -p serai-cosign-types \ -p serai-cosign \ -p serai-coordinator-substrate \ -p serai-coordinator-tributary \ diff --git a/Cargo.lock b/Cargo.lock index bcceed5b..59700472 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9706,7 +9706,6 @@ dependencies = [ "hex", "log", "modular-frost", - "parity-scale-codec", "rand_core 0.6.4", "secp256k1 0.29.1", "serai-client", @@ -9896,11 +9895,21 @@ dependencies = [ "parity-scale-codec", "schnorrkel", "serai-client", + "serai-cosign-types", "serai-db", "serai-task", "tokio", ] +[[package]] +name = "serai-cosign-types" +version = "0.1.0" +dependencies = [ + "borsh", + "schnorrkel", + "serai-primitives", +] + [[package]] name = "serai-db" version = "0.1.1" @@ -9999,7 +10008,6 @@ dependencies = [ "k256", "log", "modular-frost", - "parity-scale-codec", "rand_core 0.6.4", "serai-client", "serai-db", @@ -10136,7 +10144,6 @@ dependencies = [ "modular-frost", "monero-simple-request-rpc", "monero-wallet", - "parity-scale-codec", "rand_chacha 0.3.1", "rand_core 0.6.4", "serai-client", @@ -10258,6 +10265,7 @@ dependencies = [ "parity-scale-codec", "rand_core 0.6.4", "scale-info", + "schnorrkel", "sp-core", "zeroize", ] @@ -10272,8 +10280,7 @@ dependencies = [ "env_logger", "hex", "log", - "parity-scale-codec", - "serai-cosign", + "serai-cosign-types", "serai-db", "serai-env", "serai-message-queue", @@ -10355,7 +10362,6 @@ dependencies = [ "futures-util", "group", "k256", - "parity-scale-codec", "rand_core 0.6.4", "revm", "serai-client", @@ -10375,7 +10381,6 @@ dependencies = [ "borsh", "log", "modular-frost", - "parity-scale-codec", "rand_core 0.6.4", "serai-db", "serai-primitives", @@ -10392,7 +10397,6 @@ dependencies = [ "dkg-evrf", "flexible-transcript", "log", - "parity-scale-codec", "rand_chacha 0.3.1", "rand_core 0.6.4", "serai-db", @@ -10408,8 +10412,7 @@ dependencies = [ "borsh", "dkg", "hex", - "parity-scale-codec", - "serai-cosign", + "serai-cosign-types", "serai-primitives", ] @@ -10420,7 +10423,6 @@ dependencies = [ "borsh", "group", "log", - "parity-scale-codec", "serai-primitives", "serai-task", "tokio", @@ -10435,7 +10437,6 @@ dependencies = [ "group", "hex", "log", - "parity-scale-codec", "serai-db", "serai-primitives", "serai-processor-messages", @@ -10451,7 +10452,6 @@ dependencies = [ "borsh", "ciphersuite 0.4.2", "modular-frost", - "parity-scale-codec", "serai-db", ] @@ -10466,9 +10466,8 @@ dependencies = [ "frost-schnorrkel", "log", "modular-frost", - "parity-scale-codec", "rand_core 0.6.4", - "serai-cosign", + "serai-cosign-types", "serai-db", "serai-primitives", "serai-processor-frost-attempt-manager", @@ -10486,7 +10485,6 @@ version = "0.1.0" dependencies = [ "borsh", "group", - "parity-scale-codec", "serai-db", "serai-processor-primitives", "serai-processor-scanner", @@ -10499,7 +10497,6 @@ version = "0.1.0" dependencies = [ "borsh", "group", - "parity-scale-codec", "serai-db", "serai-primitives", "serai-processor-primitives", @@ -10514,7 +10511,6 @@ version = "0.1.0" dependencies = [ "borsh", "group", - "parity-scale-codec", "serai-db", "serai-primitives", "serai-processor-primitives", diff --git a/Cargo.toml b/Cargo.toml index f5d3a887..090b2f3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,6 +82,7 @@ members = [ "coordinator/tributary-sdk/tendermint", "coordinator/tributary-sdk", + "coordinator/cosign/types", "coordinator/cosign", "coordinator/substrate", "coordinator/tributary", diff --git a/coordinator/cosign/Cargo.toml b/coordinator/cosign/Cargo.toml index a6330be9..425018be 100644 --- a/coordinator/cosign/Cargo.toml +++ b/coordinator/cosign/Cargo.toml @@ -31,3 +31,5 @@ tokio = { version = "1", default-features = false } serai-db = { path = "../../common/db", version = "0.1.1" } serai-task = { path = "../../common/task", version = "0.1" } + +serai-cosign-types = { path = "./types" } diff --git a/coordinator/cosign/src/lib.rs b/coordinator/cosign/src/lib.rs index e98127b4..e1e5dbf9 100644 --- a/coordinator/cosign/src/lib.rs +++ b/coordinator/cosign/src/lib.rs @@ -19,6 +19,8 @@ use serai_client::{ use serai_db::*; use serai_task::*; +use serai_cosign_types::*; + /// The cosigns which are intended to be performed. mod intend; /// The evaluator of the cosigns. diff --git a/coordinator/cosign/types/Cargo.toml b/coordinator/cosign/types/Cargo.toml new file mode 100644 index 00000000..d0e51f12 --- /dev/null +++ b/coordinator/cosign/types/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "serai-cosign-types" +version = "0.1.0" +description = "Evaluator of cosigns for the Serai network" +license = "AGPL-3.0-only" +repository = "https://github.com/serai-dex/serai/tree/develop/coordinator/cosign" +authors = ["Luke Parker "] +keywords = [] +edition = "2021" +publish = false +rust-version = "1.85" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints] +workspace = true + +[dependencies] +schnorrkel = { version = "0.11", default-features = false, features = ["std"] } + +borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } + +serai-primitives = { path = "../../../substrate/primitives", default-features = false, features = ["std"] } diff --git a/coordinator/cosign/types/LICENSE b/coordinator/cosign/types/LICENSE new file mode 100644 index 00000000..621233a9 --- /dev/null +++ b/coordinator/cosign/types/LICENSE @@ -0,0 +1,15 @@ +AGPL-3.0-only license + +Copyright (c) 2023-2025 Luke Parker + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License Version 3 as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . diff --git a/coordinator/cosign/types/src/lib.rs b/coordinator/cosign/types/src/lib.rs new file mode 100644 index 00000000..62346166 --- /dev/null +++ b/coordinator/cosign/types/src/lib.rs @@ -0,0 +1,72 @@ +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![deny(missing_docs)] +//! Types used when cosigning Serai. For more info, please see `serai-cosign`. +use borsh::{BorshSerialize, BorshDeserialize}; + +use serai_primitives::{crypto::Public, network_id::ExternalNetworkId}; + +/// The schnorrkel context to used when signing a cosign. +pub const COSIGN_CONTEXT: &[u8] = b"/serai/coordinator/cosign"; + +/// An intended cosign. +#[derive(Clone, Copy, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] +pub struct CosignIntent { + /// The global session this cosign is being performed under. + pub global_session: [u8; 32], + /// The number of the block to cosign. + pub block_number: u64, + /// The hash of the block to cosign. + pub block_hash: [u8; 32], + /// If this cosign must be handled before further cosigns are. + pub notable: bool, +} + +/// A cosign. +#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] +pub struct Cosign { + /// The global session this cosign is being performed under. + pub global_session: [u8; 32], + /// The number of the block to cosign. + pub block_number: u64, + /// The hash of the block to cosign. + pub block_hash: [u8; 32], + /// The actual cosigner. + pub cosigner: ExternalNetworkId, +} + +impl CosignIntent { + /// Convert this into a `Cosign`. + pub fn into_cosign(self, cosigner: ExternalNetworkId) -> Cosign { + let CosignIntent { global_session, block_number, block_hash, notable: _ } = self; + Cosign { global_session, block_number, block_hash, cosigner } + } +} + +impl Cosign { + /// The message to sign to sign this cosign. + /// + /// This must be signed with schnorrkel, the context set to `COSIGN_CONTEXT`. + pub fn signature_message(&self) -> Vec { + // We use a schnorrkel context to domain-separate this + borsh::to_vec(self).unwrap() + } +} + +/// A signed cosign. +#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)] +pub struct SignedCosign { + /// The cosign. + pub cosign: Cosign, + /// The signature for the cosign. + pub signature: [u8; 64], +} + +impl SignedCosign { + /// Verify a cosign's signature. + pub fn verify_signature(&self, signer: Public) -> bool { + let Ok(signer) = schnorrkel::PublicKey::from_bytes(&signer.0) else { return false }; + let Ok(signature) = schnorrkel::Signature::from_bytes(&self.signature) else { return false }; + + signer.verify_simple(COSIGN_CONTEXT, &self.cosign.signature_message(), &signature).is_ok() + } +} diff --git a/processor/bin/Cargo.toml b/processor/bin/Cargo.toml index 7df18918..b37f9ef9 100644 --- a/processor/bin/Cargo.toml +++ b/processor/bin/Cargo.toml @@ -20,14 +20,13 @@ workspace = true zeroize = { version = "1", default-features = false, features = ["std"] } hex = { version = "0.4", default-features = false, features = ["std"] } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["std"] } dkg = { package = "dkg-evrf", path = "../../crypto/dkg/evrf", default-features = false, features = ["std", "ristretto"] } -serai-client = { path = "../../substrate/client", default-features = false } -serai-cosign = { path = "../../coordinator/cosign" } +serai-primitives = { path = "../../substrate/primitives", default-features = false, features = ["std"] } +serai-cosign = { package = "serai-cosign-types", path = "../../coordinator/cosign/types" } log = { version = "0.4", default-features = false, features = ["std"] } env_logger = { version = "0.10", default-features = false, features = ["humantime"] } diff --git a/processor/bin/src/coordinator.rs b/processor/bin/src/coordinator.rs index 62eb1097..e5defdc3 100644 --- a/processor/bin/src/coordinator.rs +++ b/processor/bin/src/coordinator.rs @@ -3,10 +3,10 @@ use std::sync::{LazyLock, Arc, Mutex}; use tokio::sync::mpsc; -use serai_client::{ - primitives::Signature, - validator_sets::primitives::{Session, SlashReport}, - in_instructions::primitives::SignedBatch, +use serai_primitives::{ + crypto::Signature, + validator_sets::{Session, SlashReport}, + instructions::SignedBatch, }; use serai_cosign::SignedCosign; diff --git a/processor/bin/src/lib.rs b/processor/bin/src/lib.rs index 73a0e374..8c61a9fb 100644 --- a/processor/bin/src/lib.rs +++ b/processor/bin/src/lib.rs @@ -8,7 +8,7 @@ use ciphersuite::{ }; use dkg::{Curves, Ristretto}; -use serai_client::validator_sets::primitives::Session; +use serai_primitives::validator_sets::Session; use serai_env as env; use serai_db::{Get, DbTxn, Db as DbTrait, create_db, db_channel}; diff --git a/processor/bitcoin/Cargo.toml b/processor/bitcoin/Cargo.toml index 673b3baa..6a7c907f 100644 --- a/processor/bitcoin/Cargo.toml +++ b/processor/bitcoin/Cargo.toml @@ -20,7 +20,6 @@ workspace = true rand_core = { version = "0.6", default-features = false } hex = { version = "0.4", default-features = false, features = ["std"] } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["std"] } diff --git a/processor/bitcoin/src/primitives/output.rs b/processor/bitcoin/src/primitives/output.rs index bd9ec8a7..ffacc282 100644 --- a/processor/bitcoin/src/primitives/output.rs +++ b/processor/bitcoin/src/primitives/output.rs @@ -10,12 +10,15 @@ use bitcoin_serai::{ wallet::ReceivedOutput as WalletOutput, }; -use scale::{Encode, Decode, IoReader}; use borsh::{BorshSerialize, BorshDeserialize}; use serai_db::Get; use serai_client::{ - primitives::{ExternalCoin, Amount, ExternalBalance, ExternalAddress}, + primitives::{ + coin::ExternalCoin, + balance::{Amount, ExternalBalance}, + address::ExternalAddress, + }, networks::bitcoin::Address, }; @@ -26,7 +29,7 @@ use crate::{ scan::{offsets_for_key, presumed_origin, extract_serai_data}, }; -#[derive(Clone, PartialEq, Eq, Hash, Debug, Encode, Decode, BorshSerialize, BorshDeserialize)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, BorshSerialize, BorshDeserialize)] pub(crate) struct OutputId([u8; 36]); impl Default for OutputId { fn default() -> Self { @@ -139,7 +142,7 @@ impl ReceivedOutput<::G, Address> for Output { fn write(&self, writer: &mut W) -> io::Result<()> { self.kind.write(writer)?; let presumed_origin: Option = self.presumed_origin.clone().map(Into::into); - writer.write_all(&presumed_origin.encode())?; + presumed_origin.serialize(writer)?; self.output.write(writer)?; writer.write_all(&u16::try_from(self.data.len()).unwrap().to_le_bytes())?; writer.write_all(&self.data) @@ -149,7 +152,7 @@ impl ReceivedOutput<::G, Address> for Output { Ok(Output { kind: OutputType::read(reader)?, presumed_origin: { - Option::::decode(&mut IoReader(&mut reader)) + Option::::deserialize_reader(&mut reader) .map_err(|e| io::Error::other(format!("couldn't decode ExternalAddress: {e:?}")))? .map(|address| { Address::try_from(address) diff --git a/processor/bitcoin/src/rpc.rs b/processor/bitcoin/src/rpc.rs index 4289c714..19cb1781 100644 --- a/processor/bitcoin/src/rpc.rs +++ b/processor/bitcoin/src/rpc.rs @@ -2,7 +2,7 @@ use core::future::Future; use bitcoin_serai::rpc::{RpcError, Rpc as BRpc}; -use serai_client::primitives::{ExternalNetworkId, ExternalCoin, Amount}; +use serai_client::primitives::{network_id::ExternalNetworkId, coin::ExternalCoin, balance::Amount}; use serai_db::Db; use scanner::ScannerFeed; diff --git a/processor/bitcoin/src/scheduler.rs b/processor/bitcoin/src/scheduler.rs index 2799f883..d971b9bd 100644 --- a/processor/bitcoin/src/scheduler.rs +++ b/processor/bitcoin/src/scheduler.rs @@ -9,7 +9,7 @@ use bitcoin_serai::{ }; use serai_client::{ - primitives::{ExternalCoin, Amount}, + primitives::{coin::ExternalCoin, balance::Amount}, networks::bitcoin::Address, }; diff --git a/processor/ethereum/Cargo.toml b/processor/ethereum/Cargo.toml index 8d642ffc..fb105f9f 100644 --- a/processor/ethereum/Cargo.toml +++ b/processor/ethereum/Cargo.toml @@ -21,7 +21,6 @@ rand_core = { version = "0.6", default-features = false } const-hex = { version = "1", default-features = false, features = ["std"] } hex = { version = "0.4", default-features = false, features = ["std"] } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["std"] } diff --git a/processor/ethereum/router/Cargo.toml b/processor/ethereum/router/Cargo.toml index 0a46dead..19c5ceff 100644 --- a/processor/ethereum/router/Cargo.toml +++ b/processor/ethereum/router/Cargo.toml @@ -41,7 +41,6 @@ ethereum-primitives = { package = "serai-processor-ethereum-primitives", path = ethereum-deployer = { package = "serai-processor-ethereum-deployer", path = "../deployer", default-features = false } erc20 = { package = "serai-processor-ethereum-erc20", path = "../erc20", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } serai-client = { path = "../../../substrate/client", default-features = false, features = ["ethereum"] } futures-util = { version = "0.3", default-features = false, features = ["std"] } diff --git a/processor/ethereum/router/contracts/IRouter.sol b/processor/ethereum/router/contracts/IRouter.sol index 1cf61f8e..24a3e66a 100644 --- a/processor/ethereum/router/contracts/IRouter.sol +++ b/processor/ethereum/router/contracts/IRouter.sol @@ -19,7 +19,7 @@ interface IRouterWithoutCollisions { /// @param from The address which called `inInstruction` and caused this event to be emitted /// @param coin The coin transferred in /// @param amount The amount of the coin transferred in - /// @param instruction The Shorthand-encoded InInstruction for Serai to decode and handle + /// @param instruction The encoded `RefundableInInstruction` for Serai to decode and handle event InInstruction( address indexed from, address indexed coin, uint256 amount, bytes instruction ); @@ -81,8 +81,8 @@ interface IRouterWithoutCollisions { /// @param coin The coin to transfer in (address(0) if Ether) /// @param amount The amount to transfer in (msg.value if Ether) /** - * @param instruction The Shorthand-encoded InInstruction for Serai to associate with this - * transfer in + * @param instruction The encoded `RefundableInInstruction` for Serai to associate with this + * transfer in */ // Re-entrancy doesn't bork this function // slither-disable-next-line reentrancy-events diff --git a/processor/ethereum/router/contracts/Router.sol b/processor/ethereum/router/contracts/Router.sol index bfb36cfd..593f6ca9 100644 --- a/processor/ethereum/router/contracts/Router.sol +++ b/processor/ethereum/router/contracts/Router.sol @@ -293,7 +293,7 @@ contract Router is IRouterWithoutCollisions { /// @param coin The coin to transfer in (address(0) if Ether) /// @param amount The amount to transfer in (msg.value if Ether) /** - * @param instruction The Shorthand-encoded InInstruction for Serai to associate with this + * @param instruction The encoded `RefundableInInstruction` for Serai to associate with this * transfer in */ // This function doesn't require nonReentrant as re-entrancy isn't an issue with this function diff --git a/processor/ethereum/router/src/lib.rs b/processor/ethereum/router/src/lib.rs index 02d5c0d9..cee9f079 100644 --- a/processor/ethereum/router/src/lib.rs +++ b/processor/ethereum/router/src/lib.rs @@ -21,9 +21,8 @@ use alloy_rpc_types_eth::{BlockId, Log, Filter, TransactionInput, TransactionReq use alloy_transport::{TransportErrorKind, RpcError}; use alloy_provider::{Provider, RootProvider}; -use scale::Encode; use serai_client::{ - in_instructions::primitives::Shorthand, networks::ethereum::Address as SeraiAddress, + primitives::instructions::RefundableInInstruction, networks::ethereum::Address as SeraiAddress, }; use ethereum_primitives::LogIndex; @@ -351,20 +350,29 @@ impl Router { } } - /// Construct a transaction to send coins with an InInstruction to Serai. + /// Construct a transaction to send coins with an `InInstruction` to Serai. /// /// If coin is an ERC20, this will not create a transaction calling the Router but will create a /// top-level transfer of the ERC20 to the Router. This avoids needing to call `approve` before /// publishing the transaction calling the Router. /// /// The gas limit and gas price are not set and are left to the caller. - pub fn in_instruction(&self, coin: Coin, amount: U256, in_instruction: &Shorthand) -> TxLegacy { + pub fn in_instruction( + &self, + coin: Coin, + amount: U256, + in_instruction: &RefundableInInstruction, + ) -> TxLegacy { match coin { Coin::Ether => TxLegacy { to: self.address.into(), - input: abi::inInstructionCall::new((coin.into(), amount, in_instruction.encode().into())) - .abi_encode() - .into(), + input: abi::inInstructionCall::new(( + coin.into(), + amount, + borsh::to_vec(&in_instruction).unwrap().into(), + )) + .abi_encode() + .into(), value: amount, ..Default::default() }, @@ -373,7 +381,7 @@ impl Router { input: erc20::transferWithInInstructionCall::new(( self.address, amount, - in_instruction.encode().into(), + borsh::to_vec(&in_instruction).unwrap().into(), )) .abi_encode() .into(), diff --git a/processor/ethereum/router/src/tests/in_instruction.rs b/processor/ethereum/router/src/tests/in_instruction.rs index 20ddfd02..2a6c8642 100644 --- a/processor/ethereum/router/src/tests/in_instruction.rs +++ b/processor/ethereum/router/src/tests/in_instruction.rs @@ -5,12 +5,9 @@ use alloy_sol_types::SolCall; use alloy_consensus::{TxLegacy, Signed}; -use scale::Encode; use serai_client::{ primitives::SeraiAddress, - in_instructions::primitives::{ - InInstruction as SeraiInInstruction, RefundableInInstruction, Shorthand, - }, + primitives::instructions::{InInstruction as SeraiInInstruction, RefundableInInstruction}, }; use ethereum_primitives::LogIndex; @@ -18,14 +15,14 @@ use ethereum_primitives::LogIndex; use crate::{InInstruction, tests::*}; impl Test { - pub(crate) fn in_instruction() -> Shorthand { - Shorthand::Raw(RefundableInInstruction { + pub(crate) fn in_instruction() -> RefundableInInstruction { + RefundableInInstruction { origin: None, instruction: SeraiInInstruction::Transfer(SeraiAddress([0xff; 32])), - }) + } } - pub(crate) fn eth_in_instruction_tx(&self) -> (Coin, U256, Shorthand, TxLegacy) { + pub(crate) fn eth_in_instruction_tx(&self) -> (Coin, U256, RefundableInInstruction, TxLegacy) { let coin = Coin::Ether; let amount = U256::from(1); let shorthand = Self::in_instruction(); @@ -42,7 +39,7 @@ impl Test { tx: Signed, coin: Coin, amount: U256, - shorthand: &Shorthand, + shorthand: &RefundableInInstruction, ) { let receipt = ethereum_test_primitives::publish_tx(&self.provider, tx.clone()).await; assert!(receipt.status()); @@ -81,7 +78,7 @@ impl Test { from: tx.recover_signer().unwrap(), coin, amount, - data: shorthand.encode(), + data: borsh::to_vec(&shorthand).unwrap(), } ); } @@ -140,9 +137,13 @@ async fn test_erc20_router_in_instruction() { gas_limit: 1_000_000, to: test.router.address().into(), value: U256::ZERO, - input: crate::abi::inInstructionCall::new((coin.into(), amount, shorthand.encode().into())) - .abi_encode() - .into(), + input: crate::abi::inInstructionCall::new(( + coin.into(), + amount, + borsh::to_vec(shorthand).unwrap().into(), + )) + .abi_encode() + .into(), }; // If no `approve` was granted, this should fail diff --git a/processor/ethereum/src/main.rs b/processor/ethereum/src/main.rs index 792a216e..ae366f15 100644 --- a/processor/ethereum/src/main.rs +++ b/processor/ethereum/src/main.rs @@ -14,7 +14,7 @@ use alloy_simple_request_transport::SimpleRequest; use alloy_rpc_client::ClientBuilder; use alloy_provider::{Provider, RootProvider}; -use serai_client::validator_sets::primitives::Session; +use serai_client::primitives::validator_sets::Session; use serai_env as env; use serai_db::{Get, DbTxn, create_db}; diff --git a/processor/ethereum/src/primitives/mod.rs b/processor/ethereum/src/primitives/mod.rs index 39f1eb94..859c1458 100644 --- a/processor/ethereum/src/primitives/mod.rs +++ b/processor/ethereum/src/primitives/mod.rs @@ -1,6 +1,6 @@ use alloy_core::primitives::{FixedBytes, Address}; -use serai_client::primitives::Amount; +use serai_client::primitives::balance::Amount; pub(crate) mod output; pub(crate) mod transaction; diff --git a/processor/ethereum/src/primitives/output.rs b/processor/ethereum/src/primitives/output.rs index 9fe2ba60..de08a20d 100644 --- a/processor/ethereum/src/primitives/output.rs +++ b/processor/ethereum/src/primitives/output.rs @@ -5,11 +5,14 @@ use ciphersuite_kp256::Secp256k1; use alloy_core::primitives::U256; -use scale::{Encode, Decode}; use borsh::{BorshSerialize, BorshDeserialize}; use serai_client::{ - primitives::{ExternalNetworkId, ExternalCoin, Amount, ExternalBalance}, + primitives::{ + network_id::ExternalNetworkId, + coin::ExternalCoin, + balance::{Amount, ExternalBalance}, + }, networks::ethereum::Address, }; @@ -39,9 +42,7 @@ fn amount_to_serai_amount(coin: ExternalCoin, amount: U256) -> Amount { Amount(u64::try_from(amount / divisor).unwrap()) } -#[derive( - Clone, Copy, PartialEq, Eq, Hash, Debug, Encode, Decode, BorshSerialize, BorshDeserialize, -)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, BorshSerialize, BorshDeserialize)] pub(crate) struct OutputId(pub(crate) [u8; 40]); impl Default for OutputId { fn default() -> Self { diff --git a/processor/ethereum/src/rpc.rs b/processor/ethereum/src/rpc.rs index 943a529c..908f5a3f 100644 --- a/processor/ethereum/src/rpc.rs +++ b/processor/ethereum/src/rpc.rs @@ -6,7 +6,7 @@ use alloy_rpc_types_eth::{Header, BlockNumberOrTag}; use alloy_transport::{RpcError, TransportErrorKind}; use alloy_provider::{Provider, RootProvider}; -use serai_client::primitives::{ExternalNetworkId, ExternalCoin, Amount}; +use serai_client::primitives::{network_id::ExternalNetworkId, coin::ExternalCoin, balance::Amount}; use tokio::task::JoinSet; diff --git a/processor/ethereum/src/scheduler.rs b/processor/ethereum/src/scheduler.rs index 07bf185d..b487dcbe 100644 --- a/processor/ethereum/src/scheduler.rs +++ b/processor/ethereum/src/scheduler.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use alloy_core::primitives::U256; use serai_client::{ - primitives::{ExternalNetworkId, ExternalCoin, ExternalBalance}, + primitives::{network_id::ExternalNetworkId, coin::ExternalCoin, balance::ExternalBalance}, networks::ethereum::Address, }; diff --git a/processor/frost-attempt-manager/Cargo.toml b/processor/frost-attempt-manager/Cargo.toml index 3f3c3839..4b4e47f2 100644 --- a/processor/frost-attempt-manager/Cargo.toml +++ b/processor/frost-attempt-manager/Cargo.toml @@ -15,7 +15,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [package.metadata.cargo-machete] -ignored = ["borsh", "scale"] +ignored = ["borsh"] [lints] workspace = true @@ -29,7 +29,6 @@ serai-primitives = { path = "../../substrate/primitives", default-features = fal log = { version = "0.4", default-features = false, features = ["std"] } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } serai-db = { path = "../../common/db" } diff --git a/processor/frost-attempt-manager/src/individual.rs b/processor/frost-attempt-manager/src/individual.rs index e918ff02..6912965e 100644 --- a/processor/frost-attempt-manager/src/individual.rs +++ b/processor/frost-attempt-manager/src/individual.rs @@ -7,7 +7,7 @@ use frost::{ sign::{Writable, PreprocessMachine, SignMachine, SignatureMachine}, }; -use serai_validator_sets_primitives::Session; +use serai_primitives::validator_sets::Session; use serai_db::{Get, DbTxn, Db, create_db}; use messages::sign::{VariantSignId, SignId, ProcessorMessage}; diff --git a/processor/frost-attempt-manager/src/lib.rs b/processor/frost-attempt-manager/src/lib.rs index 670d8d9f..9461622b 100644 --- a/processor/frost-attempt-manager/src/lib.rs +++ b/processor/frost-attempt-manager/src/lib.rs @@ -6,7 +6,7 @@ use std::collections::HashMap; use frost::{Participant, sign::PreprocessMachine}; -use serai_validator_sets_primitives::Session; +use serai_primitives::validator_sets::Session; use serai_db::{DbTxn, Db}; use messages::sign::{VariantSignId, ProcessorMessage, CoordinatorMessage}; diff --git a/processor/key-gen/Cargo.toml b/processor/key-gen/Cargo.toml index ab80116d..f55cd828 100644 --- a/processor/key-gen/Cargo.toml +++ b/processor/key-gen/Cargo.toml @@ -14,9 +14,6 @@ rust-version = "1.89" all-features = true rustdoc-args = ["--cfg", "docsrs"] -[package.metadata.cargo-machete] -ignored = ["scale"] - [lints] workspace = true @@ -38,7 +35,6 @@ dkg = { package = "dkg-evrf", path = "../../crypto/dkg/evrf", default-features = serai-primitives = { path = "../../substrate/primitives", default-features = false, features = ["std"] } # Encoders -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } # Application diff --git a/processor/key-gen/src/db.rs b/processor/key-gen/src/db.rs index 4496a9c6..56b6d321 100644 --- a/processor/key-gen/src/db.rs +++ b/processor/key-gen/src/db.rs @@ -6,7 +6,7 @@ use zeroize::Zeroizing; use ciphersuite::{group::GroupEncoding, Ciphersuite}; use dkg::*; -use serai_validator_sets_primitives::Session; +use serai_primitives::validator_sets::Session; use borsh::{BorshSerialize, BorshDeserialize}; use serai_db::{Get, DbTxn}; @@ -36,7 +36,7 @@ pub(crate) struct Participations { } mod _db { - use serai_validator_sets_primitives::Session; + use serai_primitives::validator_sets::Session; use serai_db::{Get, DbTxn, create_db}; diff --git a/processor/key-gen/src/generators.rs b/processor/key-gen/src/generators.rs index fa65f9fd..d76bb180 100644 --- a/processor/key-gen/src/generators.rs +++ b/processor/key-gen/src/generators.rs @@ -6,7 +6,7 @@ use std::{ use dkg::*; -use serai_validator_sets_primitives::MAX_KEY_SHARES_PER_SET; +use serai_primitives::constants::MAX_KEY_SHARES_PER_SET; /// A cache of the generators used by the eVRF DKG. /// diff --git a/processor/key-gen/src/lib.rs b/processor/key-gen/src/lib.rs index c605b791..a999e740 100644 --- a/processor/key-gen/src/lib.rs +++ b/processor/key-gen/src/lib.rs @@ -17,7 +17,7 @@ use ciphersuite::{ }; use dkg::*; -use serai_validator_sets_primitives::Session; +use serai_primitives::validator_sets::Session; use messages::key_gen::*; use serai_db::{Get, DbTxn}; diff --git a/processor/messages/Cargo.toml b/processor/messages/Cargo.toml index c3e5fbbc..f923ef9c 100644 --- a/processor/messages/Cargo.toml +++ b/processor/messages/Cargo.toml @@ -20,11 +20,10 @@ workspace = true [dependencies] hex = { version = "0.4", default-features = false, features = ["std"] } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } dkg = { path = "../../crypto/dkg", default-features = false, features = ["std", "borsh"] } serai-primitives = { path = "../../substrate/primitives", default-features = false, features = ["std"] } -serai-cosign = { path = "../../coordinator/cosign", default-features = false } +serai-cosign = { package = "serai-cosign-types", path = "../../coordinator/cosign/types" } diff --git a/processor/messages/src/lib.rs b/processor/messages/src/lib.rs index 7101fdc2..6734302d 100644 --- a/processor/messages/src/lib.rs +++ b/processor/messages/src/lib.rs @@ -1,15 +1,16 @@ use core::fmt; use std::collections::HashMap; -use scale::{Encode, Decode}; use borsh::{BorshSerialize, BorshDeserialize}; use dkg::Participant; -use serai_primitives::BlockHash; -use validator_sets_primitives::{Session, KeyPair, SlashReport}; -use coins_primitives::OutInstructionWithBalance; -use in_instructions_primitives::SignedBatch; +use serai_primitives::{ + BlockHash, + crypto::KeyPair, + validator_sets::{Session, SlashReport}, + instructions::{SignedBatch, OutInstructionWithBalance}, +}; use serai_cosign::{Cosign, SignedCosign}; @@ -87,7 +88,7 @@ pub mod key_gen { pub mod sign { use super::*; - #[derive(Clone, Copy, PartialEq, Eq, Hash, Encode, Decode, BorshSerialize, BorshDeserialize)] + #[derive(Clone, Copy, PartialEq, Eq, Hash, BorshSerialize, BorshDeserialize)] pub enum VariantSignId { Cosign(u64), Batch([u8; 32]), @@ -111,9 +112,7 @@ pub mod sign { } } - #[derive( - Clone, Copy, PartialEq, Eq, Hash, Debug, Encode, Decode, BorshSerialize, BorshDeserialize, - )] + #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, BorshSerialize, BorshDeserialize)] pub struct SignId { pub session: Session, pub id: VariantSignId, @@ -295,7 +294,7 @@ impl CoordinatorMessage { let (sub, id) = match msg { // Unique since we only have one attempt per session key_gen::CoordinatorMessage::GenerateKey { session, .. } => { - (0, borsh::to_vec(session).unwrap()) + (0, borsh::to_vec(&session).unwrap()) } // Unique since one participation per participant per session key_gen::CoordinatorMessage::Participation { session, participant, .. } => { @@ -316,17 +315,19 @@ impl CoordinatorMessage { }; let mut res = vec![COORDINATOR_UID, TYPE_SIGN_UID, sub]; - res.extend(id.encode()); + res.extend(borsh::to_vec(&id).unwrap()); res } CoordinatorMessage::Coordinator(msg) => { let (sub, id) = match msg { // We only cosign a block once, and Reattempt is a separate message coordinator::CoordinatorMessage::CosignSubstrateBlock { cosign, .. } => { - (0, cosign.block_number.encode()) + (0, borsh::to_vec(&cosign.block_number).unwrap()) } // We only sign one slash report, and Reattempt is a separate message - coordinator::CoordinatorMessage::SignSlashReport { session, .. } => (1, session.encode()), + coordinator::CoordinatorMessage::SignSlashReport { session, .. } => { + (1, borsh::to_vec(&session).unwrap()) + } }; let mut res = vec![COORDINATOR_UID, TYPE_COORDINATOR_UID, sub]; @@ -335,10 +336,14 @@ impl CoordinatorMessage { } CoordinatorMessage::Substrate(msg) => { let (sub, id) = match msg { - substrate::CoordinatorMessage::SetKeys { session, .. } => (0, session.encode()), - substrate::CoordinatorMessage::SlashesReported { session } => (1, session.encode()), + substrate::CoordinatorMessage::SetKeys { session, .. } => { + (0, borsh::to_vec(&session).unwrap()) + } + substrate::CoordinatorMessage::SlashesReported { session } => { + (1, borsh::to_vec(&session).unwrap()) + } substrate::CoordinatorMessage::Block { serai_block_number, .. } => { - (2, serai_block_number.encode()) + (2, borsh::to_vec(&serai_block_number).unwrap()) } }; @@ -363,10 +368,10 @@ impl ProcessorMessage { let (sub, id) = match msg { // Unique since we only have one participation per session (due to no re-attempts) key_gen::ProcessorMessage::Participation { session, .. } => { - (0, borsh::to_vec(session).unwrap()) + (0, borsh::to_vec(&session).unwrap()) } key_gen::ProcessorMessage::GeneratedKeyPair { session, .. } => { - (1, borsh::to_vec(session).unwrap()) + (1, borsh::to_vec(&session).unwrap()) } // Unique since we only blame a participant once (as this is fatal) key_gen::ProcessorMessage::Blame { session, participant } => { @@ -382,11 +387,11 @@ impl ProcessorMessage { let (sub, id) = match msg { // Unique since we'll only fatally slash a a participant once sign::ProcessorMessage::InvalidParticipant { session, participant } => { - (0, (session, u16::from(*participant)).encode()) + (0, borsh::to_vec(&(session, u16::from(*participant))).unwrap()) } // Unique since SignId - sign::ProcessorMessage::Preprocesses { id, .. } => (1, id.encode()), - sign::ProcessorMessage::Shares { id, .. } => (2, id.encode()), + sign::ProcessorMessage::Preprocesses { id, .. } => (1, borsh::to_vec(&id).unwrap()), + sign::ProcessorMessage::Shares { id, .. } => (2, borsh::to_vec(&id).unwrap()), }; let mut res = vec![PROCESSOR_UID, TYPE_SIGN_UID, sub]; @@ -396,10 +401,14 @@ impl ProcessorMessage { ProcessorMessage::Coordinator(msg) => { let (sub, id) = match msg { coordinator::ProcessorMessage::CosignedBlock { cosign } => { - (0, cosign.cosign.block_hash.encode()) + (0, borsh::to_vec(&cosign.cosign.block_hash).unwrap()) + } + coordinator::ProcessorMessage::SignedBatch { batch, .. } => { + (1, borsh::to_vec(&batch.batch.id()).unwrap()) + } + coordinator::ProcessorMessage::SignedSlashReport { session, .. } => { + (2, borsh::to_vec(&session).unwrap()) } - coordinator::ProcessorMessage::SignedBatch { batch, .. } => (1, batch.batch.id.encode()), - coordinator::ProcessorMessage::SignedSlashReport { session, .. } => (2, session.encode()), }; let mut res = vec![PROCESSOR_UID, TYPE_COORDINATOR_UID, sub]; @@ -408,7 +417,9 @@ impl ProcessorMessage { } ProcessorMessage::Substrate(msg) => { let (sub, id) = match msg { - substrate::ProcessorMessage::SubstrateBlockAck { block, .. } => (0, block.encode()), + substrate::ProcessorMessage::SubstrateBlockAck { block, .. } => { + (0, borsh::to_vec(&block).unwrap()) + } }; let mut res = vec![PROCESSOR_UID, TYPE_SUBSTRATE_UID, sub]; diff --git a/processor/monero/Cargo.toml b/processor/monero/Cargo.toml index 49b79814..e0efb026 100644 --- a/processor/monero/Cargo.toml +++ b/processor/monero/Cargo.toml @@ -21,7 +21,6 @@ rand_core = { version = "0.6", default-features = false } rand_chacha = { version = "0.3", default-features = false, features = ["std"] } zeroize = { version = "1", default-features = false, features = ["std"] } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["std"] } diff --git a/processor/monero/src/primitives/output.rs b/processor/monero/src/primitives/output.rs index f26ed01c..df8f1dd5 100644 --- a/processor/monero/src/primitives/output.rs +++ b/processor/monero/src/primitives/output.rs @@ -5,11 +5,13 @@ use dalek_ff_group::Ed25519; use monero_wallet::WalletOutput; -use scale::{Encode, Decode}; use borsh::{BorshSerialize, BorshDeserialize}; use serai_client::{ - primitives::{ExternalCoin, Amount, ExternalBalance}, + primitives::{ + coin::ExternalCoin, + balance::{Amount, ExternalBalance}, + }, networks::monero::Address, }; @@ -17,10 +19,7 @@ use primitives::{OutputType, ReceivedOutput}; use crate::{EXTERNAL_SUBADDRESS, BRANCH_SUBADDRESS, CHANGE_SUBADDRESS, FORWARDED_SUBADDRESS}; -#[rustfmt::skip] -#[derive( - Clone, Copy, PartialEq, Eq, Default, Hash, Debug, Encode, Decode, BorshSerialize, BorshDeserialize, -)] +#[derive(Clone, Copy, PartialEq, Eq, Default, Hash, Debug, BorshSerialize, BorshDeserialize)] pub(crate) struct OutputId(pub(crate) [u8; 32]); impl AsRef<[u8]> for OutputId { fn as_ref(&self) -> &[u8] { diff --git a/processor/monero/src/rpc.rs b/processor/monero/src/rpc.rs index 5ca74d02..ed5ba0f5 100644 --- a/processor/monero/src/rpc.rs +++ b/processor/monero/src/rpc.rs @@ -3,7 +3,7 @@ use core::future::Future; use monero_wallet::rpc::{RpcError, Rpc as RpcTrait}; use monero_simple_request_rpc::SimpleRequestRpc; -use serai_client::primitives::{ExternalNetworkId, ExternalCoin, Amount}; +use serai_client::primitives::{network_id::ExternalNetworkId, coin::ExternalCoin, balance::Amount}; use scanner::ScannerFeed; use signers::TransactionPublisher; diff --git a/processor/monero/src/scheduler.rs b/processor/monero/src/scheduler.rs index 45b837a0..8f007d3c 100644 --- a/processor/monero/src/scheduler.rs +++ b/processor/monero/src/scheduler.rs @@ -10,7 +10,7 @@ use dalek_ff_group::Ed25519; use monero_wallet::rpc::{FeeRate, RpcError}; use serai_client::{ - primitives::{ExternalCoin, Amount}, + primitives::{coin::ExternalCoin, balance::Amount}, networks::monero::Address, }; diff --git a/processor/primitives/Cargo.toml b/processor/primitives/Cargo.toml index f2ae7a9c..1d1e79cf 100644 --- a/processor/primitives/Cargo.toml +++ b/processor/primitives/Cargo.toml @@ -22,7 +22,6 @@ group = { version = "0.13", default-features = false } serai-primitives = { path = "../../substrate/primitives", default-features = false, features = ["std"] } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } log = { version = "0.4", default-features = false, features = ["std"] } diff --git a/processor/primitives/src/lib.rs b/processor/primitives/src/lib.rs index 371bdafb..9f53edb1 100644 --- a/processor/primitives/src/lib.rs +++ b/processor/primitives/src/lib.rs @@ -6,7 +6,6 @@ use core::{hash::Hash, fmt::Debug}; use group::GroupEncoding; -use scale::{Encode, Decode}; use borsh::{BorshSerialize, BorshDeserialize}; /// A module for task-related structs and functionality. @@ -40,8 +39,6 @@ pub trait Id: + AsRef<[u8]> + AsMut<[u8]> + Debug - + Encode - + Decode + BorshSerialize + BorshDeserialize { @@ -57,22 +54,15 @@ impl< + AsRef<[u8]> + AsMut<[u8]> + Debug - + Encode - + Decode + BorshSerialize + BorshDeserialize, > Id for I { } -/// A wrapper for a group element which implements the scale/borsh traits. +/// A wrapper for a group element which implements the `borsh` traits. #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct EncodableG(pub G); -impl Encode for EncodableG { - fn using_encoded R>(&self, f: F) -> R { - f(self.0.to_bytes().as_ref()) - } -} impl BorshSerialize for EncodableG { fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { writer.write_all(self.0.to_bytes().as_ref()) diff --git a/processor/primitives/src/output.rs b/processor/primitives/src/output.rs index e45b7344..8269e4ec 100644 --- a/processor/primitives/src/output.rs +++ b/processor/primitives/src/output.rs @@ -5,7 +5,7 @@ use group::GroupEncoding; use borsh::{BorshSerialize, BorshDeserialize}; -use serai_primitives::{ExternalAddress, ExternalBalance}; +use serai_primitives::{address::ExternalAddress, balance::ExternalBalance}; use crate::Id; diff --git a/processor/primitives/src/payment.rs b/processor/primitives/src/payment.rs index b892b2b4..f1af9d60 100644 --- a/processor/primitives/src/payment.rs +++ b/processor/primitives/src/payment.rs @@ -1,10 +1,11 @@ use std::io; -use scale::{Encode, Decode, IoReader}; use borsh::{BorshSerialize, BorshDeserialize}; -use serai_primitives::ExternalBalance; -use serai_coins_primitives::OutInstructionWithBalance; +use serai_primitives::{ + balance::ExternalBalance, + instructions::{OutInstruction, OutInstructionWithBalance}, +}; use crate::Address; @@ -18,9 +19,11 @@ pub struct Payment { impl TryFrom for Payment { type Error = (); fn try_from(out_instruction_with_balance: OutInstructionWithBalance) -> Result { - Ok(Payment { - address: out_instruction_with_balance.instruction.address.try_into().map_err(|_| ())?, - balance: out_instruction_with_balance.balance, + Ok(match out_instruction_with_balance.instruction { + OutInstruction::Transfer(address) => Payment { + address: address.try_into().map_err(|_| ())?, + balance: out_instruction_with_balance.balance, + }, }) } } @@ -43,14 +46,12 @@ impl Payment { /// Read a Payment. pub fn read(reader: &mut impl io::Read) -> io::Result { let address = A::deserialize_reader(reader)?; - let reader = &mut IoReader(reader); - let balance = ExternalBalance::decode(reader).map_err(io::Error::other)?; + let balance = ExternalBalance::deserialize_reader(reader).map_err(io::Error::other)?; Ok(Self { address, balance }) } /// Write the Payment. pub fn write(&self, writer: &mut impl io::Write) -> io::Result<()> { self.address.serialize(writer)?; - self.balance.encode_to(writer); - Ok(()) + self.balance.serialize(writer) } } diff --git a/processor/scanner/Cargo.toml b/processor/scanner/Cargo.toml index 770d6276..7a1de8b2 100644 --- a/processor/scanner/Cargo.toml +++ b/processor/scanner/Cargo.toml @@ -20,7 +20,6 @@ workspace = true [dependencies] # Encoders hex = { version = "0.4", default-features = false, features = ["std"] } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } # Cryptography diff --git a/processor/scanner/src/batch/db.rs b/processor/scanner/src/batch/db.rs index 015b661b..3e214f03 100644 --- a/processor/scanner/src/batch/db.rs +++ b/processor/scanner/src/batch/db.rs @@ -3,12 +3,10 @@ use std::io::{Read, Write}; use group::GroupEncoding; -use scale::{Encode, Decode, IoReader}; use borsh::{BorshSerialize, BorshDeserialize}; use serai_db::{Get, DbTxn, create_db}; -use serai_primitives::ExternalBalance; -use serai_validator_sets_primitives::Session; +use serai_primitives::{balance::ExternalBalance, validator_sets::Session}; use primitives::EncodableG; use crate::{ScannerFeed, KeyFor, AddressFor}; @@ -94,7 +92,7 @@ impl BatchDb { if let Some(ReturnInformation { address, balance }) = return_information { buf.write_all(&[1]).unwrap(); address.serialize(&mut buf).unwrap(); - balance.encode_to(&mut buf); + balance.serialize(&mut buf).unwrap(); } else { buf.write_all(&[0]).unwrap(); } @@ -116,7 +114,7 @@ impl BatchDb { res.push((opt[0] == 1).then(|| { let address = AddressFor::::deserialize_reader(&mut buf).unwrap(); - let balance = ExternalBalance::decode(&mut IoReader(&mut buf)).unwrap(); + let balance = ExternalBalance::deserialize_reader(&mut buf).unwrap(); ReturnInformation { address, balance } })); } diff --git a/processor/scanner/src/batch/mod.rs b/processor/scanner/src/batch/mod.rs index b583b6ed..69a90780 100644 --- a/processor/scanner/src/batch/mod.rs +++ b/processor/scanner/src/batch/mod.rs @@ -2,11 +2,9 @@ use core::{marker::PhantomData, future::Future}; use blake2::{digest::typenum::U32, Digest, Blake2b}; -use scale::Encode; use serai_db::{DbTxn, Db}; -use serai_primitives::BlockHash; -use serai_in_instructions_primitives::{MAX_BATCH_SIZE, Batch}; +use serai_primitives::{BlockHash, instructions::Batch}; use primitives::{ EncodableG, @@ -111,12 +109,7 @@ impl ContinuallyRan for BatchTask { let mut batch_id = BatchDb::::acquire_batch_id(&mut txn); // start with empty batch - let mut batches = vec![Batch { - network, - id: batch_id, - external_network_block_hash, - instructions: vec![], - }]; + let mut batches = vec![Batch::new(network, batch_id, external_network_block_hash)]; // We also track the return information for the InInstructions within a Batch in case // they error let mut return_information = vec![vec![]]; @@ -125,23 +118,19 @@ impl ContinuallyRan for BatchTask { let balance = in_instruction.balance; let batch = batches.last_mut().unwrap(); - batch.instructions.push(in_instruction); // check if batch is over-size - if batch.encode().len() > MAX_BATCH_SIZE { - // pop the last instruction so it's back in size - let in_instruction = batch.instructions.pop().unwrap(); - + if batch.push_instruction(in_instruction.clone()).is_err() { // bump the id for the new batch batch_id = BatchDb::::acquire_batch_id(&mut txn); // make a new batch with this instruction included - batches.push(Batch { - network, - id: batch_id, - external_network_block_hash, - instructions: vec![in_instruction], - }); + let mut batch = Batch::new(network, batch_id, external_network_block_hash); + batch + .push_instruction(in_instruction) + .expect("single InInstruction exceeded Batch size limit"); + batches.push(batch); + // Since we're allocating a new batch, allocate a new set of return addresses for it return_information.push(vec![]); } @@ -157,16 +146,16 @@ impl ContinuallyRan for BatchTask { // Now that we've finalized the Batches, save the information for each to the database assert_eq!(batches.len(), return_information.len()); for (batch, return_information) in batches.iter().zip(&return_information) { - assert_eq!(batch.instructions.len(), return_information.len()); + assert_eq!(batch.instructions().len(), return_information.len()); BatchDb::::save_batch_info( &mut txn, - batch.id, + batch.id(), block_number, session_to_sign_batch, external_key_for_session_to_sign_batch, - Blake2b::::digest(batch.instructions.encode()).into(), + Blake2b::::digest(borsh::to_vec(&batch.instructions()).unwrap()).into(), ); - BatchDb::::save_return_information(&mut txn, batch.id, return_information); + BatchDb::::save_return_information(&mut txn, batch.id(), return_information); } for batch in batches { diff --git a/processor/scanner/src/db.rs b/processor/scanner/src/db.rs index e7fd464b..1a06cc8e 100644 --- a/processor/scanner/src/db.rs +++ b/processor/scanner/src/db.rs @@ -3,13 +3,13 @@ use std::io::{self, Read, Write}; use group::GroupEncoding; -use scale::{Encode, Decode, IoReader}; use borsh::{BorshSerialize, BorshDeserialize}; use serai_db::{Get, DbTxn, create_db, db_channel}; -use serai_coins_primitives::OutInstructionWithBalance; -use serai_validator_sets_primitives::Session; -use serai_in_instructions_primitives::{InInstructionWithBalance, Batch}; +use serai_primitives::{ + validator_sets::Session, + instructions::{InInstructionWithBalance, Batch, OutInstructionWithBalance}, +}; use primitives::{EncodableG, ReceivedOutput}; @@ -56,7 +56,7 @@ impl OutputWithInInstruction { (opt[0] == 1).then(|| AddressFor::::deserialize_reader(reader)).transpose()? }; let in_instruction = - InInstructionWithBalance::decode(&mut IoReader(reader)).map_err(io::Error::other)?; + InInstructionWithBalance::deserialize_reader(reader).map_err(io::Error::other)?; Ok(Self { output, return_address, in_instruction }) } pub(crate) fn write(&self, writer: &mut impl io::Write) -> io::Result<()> { @@ -67,7 +67,7 @@ impl OutputWithInInstruction { } else { writer.write_all(&[0])?; } - self.in_instruction.encode_to(writer); + self.in_instruction.serialize(writer)?; Ok(()) } } @@ -76,10 +76,10 @@ create_db!( ScannerGlobal { StartBlock: () -> u64, - QueuedKey: (key: K) -> (), + QueuedKey: (key: K) -> (), ActiveKeys: () -> Vec>, - RetireAt: (key: K) -> u64, + RetireAt: (key: K) -> u64, // Highest acknowledged block HighestAcknowledgedBlock: () -> u64, @@ -294,7 +294,7 @@ impl ScannerGlobalDb { assert!((opt[0] == 0) || (opt[0] == 1)); let address = (opt[0] == 1).then(|| AddressFor::::deserialize_reader(&mut buf).unwrap()); - Some((address, InInstructionWithBalance::decode(&mut IoReader(buf)).unwrap())) + Some((address, InInstructionWithBalance::deserialize_reader(&mut buf).unwrap())) } } @@ -357,7 +357,7 @@ impl ScanToEventualityDb { } else { buf.write_all(&[0]).unwrap(); } - forward.in_instruction.encode_to(&mut buf); + forward.in_instruction.serialize(&mut buf).unwrap(); SerializedForwardedOutput::set(txn, forward.output.id().as_ref(), &buf); } @@ -454,7 +454,7 @@ impl Returnable { (opt[0] == 1).then(|| AddressFor::::deserialize_reader(reader)).transpose()?; let in_instruction = - InInstructionWithBalance::decode(&mut IoReader(reader)).map_err(io::Error::other)?; + InInstructionWithBalance::deserialize_reader(reader).map_err(io::Error::other)?; Ok(Returnable { return_address, in_instruction }) } fn write(&self, writer: &mut impl io::Write) -> io::Result<()> { @@ -464,7 +464,7 @@ impl Returnable { } else { writer.write_all(&[0])?; } - self.in_instruction.encode_to(writer); + self.in_instruction.serialize(writer)?; Ok(()) } } @@ -494,7 +494,7 @@ impl ScanToBatchDb { block_number: u64, data: &InInstructionData, ) { - let mut buf = data.session_to_sign_batch.encode(); + let mut buf = borsh::to_vec(&data.session_to_sign_batch).unwrap(); buf.extend(data.external_key_for_session_to_sign_batch.to_bytes().as_ref()); for returnable_in_instruction in &data.returnable_in_instructions { returnable_in_instruction.write(&mut buf).unwrap(); @@ -517,7 +517,7 @@ impl ScanToBatchDb { ); let mut buf = data.returnable_in_instructions.as_slice(); - let session_to_sign_batch = Session::decode(&mut buf).unwrap(); + let session_to_sign_batch = Session::deserialize_reader(&mut buf).unwrap(); let external_key_for_session_to_sign_batch = { let mut external_key_for_session_to_sign_batch = as GroupEncoding>::Repr::default(); @@ -595,7 +595,7 @@ impl SubstrateToEventualityDb { } mod _public_db { - use serai_in_instructions_primitives::Batch; + use serai_primitives::instructions::Batch; use serai_db::{Get, DbTxn, create_db, db_channel}; diff --git a/processor/scanner/src/eventuality/db.rs b/processor/scanner/src/eventuality/db.rs index 3e5088d1..d684274e 100644 --- a/processor/scanner/src/eventuality/db.rs +++ b/processor/scanner/src/eventuality/db.rs @@ -1,6 +1,7 @@ use core::marker::PhantomData; -use scale::Encode; +use borsh::BorshSerialize; + use serai_db::{Get, DbTxn, create_db}; use primitives::{EncodableG, ReceivedOutput, Eventuality, EventualityTracker}; @@ -14,7 +15,7 @@ create_db!( // The latest block this task has handled which was notable LatestHandledNotableBlock: () -> u64, - SerializedEventualities: (key: K) -> Vec, + SerializedEventualities: (key: K) -> Vec, AccumulatedOutput: (id: &[u8]) -> (), } diff --git a/processor/scanner/src/lib.rs b/processor/scanner/src/lib.rs index d3e24183..783d1e4a 100644 --- a/processor/scanner/src/lib.rs +++ b/processor/scanner/src/lib.rs @@ -10,8 +10,10 @@ use group::GroupEncoding; use borsh::{BorshSerialize, BorshDeserialize}; use serai_db::{Get, DbTxn, Db}; -use serai_primitives::{ExternalNetworkId, ExternalCoin, Amount}; -use serai_coins_primitives::OutInstructionWithBalance; +use serai_primitives::{ + network_id::ExternalNetworkId, coin::ExternalCoin, balance::Amount, + instructions::OutInstructionWithBalance, +}; use messages::substrate::ExecutedBatch; use primitives::{task::*, Address, ReceivedOutput, Block, Payment}; diff --git a/processor/scanner/src/report/db.rs b/processor/scanner/src/report/db.rs index a97a6b39..c86aa1c0 100644 --- a/processor/scanner/src/report/db.rs +++ b/processor/scanner/src/report/db.rs @@ -1,6 +1,6 @@ use serai_db::{Get, DbTxn, create_db}; -use serai_validator_sets_primitives::Session; +use serai_primitives::validator_sets::Session; create_db!( ScannerBatch { diff --git a/processor/scanner/src/report/mod.rs b/processor/scanner/src/report/mod.rs index 9055fcd0..0cb1ae4c 100644 --- a/processor/scanner/src/report/mod.rs +++ b/processor/scanner/src/report/mod.rs @@ -2,7 +2,7 @@ use core::{marker::PhantomData, future::Future}; use serai_db::{DbTxn, Db}; -use serai_validator_sets_primitives::Session; +use serai_primitives::validator_sets::Session; use primitives::task::{DoesNotError, ContinuallyRan}; use crate::{ @@ -70,12 +70,12 @@ impl ContinuallyRan for ReportTask { // Because this boolean was expanded, we lose short-circuiting. That's fine let handover_batch = last_session != session_to_sign_batch; let batch_after_handover_batch = - (last_session == session_to_sign_batch) && ((first_batch + 1) == batch.id); + (last_session == session_to_sign_batch) && ((first_batch + 1) == batch.id()); if handover_batch || batch_after_handover_batch { let verified_prior_batch = substrate::last_acknowledged_batch::(&txn) - // Since `batch.id = 0` in the Session(0)-never-published-a-Batch case, we don't - // check `last_acknowledged_batch >= (batch.id - 1)` but instead this - .map(|last_acknowledged_batch| (last_acknowledged_batch + 1) >= batch.id) + // Since `batch.id() = 0` in the Session(0)-never-published-a-Batch case, we don't + // check `last_acknowledged_batch >= (batch.id() - 1)` but instead this + .map(|last_acknowledged_batch| (last_acknowledged_batch + 1) >= batch.id()) // We've never verified any Batches .unwrap_or(false); if !verified_prior_batch { @@ -90,7 +90,7 @@ impl ContinuallyRan for ReportTask { BatchDb::set_last_session_to_sign_batch_and_first_batch( &mut txn, session_to_sign_batch, - batch.id, + batch.id(), ); } } diff --git a/processor/scanner/src/scan/mod.rs b/processor/scanner/src/scan/mod.rs index 24426c62..389153ec 100644 --- a/processor/scanner/src/scan/mod.rs +++ b/processor/scanner/src/scan/mod.rs @@ -1,12 +1,12 @@ use core::future::Future; use std::collections::HashMap; -use scale::Decode; +use borsh::BorshDeserialize; + use serai_db::{Get, DbTxn, Db}; -use serai_in_instructions_primitives::{ - Shorthand, RefundableInInstruction, InInstruction, InInstructionWithBalance, -}; +#[rustfmt::skip] +use serai_primitives::instructions::{RefundableInInstruction, InInstruction, InInstructionWithBalance}; use primitives::{task::ContinuallyRan, OutputType, ReceivedOutput, Block}; @@ -55,26 +55,22 @@ fn in_instruction_from_output( let presumed_origin = output.presumed_origin(); let mut data = output.data(); - let shorthand = match Shorthand::decode(&mut data) { - Ok(shorthand) => shorthand, - Err(e) => { - log::info!("data in output {} wasn't valid shorthand: {e:?}", hex::encode(output.id())); - return (presumed_origin, None); - } - }; - let instruction = match RefundableInInstruction::try_from(shorthand) { + let instruction = match RefundableInInstruction::deserialize_reader(&mut data) { Ok(instruction) => instruction, Err(e) => { log::info!( - "shorthand in output {} wasn't convertible to a RefundableInInstruction: {e:?}", - hex::encode(output.id()) + "data in output {} wasn't a valid `RefundableInInstruction`: {e:?}", + hex::encode(output.id()), ); return (presumed_origin, None); } }; ( - instruction.origin.and_then(|addr| AddressFor::::try_from(addr).ok()).or(presumed_origin), + instruction + .return_address + .and_then(|addr| AddressFor::::try_from(addr).ok()) + .or(presumed_origin), Some(instruction.instruction), ) } diff --git a/processor/scanner/src/substrate/db.rs b/processor/scanner/src/substrate/db.rs index 1e0181b8..f72bfdfb 100644 --- a/processor/scanner/src/substrate/db.rs +++ b/processor/scanner/src/substrate/db.rs @@ -5,7 +5,7 @@ use group::GroupEncoding; use borsh::{BorshSerialize, BorshDeserialize}; use serai_db::{Get, DbTxn, create_db, db_channel}; -use serai_coins_primitives::OutInstructionWithBalance; +use serai_primitives::instructions::OutInstructionWithBalance; use messages::substrate::ExecutedBatch; diff --git a/processor/scanner/src/substrate/mod.rs b/processor/scanner/src/substrate/mod.rs index 4963f66b..5ce44541 100644 --- a/processor/scanner/src/substrate/mod.rs +++ b/processor/scanner/src/substrate/mod.rs @@ -2,7 +2,7 @@ use core::{marker::PhantomData, future::Future}; use serai_db::{Get, DbTxn, Db}; -use serai_coins_primitives::{OutInstruction, OutInstructionWithBalance}; +use serai_primitives::instructions::{OutInstruction, OutInstructionWithBalance}; use messages::substrate::ExecutedBatch; use primitives::task::{DoesNotError, ContinuallyRan}; @@ -150,7 +150,7 @@ impl ContinuallyRan for SubstrateTask { if let Some(batch::ReturnInformation { address, balance }) = return_information { burns.push(OutInstructionWithBalance { - instruction: OutInstruction { address: address.into() }, + instruction: OutInstruction::Transfer(address.into()), balance, }); } diff --git a/processor/scheduler/primitives/Cargo.toml b/processor/scheduler/primitives/Cargo.toml index 64141319..603f8951 100644 --- a/processor/scheduler/primitives/Cargo.toml +++ b/processor/scheduler/primitives/Cargo.toml @@ -15,7 +15,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [package.metadata.cargo-machete] -ignored = ["scale", "borsh"] +ignored = ["borsh"] [lints] workspace = true @@ -24,7 +24,6 @@ workspace = true ciphersuite = { path = "../../../crypto/ciphersuite", default-features = false, features = ["std"] } frost = { package = "modular-frost", path = "../../../crypto/frost", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } serai-db = { path = "../../../common/db" } diff --git a/processor/scheduler/smart-contract/Cargo.toml b/processor/scheduler/smart-contract/Cargo.toml index e311f783..e147321c 100644 --- a/processor/scheduler/smart-contract/Cargo.toml +++ b/processor/scheduler/smart-contract/Cargo.toml @@ -15,7 +15,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [package.metadata.cargo-machete] -ignored = ["scale", "borsh"] +ignored = ["borsh"] [lints] workspace = true @@ -23,7 +23,6 @@ workspace = true [dependencies] group = { version = "0.13", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } serai-db = { path = "../../../common/db" } diff --git a/processor/scheduler/utxo/primitives/src/lib.rs b/processor/scheduler/utxo/primitives/src/lib.rs index a793c906..69575ada 100644 --- a/processor/scheduler/utxo/primitives/src/lib.rs +++ b/processor/scheduler/utxo/primitives/src/lib.rs @@ -4,7 +4,7 @@ use core::{fmt::Debug, future::Future}; -use serai_primitives::Amount; +use serai_primitives::balance::Amount; use primitives::{ReceivedOutput, Payment}; use scanner::{ScannerFeed, KeyFor, AddressFor, OutputFor, EventualityFor, BlockFor}; diff --git a/processor/scheduler/utxo/primitives/src/tree.rs b/processor/scheduler/utxo/primitives/src/tree.rs index 565706a3..1f4d8401 100644 --- a/processor/scheduler/utxo/primitives/src/tree.rs +++ b/processor/scheduler/utxo/primitives/src/tree.rs @@ -1,6 +1,9 @@ use borsh::{BorshSerialize, BorshDeserialize}; -use serai_primitives::{ExternalCoin, Amount, ExternalBalance}; +use serai_primitives::{ + coin::ExternalCoin, + balance::{Amount, ExternalBalance}, +}; use primitives::{Address, Payment}; use scanner::ScannerFeed; diff --git a/processor/scheduler/utxo/standard/Cargo.toml b/processor/scheduler/utxo/standard/Cargo.toml index 79c07b89..d0a75aa9 100644 --- a/processor/scheduler/utxo/standard/Cargo.toml +++ b/processor/scheduler/utxo/standard/Cargo.toml @@ -15,7 +15,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [package.metadata.cargo-machete] -ignored = ["scale", "borsh"] +ignored = ["borsh"] [lints] workspace = true @@ -23,7 +23,6 @@ workspace = true [dependencies] group = { version = "0.13", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } serai-primitives = { path = "../../../../substrate/primitives", default-features = false, features = ["std"] } diff --git a/processor/scheduler/utxo/standard/src/db.rs b/processor/scheduler/utxo/standard/src/db.rs index 128c5df6..07b63d3c 100644 --- a/processor/scheduler/utxo/standard/src/db.rs +++ b/processor/scheduler/utxo/standard/src/db.rs @@ -2,7 +2,10 @@ use core::marker::PhantomData; use group::GroupEncoding; -use serai_primitives::{ExternalCoin, Amount, ExternalBalance}; +use serai_primitives::{ + coin::ExternalCoin, + balance::{Amount, ExternalBalance}, +}; use borsh::BorshDeserialize; use serai_db::{Get, DbTxn, create_db, db_channel}; diff --git a/processor/scheduler/utxo/standard/src/lib.rs b/processor/scheduler/utxo/standard/src/lib.rs index cc2e2d35..52a9b999 100644 --- a/processor/scheduler/utxo/standard/src/lib.rs +++ b/processor/scheduler/utxo/standard/src/lib.rs @@ -7,7 +7,10 @@ use std::collections::HashMap; use group::GroupEncoding; -use serai_primitives::{ExternalCoin, Amount, ExternalBalance}; +use serai_primitives::{ + coin::ExternalCoin, + balance::{Amount, ExternalBalance}, +}; use serai_db::DbTxn; diff --git a/processor/scheduler/utxo/transaction-chaining/Cargo.toml b/processor/scheduler/utxo/transaction-chaining/Cargo.toml index d6a54e86..a94eb9a0 100644 --- a/processor/scheduler/utxo/transaction-chaining/Cargo.toml +++ b/processor/scheduler/utxo/transaction-chaining/Cargo.toml @@ -15,7 +15,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [package.metadata.cargo-machete] -ignored = ["scale", "borsh"] +ignored = ["borsh"] [lints] workspace = true @@ -23,7 +23,6 @@ workspace = true [dependencies] group = { version = "0.13", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } serai-primitives = { path = "../../../../substrate/primitives", default-features = false, features = ["std"] } diff --git a/processor/scheduler/utxo/transaction-chaining/src/db.rs b/processor/scheduler/utxo/transaction-chaining/src/db.rs index 68558e6f..2b351ae1 100644 --- a/processor/scheduler/utxo/transaction-chaining/src/db.rs +++ b/processor/scheduler/utxo/transaction-chaining/src/db.rs @@ -2,7 +2,7 @@ use core::marker::PhantomData; use group::GroupEncoding; -use serai_primitives::{ExternalCoin, Amount}; +use serai_primitives::{coin::ExternalCoin, balance::Amount}; use serai_db::{Get, DbTxn, create_db}; diff --git a/processor/scheduler/utxo/transaction-chaining/src/lib.rs b/processor/scheduler/utxo/transaction-chaining/src/lib.rs index 5f7275ce..900ef9d3 100644 --- a/processor/scheduler/utxo/transaction-chaining/src/lib.rs +++ b/processor/scheduler/utxo/transaction-chaining/src/lib.rs @@ -7,7 +7,7 @@ use std::collections::HashMap; use group::GroupEncoding; -use serai_primitives::{ExternalCoin, Amount}; +use serai_primitives::{coin::ExternalCoin, balance::Amount}; use serai_db::DbTxn; diff --git a/processor/signers/Cargo.toml b/processor/signers/Cargo.toml index 0529439f..806e3805 100644 --- a/processor/signers/Cargo.toml +++ b/processor/signers/Cargo.toml @@ -30,7 +30,6 @@ dalek-ff-group = { path = "../../crypto/dalek-ff-group", default-features = fals frost = { package = "modular-frost", path = "../../crypto/frost", default-features = false } frost-schnorrkel = { path = "../../crypto/schnorrkel", default-features = false } -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std"] } borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] } serai-primitives = { path = "../../substrate/primitives", default-features = false, features = ["std"] } @@ -39,7 +38,7 @@ serai-db = { path = "../../common/db" } log = { version = "0.4", default-features = false, features = ["std"] } tokio = { version = "1", default-features = false, features = ["rt-multi-thread", "sync", "time", "macros"] } -serai-cosign = { path = "../../coordinator/cosign" } +serai-cosign = { package = "serai-cosign-types", path = "../../coordinator/cosign/types" } messages = { package = "serai-processor-messages", path = "../messages" } primitives = { package = "serai-processor-primitives", path = "../primitives" } scanner = { package = "serai-processor-scanner", path = "../scanner" } diff --git a/processor/signers/src/batch/db.rs b/processor/signers/src/batch/db.rs index 8d9bc605..7ee85012 100644 --- a/processor/signers/src/batch/db.rs +++ b/processor/signers/src/batch/db.rs @@ -1,5 +1,7 @@ -use serai_validator_sets_primitives::Session; -use serai_in_instructions_primitives::{Batch, SignedBatch}; +use serai_primitives::{ + validator_sets::Session, + instructions::{Batch, SignedBatch}, +}; use serai_db::{Get, DbTxn, create_db}; diff --git a/processor/signers/src/batch/mod.rs b/processor/signers/src/batch/mod.rs index 695ce4e0..34728cfc 100644 --- a/processor/signers/src/batch/mod.rs +++ b/processor/signers/src/batch/mod.rs @@ -6,10 +6,7 @@ use ciphersuite::group::GroupEncoding; use dalek_ff_group::Ristretto; use frost::dkg::ThresholdKeys; -use scale::Encode; - -use serai_validator_sets_primitives::Session; -use serai_in_instructions_primitives::{SignedBatch, batch_message}; +use serai_primitives::{validator_sets::Session, instructions::SignedBatch}; use serai_db::{Get, DbTxn, Db}; @@ -74,7 +71,7 @@ impl BatchSignerTask { machines.push(WrappedSchnorrkelMachine::new( keys.clone(), b"substrate", - batch_message(&batch), + batch.publish_batch_message(), )); } attempt_manager.register(VariantSignId::Batch(id), machines); @@ -100,14 +97,14 @@ impl ContinuallyRan for BatchSignerTask { iterated = true; // Save this to the database as a transaction to sign - let batch_hash = <[u8; 32]>::from(Blake2b::::digest(batch.encode())); + let batch_hash = <[u8; 32]>::from(Blake2b::::digest(borsh::to_vec(&batch).unwrap())); self.active_signing_protocols.insert(batch_hash); ActiveSigningProtocols::set( &mut txn, self.session, &self.active_signing_protocols.iter().copied().collect(), ); - BatchHash::set(&mut txn, batch.id, &batch_hash); + BatchHash::set(&mut txn, batch.id(), &batch_hash); Batches::set(&mut txn, batch_hash, &batch); let mut machines = Vec::with_capacity(self.keys.len()); @@ -116,7 +113,7 @@ impl ContinuallyRan for BatchSignerTask { machines.push(WrappedSchnorrkelMachine::new( keys.clone(), b"substrate", - batch_message(&batch), + batch.publish_batch_message(), )); } for msg in self.attempt_manager.register(VariantSignId::Batch(batch_hash), machines) { @@ -160,8 +157,8 @@ impl ContinuallyRan for BatchSignerTask { // Update the last acknowledged Batch { let last_acknowledged = LastAcknowledgedBatch::get(&txn); - if Some(batch.id) > last_acknowledged { - LastAcknowledgedBatch::set(&mut txn, &batch.id); + if Some(batch.id()) > last_acknowledged { + LastAcknowledgedBatch::set(&mut txn, &batch.id()); } } @@ -174,7 +171,7 @@ impl ContinuallyRan for BatchSignerTask { ); // Clean up SignedBatches - SignedBatches::del(&mut txn, batch.id); + SignedBatches::del(&mut txn, batch.id()); // We retire with a txn so we either successfully flag this Batch as acknowledged, and // won't re-register it (making this retire safe), or we don't flag it, meaning we will @@ -203,7 +200,7 @@ impl ContinuallyRan for BatchSignerTask { let batch = Batches::get(&txn, id).expect("signed a Batch we didn't save to the database"); let signed_batch = SignedBatch { batch, signature: signature.into() }; - SignedBatches::set(&mut txn, signed_batch.batch.id, &signed_batch); + SignedBatches::set(&mut txn, signed_batch.batch.id(), &signed_batch); } } diff --git a/processor/signers/src/coordinator/mod.rs b/processor/signers/src/coordinator/mod.rs index 0fd10822..e0b59854 100644 --- a/processor/signers/src/coordinator/mod.rs +++ b/processor/signers/src/coordinator/mod.rs @@ -1,6 +1,6 @@ use core::future::Future; -use serai_primitives::Signature; +use serai_primitives::crypto::Signature; use serai_db::{DbTxn, Db}; @@ -140,7 +140,7 @@ impl ContinuallyRan for CoordinatorTask { let mut next_batch = last_batch.map(|id| id + 1).unwrap_or(0); while let Some(batch) = crate::batch::signed_batch(&txn, next_batch) { iterated = true; - db::LastPublishedBatch::set(&mut txn, &batch.batch.id); + db::LastPublishedBatch::set(&mut txn, &batch.batch.id()); self .coordinator .publish_signed_batch(batch) diff --git a/processor/signers/src/cosign/db.rs b/processor/signers/src/cosign/db.rs index 01a42446..b25bc34a 100644 --- a/processor/signers/src/cosign/db.rs +++ b/processor/signers/src/cosign/db.rs @@ -1,4 +1,4 @@ -use serai_validator_sets_primitives::Session; +use serai_primitives::validator_sets::Session; use serai_db::{Get, DbTxn, create_db}; diff --git a/processor/signers/src/cosign/mod.rs b/processor/signers/src/cosign/mod.rs index 2dc16c31..4c215e61 100644 --- a/processor/signers/src/cosign/mod.rs +++ b/processor/signers/src/cosign/mod.rs @@ -3,9 +3,7 @@ use core::future::Future; use dalek_ff_group::Ristretto; use frost::dkg::ThresholdKeys; -use scale::Encode; -use serai_primitives::Signature; -use serai_validator_sets_primitives::Session; +use serai_primitives::{crypto::Signature, validator_sets::Session}; use serai_db::{DbTxn, Db}; @@ -127,7 +125,7 @@ impl ContinuallyRan for CosignerTask { LatestCosigned::set(&mut txn, self.session, &cosign.block_number); let cosign = SignedCosign { cosign, - signature: Signature::from(signature).encode().try_into().unwrap(), + signature: borsh::to_vec(&Signature::from(signature)).unwrap().try_into().unwrap(), }; // Send the cosign Cosign::send(&mut txn, self.session, &cosign); diff --git a/processor/signers/src/db.rs b/processor/signers/src/db.rs index 23862236..ff8b1460 100644 --- a/processor/signers/src/db.rs +++ b/processor/signers/src/db.rs @@ -1,4 +1,4 @@ -use serai_validator_sets_primitives::{Session, SlashReport as SlashReportStruct}; +use serai_primitives::validator_sets::{Session, SlashReport as SlashReportStruct}; use serai_db::{Get, DbTxn, create_db, db_channel}; diff --git a/processor/signers/src/lib.rs b/processor/signers/src/lib.rs index 79b152ab..1e977fbf 100644 --- a/processor/signers/src/lib.rs +++ b/processor/signers/src/lib.rs @@ -11,9 +11,11 @@ use ciphersuite::{group::GroupEncoding, Ciphersuite}; use dalek_ff_group::Ristretto; use frost::dkg::ThresholdKeys; -use serai_primitives::Signature; -use serai_validator_sets_primitives::{Session, SlashReport}; -use serai_in_instructions_primitives::SignedBatch; +use serai_primitives::{ + crypto::Signature, + validator_sets::{Session, SlashReport}, + instructions::SignedBatch, +}; use serai_db::{DbTxn, Db}; diff --git a/processor/signers/src/slash_report.rs b/processor/signers/src/slash_report.rs index 25448401..3804929d 100644 --- a/processor/signers/src/slash_report.rs +++ b/processor/signers/src/slash_report.rs @@ -3,8 +3,7 @@ use core::{marker::PhantomData, future::Future}; use dalek_ff_group::Ristretto; use frost::dkg::ThresholdKeys; -use serai_primitives::Signature; -use serai_validator_sets_primitives::Session; +use serai_primitives::{crypto::Signature, validator_sets::Session}; use serai_db::{DbTxn, Db}; diff --git a/processor/signers/src/transaction/db.rs b/processor/signers/src/transaction/db.rs index a91881e7..92c03b12 100644 --- a/processor/signers/src/transaction/db.rs +++ b/processor/signers/src/transaction/db.rs @@ -1,4 +1,4 @@ -use serai_validator_sets_primitives::Session; +use serai_primitives::validator_sets::Session; use serai_db::{Get, DbTxn, create_db}; diff --git a/processor/signers/src/transaction/mod.rs b/processor/signers/src/transaction/mod.rs index b62e7303..9972bc18 100644 --- a/processor/signers/src/transaction/mod.rs +++ b/processor/signers/src/transaction/mod.rs @@ -6,7 +6,7 @@ use std::{ use frost::dkg::ThresholdKeys; -use serai_validator_sets_primitives::Session; +use serai_primitives::validator_sets::Session; use serai_db::{DbTxn, Db}; diff --git a/substrate/client/Cargo.toml b/substrate/client/Cargo.toml index ffc226c6..09252326 100644 --- a/substrate/client/Cargo.toml +++ b/substrate/client/Cargo.toml @@ -23,7 +23,7 @@ thiserror = { version = "2", default-features = false, optional = true } bitvec = { version = "1", default-features = false, features = ["alloc", "serde"] } hex = "0.4" -scale = { package = "parity-scale-codec", version = "3" } +scale = { package = "parity-scale-codec", version = "3", optional = true } borsh = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"], optional = true } serde_json = { version = "1", optional = true } @@ -64,7 +64,7 @@ dockertest = "0.5" serai-docker-tests = { path = "../../tests/docker" } [features] -serai = ["thiserror/std", "serde", "serde_json", "multiaddr", "sp-core", "sp-runtime", "frame-system", "simple-request"] +serai = ["thiserror/std", "scale", "serde", "serde_json", "multiaddr", "sp-core", "sp-runtime", "frame-system", "simple-request"] networks = [] bitcoin = ["networks", "dep:bitcoin"] @@ -73,4 +73,4 @@ monero = ["networks", "dalek-ff-group", "ciphersuite", "monero-address"] # Assumes the default usage is to use Serai as a DEX, which doesn't actually # require connecting to a Serai node -default = ["bitcoin", "monero"] +default = ["bitcoin", "ethereum", "monero"] diff --git a/substrate/client/src/lib.rs b/substrate/client/src/lib.rs index a780d55c..fc0f902e 100644 --- a/substrate/client/src/lib.rs +++ b/substrate/client/src/lib.rs @@ -8,20 +8,6 @@ pub use serai::*; #[cfg(not(feature = "serai"))] pub use serai_abi::primitives; -#[cfg(not(feature = "serai"))] -mod other_primitives { - pub mod coins { - pub use serai_abi::coins::primitives; - } - pub mod validator_sets { - pub use serai_abi::validator_sets::primitives; - } - pub mod in_instructions { - pub use serai_abi::in_instructions::primitives; - } -} -#[cfg(not(feature = "serai"))] -pub use other_primitives::*; #[cfg(test)] mod tests; diff --git a/substrate/client/src/networks/bitcoin.rs b/substrate/client/src/networks/bitcoin.rs index 28f66053..9c42756d 100644 --- a/substrate/client/src/networks/bitcoin.rs +++ b/substrate/client/src/networks/bitcoin.rs @@ -1,6 +1,5 @@ use core::{str::FromStr, fmt}; -use scale::{Encode, Decode}; use borsh::{BorshSerialize, BorshDeserialize}; use bitcoin::{ @@ -11,10 +10,10 @@ use bitcoin::{ address::{AddressType, NetworkChecked, Address as BAddress}, }; -use crate::primitives::ExternalAddress; +use crate::primitives::address::ExternalAddress; // SCALE-encodable representation of Bitcoin addresses, used internally. -#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode, BorshSerialize, BorshDeserialize)] +#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] enum EncodedAddress { P2PKH([u8; 20]), P2SH([u8; 20]), @@ -124,7 +123,7 @@ impl TryFrom for Address { fn try_from(data: ExternalAddress) -> Result { // Decode as an EncodedAddress, then map to a ScriptBuf let mut data = data.as_ref(); - let encoded = EncodedAddress::decode(&mut data).map_err(|_| ())?; + let encoded = EncodedAddress::deserialize_reader(&mut data).map_err(|_| ())?; if !data.is_empty() { Err(())? } @@ -141,8 +140,8 @@ impl From
for EncodedAddress { impl From
for ExternalAddress { fn from(addr: Address) -> ExternalAddress { - // Safe since all variants are fixed-length and fit into MAX_ADDRESS_LEN - ExternalAddress::new(EncodedAddress::from(addr).encode()).unwrap() + // Safe since all variants are fixed-length and fit into `MAX_ADDRESS_LEN` + ExternalAddress::try_from(borsh::to_vec(&EncodedAddress::from(addr)).unwrap()).unwrap() } } diff --git a/substrate/client/src/networks/ethereum.rs b/substrate/client/src/networks/ethereum.rs index 7e94dfb8..b55ce7f9 100644 --- a/substrate/client/src/networks/ethereum.rs +++ b/substrate/client/src/networks/ethereum.rs @@ -3,7 +3,7 @@ use std::io::Read; use borsh::{BorshSerialize, BorshDeserialize}; -use crate::primitives::{MAX_ADDRESS_LEN, ExternalAddress}; +use crate::primitives::address::ExternalAddress; /// THe maximum amount of gas an address is allowed to specify as its gas limit. /// @@ -33,7 +33,8 @@ impl ContractDeployment { } // The max address length, minus the type byte, minus the size of the gas - const MAX_CODE_LEN: usize = (MAX_ADDRESS_LEN as usize) - (1 + core::mem::size_of::()); + const MAX_CODE_LEN: usize = + (ExternalAddress::MAX_LEN as usize) - (1 + core::mem::size_of::()); if code.len() > MAX_CODE_LEN { None?; } @@ -111,7 +112,7 @@ impl From
for ExternalAddress { } } // We only construct addresses whose code is small enough this can safely be constructed - ExternalAddress::new(res).unwrap() + ExternalAddress::try_from(res).unwrap() } } diff --git a/substrate/client/src/networks/monero.rs b/substrate/client/src/networks/monero.rs index 5e8f6ddc..153a5be5 100644 --- a/substrate/client/src/networks/monero.rs +++ b/substrate/client/src/networks/monero.rs @@ -5,7 +5,7 @@ use ciphersuite::Ciphersuite; use monero_address::{Network, AddressType as MoneroAddressType, MoneroAddress}; -use crate::primitives::ExternalAddress; +use crate::primitives::address::ExternalAddress; #[derive(Clone, Copy, PartialEq, Eq, Debug)] enum AddressType { @@ -123,7 +123,7 @@ impl TryFrom for Address { impl From
for ExternalAddress { fn from(address: Address) -> ExternalAddress { // This is 65 bytes which is less than MAX_ADDRESS_LEN - ExternalAddress::new(borsh::to_vec(&address).unwrap()).unwrap() + ExternalAddress::try_from(borsh::to_vec(&address).unwrap()).unwrap() } } diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index 39ae17a0..af708cc5 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -25,16 +25,18 @@ scale-info = { version = "2", default-features = false, features = ["derive"], o sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "2bfdaed4b3614de2fe7d10e4ece3e6a912833e90", default-features = false } ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["alloc"] } -dalek-ff-group = { path = "../../crypto/dalek-ff-group", default-features = false } +dalek-ff-group = { path = "../../crypto/dalek-ff-group", default-features = false, features = ["alloc"] } dkg = { package = "dkg-musig", path = "../../crypto/dkg/musig", default-features = false } +schnorrkel = { version = "0.11", default-features = false } + bech32 = { version = "0.11", default-features = false } [dev-dependencies] rand_core = { version = "0.6", default-features = false, features = ["std"] } [features] -std = ["zeroize/std", "borsh/std", "bitvec/std", "scale/std", "scale-info/std", "sp-core/std", "ciphersuite/std", "dalek-ff-group/std", "dkg/std", "bech32/std"] +std = ["zeroize/std", "borsh/std", "bitvec/std", "scale?/std", "scale-info?/std", "sp-core/std", "ciphersuite/std", "dalek-ff-group/std", "dkg/std", "schnorrkel/std", "bech32/std"] serde = [] non_canonical_scale_derivations = ["scale", "scale-info"] default = ["std"] diff --git a/substrate/primitives/src/address.rs b/substrate/primitives/src/address.rs index ab98b102..a5ddf304 100644 --- a/substrate/primitives/src/address.rs +++ b/substrate/primitives/src/address.rs @@ -1,3 +1,4 @@ +use core::convert::AsRef; use alloc::vec::Vec; use zeroize::Zeroize; @@ -150,13 +151,18 @@ impl TryFrom> for ExternalAddress { vec.try_into().map(ExternalAddress).map_err(|_| FromVecError::TooLong) } } - impl From for Vec { fn from(ext: ExternalAddress) -> Vec { ext.0.into_inner() } } +impl AsRef<[u8]> for ExternalAddress { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } +} + impl zeroize::Zeroize for ExternalAddress { fn zeroize(&mut self) { self.0.as_mut().zeroize(); diff --git a/substrate/primitives/src/crypto.rs b/substrate/primitives/src/crypto.rs index 134e285a..92bd2bfe 100644 --- a/substrate/primitives/src/crypto.rs +++ b/substrate/primitives/src/crypto.rs @@ -40,6 +40,11 @@ impl From for sp_core::sr25519::Public { ) )] pub struct Signature(pub [u8; 64]); +impl From for Signature { + fn from(signature: schnorrkel::Signature) -> Self { + Self(signature.to_bytes()) + } +} impl From for Signature { fn from(signature: sp_core::sr25519::Signature) -> Self { Self(signature.0) @@ -71,6 +76,12 @@ pub struct ExternalKey( pub BoundedVec>, ); +impl AsRef<[u8]> for ExternalKey { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } +} + impl Zeroize for ExternalKey { fn zeroize(&mut self) { self.0.as_mut().zeroize(); diff --git a/substrate/primitives/src/instructions/in/batch.rs b/substrate/primitives/src/instructions/in/batch.rs index 893d1e2d..8d39ba25 100644 --- a/substrate/primitives/src/instructions/in/batch.rs +++ b/substrate/primitives/src/instructions/in/batch.rs @@ -93,6 +93,7 @@ impl BorshDeserialize for Batch { } /// An error incurred while pushing an instruction onto a `Batch`. +#[derive(Debug)] pub enum PushInstructionError { /// The Batch's max size was exceeded. MaxSizeExceeded, diff --git a/substrate/primitives/src/instructions/in/mod.rs b/substrate/primitives/src/instructions/in/mod.rs index 6e5801f0..b3385df6 100644 --- a/substrate/primitives/src/instructions/in/mod.rs +++ b/substrate/primitives/src/instructions/in/mod.rs @@ -80,7 +80,7 @@ pub struct RefundableInInstruction { #[derive(Clone, PartialEq, Eq, Debug, Zeroize, BorshSerialize, BorshDeserialize)] pub struct InInstructionWithBalance { /// The instruction on how to handle coins in. - pub instruction: OutInstruction, + pub instruction: InInstruction, /// The coins in. pub balance: ExternalBalance, } diff --git a/substrate/primitives/src/instructions/mod.rs b/substrate/primitives/src/instructions/mod.rs index 73ad54e1..5c30e639 100644 --- a/substrate/primitives/src/instructions/mod.rs +++ b/substrate/primitives/src/instructions/mod.rs @@ -1,5 +1,8 @@ mod r#in; -pub use r#in::{InInstruction, InInstructionWithBalance, PushInstructionError, Batch, SignedBatch}; +pub use r#in::{ + InInstruction, InInstructionWithBalance, RefundableInInstruction, PushInstructionError, Batch, + SignedBatch, +}; mod out; pub use out::{OutInstruction, OutInstructionWithBalance}; diff --git a/substrate/primitives/src/network_id.rs b/substrate/primitives/src/network_id.rs index a0af331b..8a963fb9 100644 --- a/substrate/primitives/src/network_id.rs +++ b/substrate/primitives/src/network_id.rs @@ -62,11 +62,11 @@ impl ExternalNetworkId { } /// The coins native to this network. - pub fn coins(&self) -> &'static [ExternalCoin] { + pub fn coins(&self) -> impl Iterator { match self { - Self::Bitcoin => &[ExternalCoin::Bitcoin], - Self::Ethereum => &[ExternalCoin::Ether, ExternalCoin::Dai], - Self::Monero => &[ExternalCoin::Monero], + Self::Bitcoin => [ExternalCoin::Bitcoin].as_slice().iter().copied(), + Self::Ethereum => [ExternalCoin::Ether, ExternalCoin::Dai].as_slice().iter().copied(), + Self::Monero => [ExternalCoin::Monero].as_slice().iter().copied(), } } } @@ -119,11 +119,11 @@ impl NetworkId { /// The coins native to this network. pub fn coins(self) -> impl Iterator { - let (coins, external_coins): (&[Coin], &[ExternalCoin]) = match self { - NetworkId::Serai => (&[Coin::Serai], &[]), - NetworkId::External(ext) => (&[], ext.coins()), + let (coins, external_coins): (&[Coin], _) = match self { + NetworkId::Serai => (&[Coin::Serai], None), + NetworkId::External(ext) => (&[], Some(ext.coins())), }; - coins.iter().copied().chain(external_coins.iter().copied().map(Into::into)) + coins.iter().copied().chain(external_coins.into_iter().flatten().map(Into::into)) } }