mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 14:48:08 -05:00
contract/deployooor: Initial impl of non-native smart contract deployment.
This supports (Re)Deployment of smart contracts, and additionally making them immutable after they have been deployed.
This commit is contained in:
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -1229,6 +1229,16 @@ dependencies = [
|
||||
"sqlx",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darkfi-deployooor-contract"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"darkfi-sdk",
|
||||
"darkfi-serial",
|
||||
"getrandom",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darkfi-derive"
|
||||
version = "0.4.1"
|
||||
|
||||
@@ -50,6 +50,7 @@ members = [
|
||||
"src/contract/money",
|
||||
"src/contract/dao",
|
||||
"src/contract/consensus",
|
||||
"src/contract/deployooor",
|
||||
|
||||
"example/dchat",
|
||||
]
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
constant "DeployContract" {
|
||||
EcFixedPointBase NULLIFIER_K,
|
||||
}
|
||||
|
||||
witness "DeployContract" {
|
||||
# Amount of bytes to store on-chain
|
||||
Base bytes,
|
||||
# Deploy key used for signing and contract reference
|
||||
Base deploy_key,
|
||||
}
|
||||
|
||||
circuit "DeployContract" {
|
||||
# Derive a public key used for the signature and constrain
|
||||
# its coordinates:
|
||||
signature_public = ec_mul_base(deploy_key, NULLIFIER_K);
|
||||
signature_x = ec_get_x(signature_public);
|
||||
signature_y = ec_get_y(signature_public);
|
||||
constrain_instance(signature_x);
|
||||
constrain_instance(signature_y);
|
||||
|
||||
# Derive the contract address from the public key's coordinates
|
||||
address = poseidon_hash(signature_x, signature_y);
|
||||
constrain_instance(address);
|
||||
|
||||
# Constrain the byte size of the deployed binaries
|
||||
constrain_instance(bytes);
|
||||
|
||||
# TODO: Fee cost for storing this data on-chain
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
This directory contains native WASM contracts on DarkFi.
|
||||
This directory contains native WASM contracts on DarkFi:
|
||||
|
||||
## Money
|
||||
|
||||
* https://darkrenaissance.github.io/darkfi/development/darkfi_money_contract/index.html
|
||||
|
||||
|
||||
## DAO
|
||||
|
||||
* https://darkrenaissance.github.io/darkfi/development/darkfi_dao_contract/index.html
|
||||
@@ -12,3 +11,7 @@ This directory contains native WASM contracts on DarkFi.
|
||||
## Consensus
|
||||
|
||||
* https://darkrenaissance.github.io/darkfi/development/darkfi_consensus_contract/index.html
|
||||
|
||||
## Deployooor
|
||||
|
||||
* https://darkrenaissance.github.io/darkfi/development/darkfi_deployooor_contract/index.html
|
||||
|
||||
1
src/contract/deployooor/.gitignore
vendored
Normal file
1
src/contract/deployooor/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
deployooor_contract.wasm
|
||||
23
src/contract/deployooor/Cargo.toml
Normal file
23
src/contract/deployooor/Cargo.toml
Normal file
@@ -0,0 +1,23 @@
|
||||
[package]
|
||||
name = "darkfi-deployooor-contract"
|
||||
version = "0.4.1"
|
||||
authors = ["Dyne.org foundation <foundation@dyne.org>"]
|
||||
license = "AGPL-3.0-only"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
darkfi-sdk = { path = "../../sdk" }
|
||||
darkfi-serial = { path = "../../serial", features = ["derive", "crypto"] }
|
||||
thiserror = "1.0.40"
|
||||
|
||||
# We need to disable random using "custom" which makes the crate a noop
|
||||
# so the wasm32-unknown-unknown target is enabled.
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
getrandom = { version = "0.2.8", features = ["custom"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
no-entrypoint = []
|
||||
34
src/contract/deployooor/Makefile
Normal file
34
src/contract/deployooor/Makefile
Normal file
@@ -0,0 +1,34 @@
|
||||
.POSIX:
|
||||
|
||||
# Cargo binary
|
||||
CARGO = cargo
|
||||
|
||||
# zkas compiler binary
|
||||
ZKAS = ../../../zkas
|
||||
|
||||
# zkas circuits
|
||||
PROOFS_SRC = $(shell find proof -type f -name '*.zk')
|
||||
PROOFS_BIN = $(PROOFS_SRC:=.bin)
|
||||
|
||||
# wasm source files
|
||||
WASM_SRC = \
|
||||
$(shell find src -type f) \
|
||||
$(shell find ../../sdk -type f) \
|
||||
$(shell find ../../serial -type f)
|
||||
|
||||
# wasm contract binary
|
||||
WASM_BIN = deployooor_contract.wasm
|
||||
|
||||
all: $(WASM_BIN)
|
||||
|
||||
$(WASM_BIN): $(WASM_SRC) $(PROOFS_BIN)
|
||||
$(CARGO) build --release --package darkfi-deployooor-contract --target wasm32-unknown-unknown
|
||||
cp -f ../../../target/wasm32-unknown-unknown/release/darkfi_deployooor_contract.wasm $@
|
||||
|
||||
$(PROOFS_BIN): $(ZKAS) $(PROOFS_SRC)
|
||||
$(ZKAS) $(basename $@) -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(PROOFS_BIN) $(WASM_BIN)
|
||||
|
||||
.PHONY: all clean
|
||||
24
src/contract/deployooor/proof/derive_contract_id.zk
Normal file
24
src/contract/deployooor/proof/derive_contract_id.zk
Normal file
@@ -0,0 +1,24 @@
|
||||
constant "DeriveContractID" {
|
||||
EcFixedPointBase NULLIFIER_K,
|
||||
}
|
||||
|
||||
witness "DeriveContractID" {
|
||||
# Deploy key used for signing and contract ID derivation
|
||||
Base deploy_key,
|
||||
}
|
||||
|
||||
circuit "DeriveContractID" {
|
||||
# ContractID derivation path (See darkfi_sdk::crypto::ContractId)
|
||||
derivation_path = witness_base(42);
|
||||
|
||||
# Derive the public key used for the signature
|
||||
signature_public = ec_mul_base(deploy_key, NULLIFIER_K);
|
||||
signature_x = ec_get_x(signature_public);
|
||||
signature_y = ec_get_y(signature_public);
|
||||
constrain_instance(signature_x);
|
||||
constrain_instance(signature_y);
|
||||
|
||||
# Derive the Contract ID
|
||||
contract_id = poseidon_hash(derivation_path, signature_x, signature_y);
|
||||
constrain_instance(contract_id);
|
||||
}
|
||||
144
src/contract/deployooor/src/entrypoint.rs
Normal file
144
src/contract/deployooor/src/entrypoint.rs
Normal file
@@ -0,0 +1,144 @@
|
||||
/* This file is part of DarkFi (https://dark.fi)
|
||||
*
|
||||
* Copyright (C) 2020-2023 Dyne.org foundation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use darkfi_sdk::{
|
||||
crypto::ContractId,
|
||||
db::{db_init, db_lookup, db_set, zkas_db_set},
|
||||
error::{ContractError, ContractResult},
|
||||
msg,
|
||||
util::set_return_data,
|
||||
ContractCall,
|
||||
};
|
||||
use darkfi_serial::{deserialize, serialize};
|
||||
|
||||
use crate::{
|
||||
model::{DeployUpdateV1, LockUpdateV1},
|
||||
DeployFunction, DEPLOY_CONTRACT_DB_VERSION, DEPLOY_CONTRACT_INFO_TREE,
|
||||
DEPLOY_CONTRACT_LOCK_TREE,
|
||||
};
|
||||
|
||||
/// `Deployooor::Deploy` functions
|
||||
mod deploy_v1;
|
||||
use deploy_v1::{deploy_get_metadata_v1, deploy_process_instruction_v1, deploy_process_update_v1};
|
||||
|
||||
/// `Deployooor::Lock` functions
|
||||
mod lock_v1;
|
||||
use lock_v1::{lock_get_metadata_v1, lock_process_instruction_v1, lock_process_update_v1};
|
||||
|
||||
darkfi_sdk::define_contract!(
|
||||
init: init_contract,
|
||||
exec: process_instruction,
|
||||
apply: process_update,
|
||||
metadata: get_metadata
|
||||
);
|
||||
|
||||
/// This entrypoint function runs when the contract is (re)deployed and initialized.
|
||||
/// We use this function to initialize all the necessary databases and prepare them
|
||||
/// with initial data if necessary.
|
||||
fn init_contract(cid: ContractId, _ix: &[u8]) -> ContractResult {
|
||||
// Set up the zkas circuit tree
|
||||
let derive_cid_bincode = include_bytes!("../proof/derive_contract_id.zk");
|
||||
zkas_db_set(&derive_cid_bincode[..])?;
|
||||
|
||||
// Set up a database tree for arbitrary data
|
||||
let info_db = match db_lookup(cid, DEPLOY_CONTRACT_INFO_TREE) {
|
||||
Ok(v) => v,
|
||||
Err(_) => {
|
||||
let info_db = db_init(cid, DEPLOY_CONTRACT_INFO_TREE)?;
|
||||
info_db
|
||||
}
|
||||
};
|
||||
|
||||
// Set up a database to hold the set of locked contracts
|
||||
// k=ContractId, v=bool
|
||||
if db_lookup(cid, DEPLOY_CONTRACT_LOCK_TREE).is_err() {
|
||||
db_init(cid, DEPLOY_CONTRACT_LOCK_TREE)?;
|
||||
}
|
||||
|
||||
// Update db version
|
||||
db_set(
|
||||
info_db,
|
||||
&serialize(&DEPLOY_CONTRACT_DB_VERSION),
|
||||
&serialize(&env!("CARGO_PKG_VERSION")),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This function is used by the wasm VM's host to fetch the necessary metadata
|
||||
/// for verifying signatures and zk proofs. The payload given here are all the
|
||||
/// contract calls in the transaction.
|
||||
fn get_metadata(cid: ContractId, ix: &[u8]) -> ContractResult {
|
||||
let (call_idx, calls): (u32, Vec<ContractCall>) = deserialize(ix)?;
|
||||
if call_idx >= calls.len() as u32 {
|
||||
msg!("Error: call_idx >= calls.len()");
|
||||
return Err(ContractError::Internal)
|
||||
}
|
||||
|
||||
match DeployFunction::try_from(calls[call_idx as usize].data[0])? {
|
||||
DeployFunction::DeployV1 => {
|
||||
let metadata = deploy_get_metadata_v1(cid, call_idx, calls)?;
|
||||
Ok(set_return_data(&metadata)?)
|
||||
}
|
||||
|
||||
DeployFunction::LockV1 => {
|
||||
let metadata = lock_get_metadata_v1(cid, call_idx, calls)?;
|
||||
Ok(set_return_data(&metadata)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This function verifies a state transition and produces a state update
|
||||
/// if everything is successful.
|
||||
fn process_instruction(cid: ContractId, ix: &[u8]) -> ContractResult {
|
||||
let (call_idx, calls): (u32, Vec<ContractCall>) = deserialize(ix)?;
|
||||
if call_idx >= calls.len() as u32 {
|
||||
msg!("Error: call_idx >= calls.len()");
|
||||
return Err(ContractError::Internal)
|
||||
}
|
||||
|
||||
match DeployFunction::try_from(calls[call_idx as usize].data[0])? {
|
||||
DeployFunction::DeployV1 => {
|
||||
let update_data = deploy_process_instruction_v1(cid, call_idx, calls)?;
|
||||
Ok(set_return_data(&update_data)?)
|
||||
}
|
||||
|
||||
DeployFunction::LockV1 => {
|
||||
let update_data = lock_process_instruction_v1(cid, call_idx, calls)?;
|
||||
Ok(set_return_data(&update_data)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This function attempts to write a given state update provided the previous
|
||||
/// steps of the contract call execution were all successful. It's the last in
|
||||
/// line, and assumes that the transaction/call was successful. The payload
|
||||
/// given to the function is the update data retrieved from `process_instruction()`.
|
||||
fn process_update(cid: ContractId, update_data: &[u8]) -> ContractResult {
|
||||
match DeployFunction::try_from(update_data[0])? {
|
||||
DeployFunction::DeployV1 => {
|
||||
let update: DeployUpdateV1 = deserialize(&update_data[1..])?;
|
||||
Ok(deploy_process_update_v1(cid, update)?)
|
||||
}
|
||||
|
||||
DeployFunction::LockV1 => {
|
||||
let update: LockUpdateV1 = deserialize(&update_data[1..])?;
|
||||
Ok(lock_process_update_v1(cid, update)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
103
src/contract/deployooor/src/entrypoint/deploy_v1.rs
Normal file
103
src/contract/deployooor/src/entrypoint/deploy_v1.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
/* This file is part of DarkFi (https://dark.fi)
|
||||
*
|
||||
* Copyright (C) 2020-2023 Dyne.org foundation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use darkfi_sdk::{
|
||||
crypto::{ContractId, PublicKey},
|
||||
db::{db_get, db_lookup, db_set},
|
||||
error::{ContractError, ContractResult},
|
||||
msg,
|
||||
pasta::pallas,
|
||||
ContractCall,
|
||||
};
|
||||
use darkfi_serial::{deserialize, serialize, Encodable, WriteExt};
|
||||
|
||||
use crate::{
|
||||
error::DeployError,
|
||||
model::{DeployParamsV1, DeployUpdateV1},
|
||||
DeployFunction, DEPLOY_CONTRACT_LOCK_TREE, DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1,
|
||||
};
|
||||
|
||||
/// `get_metadata` function for `Deploy::DeployV1`
|
||||
pub(crate) fn deploy_get_metadata_v1(
|
||||
_cid: ContractId,
|
||||
call_idx: u32,
|
||||
calls: Vec<ContractCall>,
|
||||
) -> Result<Vec<u8>, ContractError> {
|
||||
let self_ = &calls[call_idx as usize];
|
||||
let params: DeployParamsV1 = deserialize(&self_.data[1..])?;
|
||||
|
||||
// Public inputs for the ZK proofs we have to verify
|
||||
let mut zk_public_inputs: Vec<(String, Vec<pallas::Base>)> = vec![];
|
||||
// Public keys for the transaction signatures we have to verify
|
||||
let signature_pubkeys: Vec<PublicKey> = vec![params.public_key];
|
||||
|
||||
// Derive the ContractID from the public key
|
||||
let (sig_x, sig_y) = params.public_key.xy();
|
||||
let contract_id = ContractId::derive_public(params.public_key);
|
||||
|
||||
// Append the ZK public inputs
|
||||
zk_public_inputs.push((
|
||||
DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1.to_string(),
|
||||
vec![sig_x, sig_y, contract_id.inner()],
|
||||
));
|
||||
|
||||
// Serialize everything gathered and return it
|
||||
let mut metadata = vec![];
|
||||
zk_public_inputs.encode(&mut metadata)?;
|
||||
signature_pubkeys.encode(&mut metadata)?;
|
||||
|
||||
Ok(metadata)
|
||||
}
|
||||
|
||||
/// `process_instruction` function for `Deploy::DeployV1`
|
||||
pub(crate) fn deploy_process_instruction_v1(
|
||||
cid: ContractId,
|
||||
call_idx: u32,
|
||||
calls: Vec<ContractCall>,
|
||||
) -> Result<Vec<u8>, ContractError> {
|
||||
let self_ = &calls[call_idx as usize];
|
||||
let params: DeployParamsV1 = deserialize(&self_.data[1..])?;
|
||||
|
||||
// In this function, we have to check that the contract isn't locked.
|
||||
let lock_db = db_lookup(cid, DEPLOY_CONTRACT_LOCK_TREE)?;
|
||||
let contract_id = ContractId::derive_public(params.public_key);
|
||||
|
||||
if let Some(v) = db_get(lock_db, &serialize(&contract_id))? {
|
||||
let locked: bool = deserialize(&v)?;
|
||||
if locked {
|
||||
msg!("[DeployV1] Error: Contract is locked. Cannot redeploy.");
|
||||
return Err(DeployError::ContractLocked.into())
|
||||
}
|
||||
}
|
||||
|
||||
let update = DeployUpdateV1 { contract_id };
|
||||
let mut update_data = vec![];
|
||||
update_data.write_u8(DeployFunction::DeployV1 as u8)?;
|
||||
update.encode(&mut update_data)?;
|
||||
Ok(update_data)
|
||||
}
|
||||
|
||||
/// `process_update` function for `Deploy::DeployV1`
|
||||
pub(crate) fn deploy_process_update_v1(cid: ContractId, update: DeployUpdateV1) -> ContractResult {
|
||||
// We add the contract to the list
|
||||
msg!("[DeployV1] Adding ContractID to deployed list");
|
||||
let lock_db = db_lookup(cid, DEPLOY_CONTRACT_LOCK_TREE)?;
|
||||
db_set(lock_db, &serialize(&update.contract_id), &serialize(&false))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
109
src/contract/deployooor/src/entrypoint/lock_v1.rs
Normal file
109
src/contract/deployooor/src/entrypoint/lock_v1.rs
Normal file
@@ -0,0 +1,109 @@
|
||||
/* This file is part of DarkFi (https://dark.fi)
|
||||
*
|
||||
* Copyright (C) 2020-2023 Dyne.org foundation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use darkfi_sdk::{
|
||||
crypto::{ContractId, PublicKey},
|
||||
db::{db_contains_key, db_get, db_lookup, db_set},
|
||||
error::{ContractError, ContractResult},
|
||||
msg,
|
||||
pasta::pallas,
|
||||
ContractCall,
|
||||
};
|
||||
use darkfi_serial::{deserialize, serialize, Encodable, WriteExt};
|
||||
|
||||
use crate::{
|
||||
error::DeployError,
|
||||
model::{LockParamsV1, LockUpdateV1},
|
||||
DeployFunction, DEPLOY_CONTRACT_LOCK_TREE, DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1,
|
||||
};
|
||||
|
||||
/// `get_metadata` function for `Deploy::LockV1`
|
||||
pub(crate) fn lock_get_metadata_v1(
|
||||
_cid: ContractId,
|
||||
call_idx: u32,
|
||||
calls: Vec<ContractCall>,
|
||||
) -> Result<Vec<u8>, ContractError> {
|
||||
let self_ = &calls[call_idx as usize];
|
||||
let params: LockParamsV1 = deserialize(&self_.data[1..])?;
|
||||
|
||||
// Public inputs for the ZK proofs we have to verify
|
||||
let mut zk_public_inputs: Vec<(String, Vec<pallas::Base>)> = vec![];
|
||||
// Public keys for the transaction signatures we have to verify
|
||||
let signature_pubkeys: Vec<PublicKey> = vec![params.public_key];
|
||||
|
||||
// Derive the ContractID from the public key
|
||||
let (sig_x, sig_y) = params.public_key.xy();
|
||||
let contract_id = ContractId::derive_public(params.public_key);
|
||||
|
||||
// Append the ZK public inputs
|
||||
zk_public_inputs.push((
|
||||
DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1.to_string(),
|
||||
vec![sig_x, sig_y, contract_id.inner()],
|
||||
));
|
||||
|
||||
// Serialize everything gathered and return it
|
||||
let mut metadata = vec![];
|
||||
zk_public_inputs.encode(&mut metadata)?;
|
||||
signature_pubkeys.encode(&mut metadata)?;
|
||||
|
||||
Ok(metadata)
|
||||
}
|
||||
|
||||
/// `process_instruction` function for `Deploy::LockV1`
|
||||
pub(crate) fn lock_process_instruction_v1(
|
||||
cid: ContractId,
|
||||
call_idx: u32,
|
||||
calls: Vec<ContractCall>,
|
||||
) -> Result<Vec<u8>, ContractError> {
|
||||
let self_ = &calls[call_idx as usize];
|
||||
let params: LockParamsV1 = deserialize(&self_.data[1..])?;
|
||||
|
||||
// In this function, we check that the contract exists, and that it isn't
|
||||
// already locked.
|
||||
let lock_db = db_lookup(cid, DEPLOY_CONTRACT_LOCK_TREE)?;
|
||||
let contract_id = ContractId::derive_public(params.public_key);
|
||||
|
||||
if !db_contains_key(lock_db, &serialize(&contract_id))? {
|
||||
msg!("[LockV1] Error: Contract ID doesn't exist.");
|
||||
return Err(DeployError::ContractNonExistent.into())
|
||||
}
|
||||
|
||||
let v = db_get(lock_db, &serialize(&contract_id))?.unwrap();
|
||||
let locked: bool = deserialize(&v)?;
|
||||
if locked {
|
||||
msg!("[LockV1] Error: Contract already locked.");
|
||||
return Err(DeployError::ContractLocked.into())
|
||||
}
|
||||
|
||||
let update = LockUpdateV1 { contract_id };
|
||||
let mut update_data = vec![];
|
||||
update_data.write_u8(DeployFunction::LockV1 as u8)?;
|
||||
update.encode(&mut update_data)?;
|
||||
|
||||
Ok(update_data)
|
||||
}
|
||||
|
||||
/// `process_update` function for `Deploy::LockV1`
|
||||
pub(crate) fn lock_process_update_v1(cid: ContractId, update: LockUpdateV1) -> ContractResult {
|
||||
// We make the contract immutable
|
||||
msg!("[LockV1] Making ContractID immutable");
|
||||
let lock_db = db_lookup(cid, DEPLOY_CONTRACT_LOCK_TREE)?;
|
||||
db_set(lock_db, &serialize(&update.contract_id), &serialize(&true))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
37
src/contract/deployooor/src/error.rs
Normal file
37
src/contract/deployooor/src/error.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of DarkFi (https://dark.fi)
|
||||
*
|
||||
* Copyright (C) 2020-2023 Dyne.org foundation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use darkfi_sdk::error::ContractError;
|
||||
|
||||
#[derive(Debug, Clone, thiserror::Error)]
|
||||
pub enum DeployError {
|
||||
#[error("Contract deployment is locked.")]
|
||||
ContractLocked,
|
||||
|
||||
#[error("Contract does not exist.")]
|
||||
ContractNonExistent,
|
||||
}
|
||||
|
||||
impl From<DeployError> for ContractError {
|
||||
fn from(e: DeployError) -> Self {
|
||||
match e {
|
||||
DeployError::ContractLocked => Self::Custom(1),
|
||||
DeployError::ContractNonExistent => Self::Custom(2),
|
||||
}
|
||||
}
|
||||
}
|
||||
60
src/contract/deployooor/src/lib.rs
Normal file
60
src/contract/deployooor/src/lib.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
/* This file is part of DarkFi (https://dark.fi)
|
||||
*
|
||||
* Copyright (C) 2020-2023 Dyne.org foundation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Smart contract implementing non-native smart contract deployment.
|
||||
|
||||
use darkfi_sdk::error::ContractError;
|
||||
|
||||
/// Functions available in the contract
|
||||
#[repr(u8)]
|
||||
pub enum DeployFunction {
|
||||
DeployV1 = 0x00,
|
||||
LockV1 = 0x01,
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for DeployFunction {
|
||||
type Error = ContractError;
|
||||
|
||||
fn try_from(b: u8) -> core::result::Result<Self, Self::Error> {
|
||||
match b {
|
||||
0x00 => Ok(Self::DeployV1),
|
||||
0x01 => Ok(Self::LockV1),
|
||||
_ => Err(ContractError::InvalidFunction),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no-entrypoint"))]
|
||||
/// WASM entrypoint functions
|
||||
pub mod entrypoint;
|
||||
|
||||
/// Call parameters definitions
|
||||
pub mod model;
|
||||
|
||||
/// Contract errors
|
||||
pub mod error;
|
||||
|
||||
// These are the different sled trees that will be created
|
||||
pub const DEPLOY_CONTRACT_INFO_TREE: &str = "info";
|
||||
pub const DEPLOY_CONTRACT_LOCK_TREE: &str = "lock";
|
||||
|
||||
// These are keys inside the info tree
|
||||
pub const DEPLOY_CONTRACT_DB_VERSION: &str = "db_version";
|
||||
|
||||
/// zkas derive circuit namespace
|
||||
pub const DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1: &str = "DeriveContractID";
|
||||
50
src/contract/deployooor/src/model.rs
Normal file
50
src/contract/deployooor/src/model.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
/* This file is part of DarkFi (https://dark.fi)
|
||||
*
|
||||
* Copyright (C) 2020-2023 Dyne.org foundation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use darkfi_sdk::crypto::{ContractId, PublicKey};
|
||||
use darkfi_serial::{SerialDecodable, SerialEncodable};
|
||||
|
||||
/// Parameters for `Deploy::Deploy`
|
||||
#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
|
||||
pub struct DeployParamsV1 {
|
||||
/// Webassembly bincode of the smart contract
|
||||
pub wasm_bincode: Vec<u8>,
|
||||
/// Public key used to sign the transaction and derive the `ContractId`
|
||||
pub public_key: PublicKey,
|
||||
}
|
||||
|
||||
/// State update for `Deploy::Deploy`
|
||||
#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
|
||||
pub struct DeployUpdateV1 {
|
||||
/// The `ContractId` to deploy
|
||||
pub contract_id: ContractId,
|
||||
}
|
||||
|
||||
/// Parameters for `Deploy::Lock`
|
||||
#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
|
||||
pub struct LockParamsV1 {
|
||||
/// Public key used to sign the transaction and derive the `ContractId`
|
||||
pub public_key: PublicKey,
|
||||
}
|
||||
|
||||
/// State update for `Deploy::Lock`
|
||||
#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
|
||||
pub struct LockUpdateV1 {
|
||||
/// The `ContractId` to lock
|
||||
pub contract_id: ContractId,
|
||||
}
|
||||
Reference in New Issue
Block a user