diff --git a/tuxedo-core/src/lib.rs b/tuxedo-core/src/lib.rs index fadec067..19e02fc0 100644 --- a/tuxedo-core/src/lib.rs +++ b/tuxedo-core/src/lib.rs @@ -11,6 +11,7 @@ mod executive; pub mod constraint_checker; pub mod genesis; pub mod inherents; +pub mod metadata; pub mod support_macros; pub mod traits; pub mod types; @@ -21,6 +22,7 @@ pub use aggregator::{aggregate, tuxedo_constraint_checker, tuxedo_verifier}; pub use constraint_checker::{ConstraintChecker, SimpleConstraintChecker}; pub use executive::Executive; pub use inherents::{InherentAdapter, InherentHooks}; +pub use metadata::TuxedoMetadata; pub use verifier::Verifier; /// A Tuxedo-specific target for diagnostic node log messages diff --git a/tuxedo-core/src/metadata.rs b/tuxedo-core/src/metadata.rs new file mode 100644 index 00000000..ed1ed618 --- /dev/null +++ b/tuxedo-core/src/metadata.rs @@ -0,0 +1,24 @@ +//! A simple type to use as metadata. For now the metadata just communicates whether we +//! are dealing with a parachain or not. + +use parity_scale_codec::{Decode, Encode}; +#[derive(Default, Debug, Encode, Decode)] +pub struct TuxedoMetadata { + /// Placeholder for the scale info type registry that will hopefully eventually go here. + _registry: (), + /// Indicator of whether this chain is a parachain or not. + parachain: bool, +} + +impl TuxedoMetadata { + pub fn new_parachain() -> Self { + Self { + _registry: (), + parachain: true, + } + } + + pub fn is_parachain(&self) -> bool { + self.parachain + } +} diff --git a/tuxedo-parachain-runtime/src/lib.rs b/tuxedo-parachain-runtime/src/lib.rs index b7ac7a65..673a5bc9 100644 --- a/tuxedo-parachain-runtime/src/lib.rs +++ b/tuxedo-parachain-runtime/src/lib.rs @@ -29,7 +29,7 @@ use tuxedo_core::{ genesis::TuxedoGenesisConfigBuilder, tuxedo_constraint_checker, types::Block as TuxedoBlock, types::Transaction as TuxedoTransaction, InherentAdapter, }; -use tuxedo_parachain_core::tuxedo_core; +use tuxedo_parachain_core::tuxedo_core::{self, TuxedoMetadata}; // We use the same aggregate verifier and opaque types from the inner_runtime. // They do not contain anything parachain specific. @@ -149,10 +149,10 @@ impl_runtime_apis! { } } - // Tuxedo does not yet support metadata + // Tuxedo metadata is pretty trivial atm impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - OpaqueMetadata::new(Default::default()) + OpaqueMetadata::new(TuxedoMetadata::new_parachain().encode()) } fn metadata_at_version(_version: u32) -> Option { diff --git a/tuxedo-template-runtime/src/lib.rs b/tuxedo-template-runtime/src/lib.rs index 3f22aaf1..a3472ae0 100644 --- a/tuxedo-template-runtime/src/lib.rs +++ b/tuxedo-template-runtime/src/lib.rs @@ -37,7 +37,7 @@ use tuxedo_core::{ tuxedo_constraint_checker, tuxedo_verifier, types::Transaction as TuxedoTransaction, verifier::{Sr25519Signature, ThresholdMultiSignature, UpForGrabs}, - InherentAdapter, + InherentAdapter, TuxedoMetadata, }; pub use amoeba; @@ -273,10 +273,10 @@ impl_runtime_apis! { } } - // Tuxedo does not yet support metadata + // Tuxedo metadata is pretty trivial atm impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - OpaqueMetadata::new(Default::default()) + OpaqueMetadata::new(TuxedoMetadata::default().encode()) } fn metadata_at_version(_version: u32) -> Option { diff --git a/wallet/src/cli.rs b/wallet/src/cli.rs index fc44a3c2..e35053a5 100644 --- a/wallet/src/cli.rs +++ b/wallet/src/cli.rs @@ -40,10 +40,6 @@ pub struct Cli { /// The keystore will contain the development key Shawn. pub dev: bool, - /// Use the Parachain template encoding instead of the regular node template encoding. - #[arg(long, short, verbatim_doc_comment)] - pub parachain: bool, - #[command(subcommand)] pub command: Option, } diff --git a/wallet/src/main.rs b/wallet/src/main.rs index 5615321b..5240f1ca 100644 --- a/wallet/src/main.rs +++ b/wallet/src/main.rs @@ -53,6 +53,9 @@ async fn main() -> anyhow::Result<()> { // https://github.com/paritytech/jsonrpsee/blob/master/examples/examples/http.rs let client = HttpClientBuilder::default().build(cli.endpoint)?; + // Fetch the metadata and determine whether we are dealing with a parachain. + let metadata = rpc::node_get_metadata(&client).await?; + // Read node's genesis block. let node_genesis_hash = rpc::node_get_block_hash(0, &client) .await? @@ -80,7 +83,7 @@ async fn main() -> anyhow::Result<()> { if !sled::Db::was_recovered(&db) { // This is a new instance, so we need to apply the genesis block to the database. - if cli.parachain { + if metadata.is_parachain() { sync::apply_block::<_, ParachainConstraintChecker>( &db, node_genesis_block, @@ -103,7 +106,7 @@ async fn main() -> anyhow::Result<()> { if cli.no_sync { log::warn!("Skipping sync with node. Using previously synced information.") } else { - sync::synchronize(cli.parachain, &db, &client, &keystore_filter).await?; + sync::synchronize(metadata.is_parachain(), &db, &client, &keystore_filter).await?; log::info!( "Wallet database synchronized with node to height {:?}", @@ -113,9 +116,11 @@ async fn main() -> anyhow::Result<()> { // Dispatch to proper subcommand match cli.command { - Some(Command::AmoebaDemo) => amoeba::amoeba_demo(cli.parachain, &client).await, + Some(Command::AmoebaDemo) => amoeba::amoeba_demo(metadata.is_parachain(), &client).await, // Command::MultiSigDemo => multi_sig::multi_sig_demo(&client).await, - Some(Command::MintCoins(args)) => money::mint_coins(cli.parachain, &client, args).await, + Some(Command::MintCoins(args)) => { + money::mint_coins(metadata.is_parachain(), &client, args).await + } Some(Command::VerifyCoin { output_ref }) => { println!("Details of coin {}:", hex::encode(output_ref.encode())); @@ -138,7 +143,7 @@ async fn main() -> anyhow::Result<()> { Ok(()) } Some(Command::SpendCoins(args)) => { - money::spend_coins(cli.parachain, &db, &client, &keystore, args).await + money::spend_coins(metadata.is_parachain(), &db, &client, &keystore, args).await } Some(Command::InsertKey { seed }) => crate::keystore::insert_key(&keystore, &seed), Some(Command::GenerateKey { password }) => { diff --git a/wallet/src/rpc.rs b/wallet/src/rpc.rs index 4691623e..9ae88a54 100644 --- a/wallet/src/rpc.rs +++ b/wallet/src/rpc.rs @@ -8,9 +8,25 @@ use parity_scale_codec::{Decode, Encode}; use sp_core::H256; use tuxedo_core::{ types::{OpaqueBlock, Output, OutputRef}, - Verifier, + TuxedoMetadata, Verifier, }; +/// Get the node's metadata +pub async fn node_get_metadata(client: &HttpClient) -> anyhow::Result { + // Don't provide a block height to use the best height. + let params = rpc_params![Option::::None]; + let rpc_response: Option = client.request("state_getMetadata", params).await?; + let metadata = metadata_from_string(&rpc_response.expect("metadata should be available."))?; + Ok(metadata) +} + +/// Parse a string into a Tuxedo Metadata +pub(crate) fn metadata_from_string(s: &str) -> anyhow::Result { + let s = strip_0x_prefix(s); + let bytes = hex::decode(s)?; + Ok(TuxedoMetadata::decode(&mut &bytes[..])?) +} + /// Typed helper to get the Node's block hash at a particular height pub async fn node_get_block_hash(height: u32, client: &HttpClient) -> anyhow::Result> { let params = rpc_params![Some(height)];