diff --git a/example/dao2/contract/dao/Cargo.toml b/example/dao2/contract/dao/Cargo.toml index e3f645f66..9d2293831 100644 --- a/example/dao2/contract/dao/Cargo.toml +++ b/example/dao2/contract/dao/Cargo.toml @@ -10,7 +10,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] darkfi-sdk = { path = "../../../../src/sdk" } -darkfi-serial = { path = "../../../../src/serial" } +darkfi-serial = { path = "../../../../src/serial", features = ["crypto"] } # We need to disable random using "custom" which makes the crate a noop # so the wasm32-unknown-unknown target is enabled. diff --git a/example/dao2/contract/dao/src/lib.rs b/example/dao2/contract/dao/src/lib.rs index 426397006..76e92f6af 100644 --- a/example/dao2/contract/dao/src/lib.rs +++ b/example/dao2/contract/dao/src/lib.rs @@ -1,14 +1,23 @@ use darkfi_sdk::{ - crypto::ContractId, + crypto::{ContractId, constants::MERKLE_DEPTH, MerkleNode, Nullifier}, db::{db_get, db_init, db_lookup, db_set}, define_contract, error::ContractResult, msg, + merkle::merkle_add, pasta::pallas, tx::ContractCall, - util::{set_return_data, put_object_bytes, get_object_bytes, get_object_size}, + util::{get_object_bytes, get_object_size, put_object_bytes, set_return_data}, + incrementalmerkletree::{bridgetree::BridgeTree, Tree} }; -use darkfi_serial::{deserialize, serialize, Encodable, SerialDecodable, SerialEncodable, WriteExt, ReadExt}; +use darkfi_serial::{ + deserialize, serialize, Encodable, ReadExt, SerialDecodable, SerialEncodable, WriteExt, +}; + +type MerkleTree = BridgeTree; + +#[derive(Clone, SerialEncodable, SerialDecodable)] +pub struct DaoBulla(pub pallas::Base); #[repr(u8)] pub enum DaoFunction { @@ -16,10 +25,23 @@ pub enum DaoFunction { Mint = 0x01, } +impl From for DaoFunction { + fn from(b: u8) -> Self { + match b { + 0x00 => Self::Foo, + 0x01 => Self::Mint, + _ => panic!("Invalid function ID: {:#04x?}", b), + } + } +} + #[derive(SerialEncodable, SerialDecodable)] pub struct DaoMintParams { - pub a: u32, - pub b: u32 + pub dao_bulla: DaoBulla, +} +#[derive(SerialEncodable, SerialDecodable)] +pub struct DaoMintUpdate { + pub dao_bulla: DaoBulla, } define_contract!( @@ -30,7 +52,11 @@ define_contract!( ); fn init_contract(cid: ContractId, _ix: &[u8]) -> ContractResult { - let db_handle = db_init(cid, "wagies")?; + let db_handle = db_init(cid, "info")?; + + let dao_tree = MerkleTree::new(100); + let dao_tree_data = serialize(&dao_tree); + db_set(db_handle, &serialize(&"dao_tree".to_string()), &dao_tree_data)?; Ok(()) } @@ -46,10 +72,47 @@ fn get_metadata(_cid: ContractId, ix: &[u8]) -> ContractResult { Ok(()) } fn process_instruction(cid: ContractId, ix: &[u8]) -> ContractResult { + let (call_idx, call): (u32, Vec) = deserialize(ix)?; + + assert!(call_idx < call.len() as u32); + let self_ = &call[call_idx as usize]; + + match DaoFunction::from(self_.data[0]) { + DaoFunction::Mint => { + let data = &self_.data[1..]; + let params: DaoMintParams = deserialize(data)?; + + // No checks in Mint. Just return the update. + + let update = DaoMintUpdate { dao_bulla: params.dao_bulla }; + + let mut update_data = Vec::new(); + update_data.write_u8(DaoFunction::Mint as u8); + update.encode(&mut update_data); + set_return_data(&update_data)?; + msg!("update is set!"); + } + DaoFunction::Foo => { + unimplemented!(); + } + } + Ok(()) } fn process_update(cid: ContractId, update_data: &[u8]) -> ContractResult { - let db_handle = db_lookup(cid, "wagies")?; - db_set(db_handle, &serialize(&"jason_gulag".to_string()), &serialize(&110))?; + match DaoFunction::from(update_data[0]) { + DaoFunction::Mint => { + let data = &update_data[1..]; + let update: DaoMintUpdate = deserialize(data)?; + + let db_handle = db_lookup(cid, "info")?; + let node = MerkleNode::new(update.dao_bulla.0); + merkle_add(db_handle, &serialize(&"dao_tree".to_string()), &node)?; + } + DaoFunction::Foo => { + unimplemented!(); + } + } + Ok(()) } diff --git a/example/dao2/contract/money/src/lib.rs b/example/dao2/contract/money/src/lib.rs index 29aa06949..cb073bc6e 100644 --- a/example/dao2/contract/money/src/lib.rs +++ b/example/dao2/contract/money/src/lib.rs @@ -1,8 +1,57 @@ +use darkfi_sdk::{ + crypto::ContractId, + db::{db_get, db_init, db_lookup, db_set}, + define_contract, + error::ContractResult, + msg, + pasta::pallas, + tx::ContractCall, + util::{get_object_bytes, get_object_size, put_object_bytes, set_return_data}, +}; +use darkfi_serial::{ + deserialize, serialize, Encodable, ReadExt, SerialDecodable, SerialEncodable, WriteExt, +}; + #[repr(u8)] pub enum MoneyFunction { - Bar = 0x01, + Foo = 0x00, + Mint = 0x01, } -pub fn bar() { - println!("bar"); +#[derive(SerialEncodable, SerialDecodable)] +pub struct MoneyMintParams { + pub a: u32, + pub b: u32, +} + +define_contract!( + init: init_contract, + exec: process_instruction, + apply: process_update, + metadata: get_metadata +); + +fn init_contract(cid: ContractId, _ix: &[u8]) -> ContractResult { + let db_handle = db_init(cid, "wagies")?; + + Ok(()) +} +fn get_metadata(_cid: ContractId, ix: &[u8]) -> ContractResult { + let zk_public_values: Vec<(String, Vec)> = Vec::new(); + let signature_public_keys: Vec = Vec::new(); + + let mut metadata = Vec::new(); + zk_public_values.encode(&mut metadata)?; + signature_public_keys.encode(&mut metadata)?; + set_return_data(&metadata)?; + + Ok(()) +} +fn process_instruction(cid: ContractId, ix: &[u8]) -> ContractResult { + Ok(()) +} +fn process_update(cid: ContractId, update_data: &[u8]) -> ContractResult { + let db_handle = db_lookup(cid, "wagies")?; + db_set(db_handle, &serialize(&"jason_gulag".to_string()), &serialize(&110))?; + Ok(()) } diff --git a/example/dao2/src/main.rs b/example/dao2/src/main.rs index 676c4d039..4562987d5 100644 --- a/example/dao2/src/main.rs +++ b/example/dao2/src/main.rs @@ -1,22 +1,69 @@ use darkfi::{ blockchain::Blockchain, consensus::{TESTNET_GENESIS_HASH_BYTES, TESTNET_GENESIS_TIMESTAMP}, + crypto::{ + coin::Coin, + keypair::{Keypair, PublicKey, SecretKey}, + proof::{ProvingKey, VerifyingKey}, + types::{DrkSpendHook, DrkUserData, DrkValue}, + util::{pedersen_commitment_u64, poseidon_hash}, + }, runtime::vm_runtime::Runtime, + zk::circuit::{BurnContract, MintContract}, + zkas::decoder::ZkBinary, Result, }; -use darkfi_sdk::{crypto::ContractId, pasta::pallas, tx::ContractCall}; -use darkfi_serial::{serialize, deserialize, Decodable, Encodable, WriteExt}; -use std::io::Cursor; +use darkfi_sdk::{ + crypto::{constants::MERKLE_DEPTH, ContractId, MerkleNode}, + tx::ContractCall, +}; +use darkfi_serial::{deserialize, serialize, Decodable, Encodable, WriteExt}; +use incrementalmerkletree::{bridgetree::BridgeTree, Tree}; +use log::{debug, error}; +use pasta_curves::{ + arithmetic::CurveAffine, + group::{ff::Field, Curve, Group}, + pallas, +}; +use rand::rngs::OsRng; +use std::{ + any::{Any, TypeId}, + io::Cursor, + time::Instant, +}; use dao_contract::{DaoFunction, DaoMintParams}; +use crate::{ + contract::{dao, example, money}, + note::EncryptedNote2, + schema::WalletCache, + tx::Transaction, + util::{sign, StateRegistry, ZkContractTable}, +}; + mod contract; mod error; mod note; mod schema; +mod tx; mod util; fn show_dao_state(chain: &Blockchain, contract_id: &ContractId) -> Result<()> { + let db = chain.contracts.lookup(&chain.sled_db, contract_id, "info")?; + match db.get(&serialize(&"dao_tree".to_string())).expect("dao_tree") { + Some(value) => { + debug!(target: "demo", "DAO tree: {} bytes", value.len()); + } + None => { + error!(target: "demo", "Missing DAO tree"); + } + } + + Ok(()) +} + +fn show_money_state(chain: &Blockchain, contract_id: &ContractId) -> Result<()> { let db = chain.contracts.lookup(&chain.sled_db, contract_id, "wagies")?; for obj in db.iter() { let (key, value) = obj.unwrap(); @@ -43,19 +90,229 @@ async fn main() -> BoxResult<()> { println!("wakie wakie young wagie"); + //return Ok(()); + //schema::schema().await?; //return Ok(()); // ============================= - // Initialize a dummy blockchain + // Setup initial program parameters // ============================= + + // Money parameters + let xdrk_supply = 1_000_000; + let xdrk_token_id = pallas::Base::random(&mut OsRng); + + // Governance token parameters + let gdrk_supply = 1_000_000; + let gdrk_token_id = pallas::Base::random(&mut OsRng); + + // DAO parameters + let dao_proposer_limit = 110; + let dao_quorum = 110; + let dao_approval_ratio_quot = 1; + let dao_approval_ratio_base = 2; + + // Initialize ZK binary table + let mut zk_bins = ZkContractTable::new(); + + debug!(target: "demo", "Loading dao-mint.zk"); + let zk_dao_mint_bincode = include_bytes!("../proof/dao-mint.zk.bin"); + let zk_dao_mint_bin = ZkBinary::decode(zk_dao_mint_bincode)?; + zk_bins.add_contract("dao-mint".to_string(), zk_dao_mint_bin, 13); + + /* + debug!(target: "demo", "Loading money-transfer contracts"); + { + let start = Instant::now(); + let mint_pk = ProvingKey::build(11, &MintContract::default()); + debug!("Mint PK: [{:?}]", start.elapsed()); + let start = Instant::now(); + let burn_pk = ProvingKey::build(11, &BurnContract::default()); + debug!("Burn PK: [{:?}]", start.elapsed()); + let start = Instant::now(); + let mint_vk = VerifyingKey::build(11, &MintContract::default()); + debug!("Mint VK: [{:?}]", start.elapsed()); + let start = Instant::now(); + let burn_vk = VerifyingKey::build(11, &BurnContract::default()); + debug!("Burn VK: [{:?}]", start.elapsed()); + + zk_bins.add_native("money-transfer-mint".to_string(), mint_pk, mint_vk); + zk_bins.add_native("money-transfer-burn".to_string(), burn_pk, burn_vk); + } + debug!(target: "demo", "Loading dao-propose-main.zk"); + let zk_dao_propose_main_bincode = include_bytes!("../proof/dao-propose-main.zk.bin"); + let zk_dao_propose_main_bin = ZkBinary::decode(zk_dao_propose_main_bincode)?; + zk_bins.add_contract("dao-propose-main".to_string(), zk_dao_propose_main_bin, 13); + debug!(target: "demo", "Loading dao-propose-burn.zk"); + let zk_dao_propose_burn_bincode = include_bytes!("../proof/dao-propose-burn.zk.bin"); + let zk_dao_propose_burn_bin = ZkBinary::decode(zk_dao_propose_burn_bincode)?; + zk_bins.add_contract("dao-propose-burn".to_string(), zk_dao_propose_burn_bin, 13); + debug!(target: "demo", "Loading dao-vote-main.zk"); + let zk_dao_vote_main_bincode = include_bytes!("../proof/dao-vote-main.zk.bin"); + let zk_dao_vote_main_bin = ZkBinary::decode(zk_dao_vote_main_bincode)?; + zk_bins.add_contract("dao-vote-main".to_string(), zk_dao_vote_main_bin, 13); + debug!(target: "demo", "Loading dao-vote-burn.zk"); + let zk_dao_vote_burn_bincode = include_bytes!("../proof/dao-vote-burn.zk.bin"); + let zk_dao_vote_burn_bin = ZkBinary::decode(zk_dao_vote_burn_bincode)?; + zk_bins.add_contract("dao-vote-burn".to_string(), zk_dao_vote_burn_bin, 13); + let zk_dao_exec_bincode = include_bytes!("../proof/dao-exec.zk.bin"); + let zk_dao_exec_bin = ZkBinary::decode(zk_dao_exec_bincode)?; + zk_bins.add_contract("dao-exec".to_string(), zk_dao_exec_bin, 13); + + // State for money contracts + let cashier_signature_secret = SecretKey::random(&mut OsRng); + let cashier_signature_public = PublicKey::from_secret(cashier_signature_secret); + let faucet_signature_secret = SecretKey::random(&mut OsRng); + let faucet_signature_public = PublicKey::from_secret(faucet_signature_secret); + */ + + // We use this to receive coins + let mut cache = WalletCache::new(); + + // Initialize a dummy blockchain // TODO: This blockchain interface should perhaps be ValidatorState and Mutex/RwLock. let db = sled::Config::new().temporary(true).open()?; let blockchain = Blockchain::new(&db, *TESTNET_GENESIS_TIMESTAMP, *TESTNET_GENESIS_HASH_BYTES)?; // ================================================================ - // Load the wasm binary into memory and create an execution runtime + // Deploy the wasm contracts // ================================================================ + + let dao_wasm_bytes = std::fs::read("dao_contract.wasm")?; + let dao_contract_id = ContractId::from(pallas::Base::from(1)); + let money_wasm_bytes = std::fs::read("money_contract.wasm")?; + let money_contract_id = ContractId::from(pallas::Base::from(2)); + + // Block 1 + // This has 2 transaction deploying the DAO and Money wasm contracts + // together with their ZK proofs. + { + let mut dao_runtime = Runtime::new(&dao_wasm_bytes, blockchain.clone(), dao_contract_id)?; + let mut money_runtime = + Runtime::new(&money_wasm_bytes, blockchain.clone(), money_contract_id)?; + + // 1. exec() - zk and sig verify also + // ... none in this block + + // 2. commit() - all apply() and deploy() + // Deploy function to initialize the smart contract state. + // Here we pass an empty payload, but it's possible to feed in arbitrary data. + dao_runtime.deploy(&[])?; + money_runtime.deploy(&[])?; + debug!(target: "demo", "Deployed DAO and money contracts"); + } + + // ================================================================ + // DAO::mint() + // ================================================================ + + // Wallet + let dao_keypair = Keypair::random(&mut OsRng); + let dao_bulla_blind = pallas::Base::random(&mut OsRng); + let tx = { + let signature_secret = SecretKey::random(&mut OsRng); + // Create DAO mint tx + let builder = dao::mint::wallet::Builder { + dao_proposer_limit, + dao_quorum, + dao_approval_ratio_quot, + dao_approval_ratio_base, + gov_token_id: gdrk_token_id, + dao_pubkey: dao_keypair.public, + dao_bulla_blind, + signature_secret, + }; + let (params, dao_mint_proofs) = builder.build(&zk_bins); + + // Write the actual call data + let mut calldata = Vec::new(); + // Selects which path executes in the contract. + calldata.write_u8(DaoFunction::Mint as u8)?; + params.encode(&mut calldata)?; + + let calls = vec![ContractCall { contract_id: dao_contract_id, data: calldata }]; + + //let mut payload = Vec::new(); + ////// Write the actual payload data + //let call_index = 0; + //payload.write_u32(call_index)?; + //func_calls.encode(&mut payload)?; + + let signatures = vec![]; + //for func_call in &func_calls { + // let sign = sign([signature_secret].to_vec(), func_call); + // signatures.push(sign); + //} + + //let tx = Transaction { func_calls, signatures }; + let proofs = vec![dao_mint_proofs]; + + Transaction { calls, proofs, signatures } + }; + + //// Validator + + // We can do all exec(), zk proof checks and signature verifies in parallel. + let mut updates = vec![]; + // Validate all function calls in the tx + for (idx, call) in tx.calls.iter().enumerate() { + // So then the verifier will lookup the corresponding state_transition and apply + // functions based off the func_id + + // Write the actual payload data + let mut payload = Vec::new(); + // Call index + payload.write_u32(idx as u32)?; + // Actuall calldata + tx.calls.encode(&mut payload)?; + + match call.contract_id { + dao_contract_id => { + debug!(target: "demo", "DAO::exec() contract called"); + let mut runtime = + Runtime::new(&dao_wasm_bytes, blockchain.clone(), dao_contract_id)?; + let update = runtime.exec(&payload)?; + updates.push(update); + } + money_contract_id => { + debug!(target: "demo", "Money::exec() contract called"); + let mut runtime = + Runtime::new(&money_wasm_bytes, blockchain.clone(), money_contract_id)?; + let update = runtime.exec(&payload)?; + updates.push(update); + } + _ => {} + } + } + + //tx.zk_verify(&zk_bins).unwrap(); + //tx.verify_sigs(); + + // Now we finished verification stage, just apply all changes + assert_eq!(tx.calls.len(), updates.len()); + for (call, update) in tx.calls.iter().zip(updates.iter()) { + match call.contract_id { + dao_contract_id => { + debug!(target: "demo", "DAO::apply() contract called"); + let mut runtime = + Runtime::new(&dao_wasm_bytes, blockchain.clone(), dao_contract_id)?; + runtime.apply(&update)?; + } + money_contract_id => { + debug!(target: "demo", "Money::apply() contract called"); + let mut runtime = + Runtime::new(&money_wasm_bytes, blockchain.clone(), money_contract_id)?; + runtime.apply(&update)?; + } + _ => {} + } + } + + ///////////////////////////////////////////////// + // Old stuff + ///////////////////////////////////////////////// + /* let wasm_bytes = std::fs::read("dao_contract.wasm")?; let dao_contract_id = ContractId::from(pallas::Base::from(1)); let mut runtime = Runtime::new(&wasm_bytes, blockchain.clone(), dao_contract_id)?; @@ -105,8 +362,10 @@ async fn main() -> BoxResult<()> { let mut decoder = Cursor::new(&metadata); let zk_public_values: Vec<(String, Vec)> = Decodable::decode(&mut decoder)?; let signature_public_keys: Vec = Decodable::decode(decoder)?; + */ show_dao_state(&blockchain, &dao_contract_id)?; + show_money_state(&blockchain, &money_contract_id)?; Ok(()) } diff --git a/example/dao2/src/schema.rs b/example/dao2/src/schema.rs index e37b1b2a9..37e6ea8a7 100644 --- a/example/dao2/src/schema.rs +++ b/example/dao2/src/schema.rs @@ -174,6 +174,7 @@ pub async fn example() -> Result<()> { } pub async fn schema() -> Result<()> { + /* // Example smart contract //// TODO: this will be moved to a different file example().await?; @@ -1288,7 +1289,7 @@ pub async fn schema() -> Result<()> { tx.verify_sigs(); //// Wallet + */ Ok(()) } - diff --git a/src/runtime/import/db.rs b/src/runtime/import/db.rs index 6a0096157..1597b052c 100644 --- a/src/runtime/import/db.rs +++ b/src/runtime/import/db.rs @@ -29,7 +29,7 @@ use crate::{ /// Internal wasm runtime API for sled trees pub struct DbHandle { - contract_id: ContractId, + pub contract_id: ContractId, tree: sled::Tree, } diff --git a/src/runtime/import/mod.rs b/src/runtime/import/mod.rs index c690a025d..6d358dc43 100644 --- a/src/runtime/import/mod.rs +++ b/src/runtime/import/mod.rs @@ -19,5 +19,8 @@ /// Host functions for interacting with db backend pub(crate) mod db; +/// Host functions for merkle tree functions +pub(crate) mod merkle; + /// Host functions for utilities pub(crate) mod util; diff --git a/src/runtime/vm_runtime.rs b/src/runtime/vm_runtime.rs index c239cc040..a6a6d5e0e 100644 --- a/src/runtime/vm_runtime.rs +++ b/src/runtime/vm_runtime.rs @@ -222,6 +222,12 @@ impl Runtime { &ctx, import::util::get_object_size, ), + + "merkle_add_" => Function::new_typed_with_env( + &mut store, + &ctx, + import::merkle::merkle_add, + ), } }; diff --git a/src/sdk/src/crypto/merkle_node.rs b/src/sdk/src/crypto/merkle_node.rs index 7ab87603b..93a5d65ee 100644 --- a/src/sdk/src/crypto/merkle_node.rs +++ b/src/sdk/src/crypto/merkle_node.rs @@ -54,6 +54,10 @@ lazy_static! { pub struct MerkleNode(pallas::Base); impl MerkleNode { + pub fn new(v: pallas::Base) -> Self { + Self(v) + } + /// Reference the raw inner base field element pub fn inner(&self) -> pallas::Base { self.0 diff --git a/src/sdk/src/db.rs b/src/sdk/src/db.rs index e6bfe0e6a..0ab9f33ec 100644 --- a/src/sdk/src/db.rs +++ b/src/sdk/src/db.rs @@ -6,7 +6,7 @@ use super::{ util::{get_object_bytes, get_object_size}, }; -type DbHandle = u32; +pub type DbHandle = u32; type TxHandle = u32; /// Only deploy() can call this. Creates a new database instance for this contract. diff --git a/src/sdk/src/lib.rs b/src/sdk/src/lib.rs index 7bcae1ac1..2c8c8bbdb 100644 --- a/src/sdk/src/lib.rs +++ b/src/sdk/src/lib.rs @@ -34,6 +34,9 @@ pub mod log; /// Crypto-related definitions pub mod crypto; +/// Merkle +pub mod merkle; + /// Transaction structure pub mod tx; diff --git a/src/sdk/src/tx.rs b/src/sdk/src/tx.rs index 78af6a3a1..989c32a84 100644 --- a/src/sdk/src/tx.rs +++ b/src/sdk/src/tx.rs @@ -6,5 +6,5 @@ use super::crypto::ContractId; #[derive(SerialEncodable, SerialDecodable)] pub struct ContractCall { pub contract_id: ContractId, - pub calldata: Vec, + pub data: Vec, } diff --git a/src/serial/src/lib.rs b/src/serial/src/lib.rs index bf7af03c7..2fe096915 100644 --- a/src/serial/src/lib.rs +++ b/src/serial/src/lib.rs @@ -73,8 +73,6 @@ pub fn deserialize(data: &[u8]) -> Result { /// Extensions of `Write` to encode data as per Bitcoin consensus. pub trait WriteExt { - /// Output a platform-specific unsigned int (DANGEROUS AND UNDEFINED) - fn write_usize(&mut self, v: usize) -> Result<(), Error>; /// Output a 128-bit unsigned int fn write_u128(&mut self, v: u128) -> Result<(), Error>; /// Output a 64-bit unsigned int @@ -86,8 +84,6 @@ pub trait WriteExt { /// Output an 8-bit unsigned int fn write_u8(&mut self, v: u8) -> Result<(), Error>; - /// Output a platform-specific signed int (DANGEROUS AND UNDEFINED) - fn write_isize(&mut self, v: isize) -> Result<(), Error>; /// Output a 128-bit signed int fn write_i128(&mut self, v: i128) -> Result<(), Error>; /// Output a 64-bit signed int @@ -113,8 +109,6 @@ pub trait WriteExt { /// Extensions of `Read` to decode data as per Bitcoin consensus. pub trait ReadExt { - /// Read a platform-specific unsigned int (DANGEROUS AND UNDEFINED) - fn read_usize(&mut self) -> Result; /// Read a 128-bit unsigned int fn read_u128(&mut self) -> Result; /// Read a 64-bit unsigned int @@ -126,8 +120,6 @@ pub trait ReadExt { /// Read an 8-bit unsigned int fn read_u8(&mut self) -> Result; - /// Read a platform-specific signed int (DANGEROUS AND UNDEFINED) - fn read_isize(&mut self) -> Result; /// Read a 128-bit signed int fn read_i128(&mut self) -> Result; /// Read a 64-bit signed int @@ -173,12 +165,10 @@ macro_rules! decoder_fn { } impl WriteExt for W { - encoder_fn!(write_usize, usize, usize_to_array_le); encoder_fn!(write_u128, u128, u128_to_array_le); encoder_fn!(write_u64, u64, u64_to_array_le); encoder_fn!(write_u32, u32, u32_to_array_le); encoder_fn!(write_u16, u16, u16_to_array_le); - encoder_fn!(write_isize, isize, isize_to_array_le); encoder_fn!(write_i128, i128, i128_to_array_le); encoder_fn!(write_i64, i64, i64_to_array_le); encoder_fn!(write_i32, i32, i32_to_array_le); @@ -205,12 +195,10 @@ impl WriteExt for W { } impl ReadExt for R { - decoder_fn!(read_usize, usize, slice_to_usize_le, usize::BITS as usize / 8); decoder_fn!(read_u128, u128, slice_to_u128_le, 16); decoder_fn!(read_u64, u64, slice_to_u64_le, 8); decoder_fn!(read_u32, u32, slice_to_u32_le, 4); decoder_fn!(read_u16, u16, slice_to_u16_le, 2); - decoder_fn!(read_isize, isize, slice_to_isize_le, isize::BITS as usize / 8); decoder_fn!(read_i128, i128, slice_to_i128_le, 16); decoder_fn!(read_i64, i64, slice_to_i64_le, 8); decoder_fn!(read_i32, i32, slice_to_i32_le, 4); @@ -264,14 +252,12 @@ impl_int_encodable!(u16, read_u16, write_u16); impl_int_encodable!(u32, read_u32, write_u32); impl_int_encodable!(u64, read_u64, write_u64); impl_int_encodable!(u128, read_u128, write_u128); -impl_int_encodable!(usize, read_usize, write_usize); impl_int_encodable!(i8, read_i8, write_i8); impl_int_encodable!(i16, read_i16, write_i16); impl_int_encodable!(i32, read_i32, write_i32); impl_int_encodable!(i64, read_i64, write_i64); impl_int_encodable!(i128, read_i128, write_i128); -impl_int_encodable!(isize, read_isize, write_isize); /// Variable-integer encoding #[derive(Debug, PartialEq, Eq)] @@ -397,6 +383,21 @@ macro_rules! encode_payload { } // Implementations for some primitive types. +impl Encodable for usize { + #[inline] + fn encode(&self, mut s: S) -> Result { + s.write_u64(*self as u64)?; + Ok(8) + } +} + +impl Decodable for usize { + #[inline] + fn decode(mut d: D) -> Result { + Ok(ReadExt::read_u64(&mut d)? as usize) + } +} + impl Encodable for f64 { #[inline] fn encode(&self, mut s: S) -> Result {