mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 22:57:59 -05:00
initial basic dao mint in wasm
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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<MerkleNode, { MERKLE_DEPTH }>;
|
||||
|
||||
#[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<u8> 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<ContractCall>) = 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(())
|
||||
}
|
||||
|
||||
@@ -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<pallas::Base>)> = Vec::new();
|
||||
let signature_public_keys: Vec<pallas::Point> = 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(())
|
||||
}
|
||||
|
||||
@@ -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<pallas::Base>)> = Decodable::decode(&mut decoder)?;
|
||||
let signature_public_keys: Vec<pallas::Point> = Decodable::decode(decoder)?;
|
||||
*/
|
||||
|
||||
show_dao_state(&blockchain, &dao_contract_id)?;
|
||||
show_money_state(&blockchain, &money_contract_id)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -34,6 +34,9 @@ pub mod log;
|
||||
/// Crypto-related definitions
|
||||
pub mod crypto;
|
||||
|
||||
/// Merkle
|
||||
pub mod merkle;
|
||||
|
||||
/// Transaction structure
|
||||
pub mod tx;
|
||||
|
||||
|
||||
@@ -6,5 +6,5 @@ use super::crypto::ContractId;
|
||||
#[derive(SerialEncodable, SerialDecodable)]
|
||||
pub struct ContractCall {
|
||||
pub contract_id: ContractId,
|
||||
pub calldata: Vec<u8>,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
@@ -73,8 +73,6 @@ pub fn deserialize<T: Decodable>(data: &[u8]) -> Result<T, Error> {
|
||||
|
||||
/// 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<usize, Error>;
|
||||
/// Read a 128-bit unsigned int
|
||||
fn read_u128(&mut self) -> Result<u128, Error>;
|
||||
/// 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<u8, Error>;
|
||||
|
||||
/// Read a platform-specific signed int (DANGEROUS AND UNDEFINED)
|
||||
fn read_isize(&mut self) -> Result<isize, Error>;
|
||||
/// Read a 128-bit signed int
|
||||
fn read_i128(&mut self) -> Result<i128, Error>;
|
||||
/// Read a 64-bit signed int
|
||||
@@ -173,12 +165,10 @@ macro_rules! decoder_fn {
|
||||
}
|
||||
|
||||
impl<W: Write> 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<W: Write> WriteExt for W {
|
||||
}
|
||||
|
||||
impl<R: Read> 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<S: WriteExt>(&self, mut s: S) -> Result<usize, Error> {
|
||||
s.write_u64(*self as u64)?;
|
||||
Ok(8)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for usize {
|
||||
#[inline]
|
||||
fn decode<D: Read>(mut d: D) -> Result<Self, Error> {
|
||||
Ok(ReadExt::read_u64(&mut d)? as usize)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for f64 {
|
||||
#[inline]
|
||||
fn encode<S: WriteExt>(&self, mut s: S) -> Result<usize, Error> {
|
||||
|
||||
Reference in New Issue
Block a user