Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Darkmap #170

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ members = [
"src/contract/money",
"src/contract/dao",
"src/contract/consensus",
"src/contract/map",

"example/dchat",
]
Expand Down
2 changes: 1 addition & 1 deletion doc/src/architecture/smart_contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ both automatically verified by the VM.

However for verification to work, the ZK proofs also need corresponding
public values, and the signatures need the public keys. We do this
by exporting these values. (TODO: link the code where this happens)
by exporting these values. For example: https://github.com/darkrenaissance/darkfi/blob/6cddfac05f0d61f3a0f077082f87282d3df72f70/src/contract/dao/src/entrypoint.rs#L487-L488

These methods export the required values needed for the ZK proofs
and signature verification from the actual call data itself.
Expand Down
93 changes: 93 additions & 0 deletions doc/src/learn/contract-intro/overview.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# data storage

* a contract can have any number of databases, barring any future gas limitations i assume
```
src/runtime/vm_runtime.rs

const GAS_LIMIT: u64 = 200000000;

// TODO: Add necessary operators
// This function will be called for each `Operator` encountered during
// the wasm module execution. It should return the cost of the operator
// that it received as its first argument.
// https://docs.rs/wasmparser/latest/wasmparser/enum.Operator.html
let cost_function = |operator: &Operator| -> u64 {
match operator {
Operator::LocalGet { .. } => 1,
Operator::I32Const { .. } => 1,
Operator::I32Add { .. } => 2,
_ => 0,
}
};
```
contract_id db_name key value
v v v v
* storage is keyed by (pallas::Base, &str, Vec<u8>, Vec<u8>)
* contract can only write its own databases, and not others'
* each database is a publicly readable record
* src/runtime/import/db.rs
* src/sdk/src/crypto/contract_id.rs

# anonymity

* a contract can choose to persist plaintext, then this contract is completely transparent, no different than a contract on a transparent blockchain
* contract only gets anonymity by carefull persisting **only** encrypted state

see how a coin is represented: note there is no owner
```

/////////////// model ////////////////

/// input to contract's mint
pub struct MoneyMintParamsV1 {
pub input: ClearInput,
pub output: Output,
}

pub struct ClearInput {
/// q: for checking commitment, why?
pub value: u64,
pub token_id: TokenId,
pub value_blind: pallas::Scalar,
pub token_blind: pallas::Scalar,
pub signature_public: PublicKey,
}

pub struct Output {
pub value_commit: pallas::Point,
pub token_commit: pallas::Point,
pub coin: Coin,
pub note: AeadEncryptedNote,
}

/// state changes
pub struct MoneyMintUpdateV1 {
/// this is a base field element (ie a number) that doesn't reveal value or owner
/// yes, there is value in ClearInput, need to figure out why
pub coin: Coin,
}

/// src/contract/money/proof/mint_v1.zk
circuit "TokenMint_V1" {
...
token_id = poseidon_hash(...);
// only token is public
constrain_instance(token_id);

C = poseidon_hash(
// receipent is hidden in the hash
rcpt_x,
rcpt_y,
...
);
constrain_instance(C);
...
}
//////////// zkp //////////////////
```

# runtime, instructions, apis

* for zk circuits, the zk opcodes are in src/zkas/opcodes.rs
* for wasm contract, i believe anything that compiles to wasm would work, but src/sdk have ready-made tools
* when in doubt, look at src/contract/ for inspirations
49 changes: 28 additions & 21 deletions src/consensus/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use async_std::sync::{Arc, RwLock};
use darkfi_sdk::{
crypto::{
constants::MERKLE_DEPTH,
contract_id::{CONSENSUS_CONTRACT_ID, DAO_CONTRACT_ID, MONEY_CONTRACT_ID},
contract_id::MAP_CONTRACT_ID,
schnorr::{SchnorrPublic, SchnorrSecret},
MerkleNode, PublicKey, SecretKey,
},
Expand Down Expand Up @@ -94,7 +94,7 @@ impl ValidatorState {
genesis_data: blake3::Hash,
initial_distribution: u64,
wallet: WalletPtr,
faucet_pubkeys: Vec<PublicKey>,
_faucet_pubkeys: Vec<PublicKey>,
enable_participation: bool,
single_node: bool,
) -> Result<ValidatorStatePtr> {
Expand Down Expand Up @@ -148,28 +148,35 @@ impl ValidatorState {

// The faucet pubkeys are pubkeys which are allowed to create clear inputs
// in the money contract.
let money_contract_deploy_payload = serialize(&faucet_pubkeys);
let dao_contract_deploy_payload = vec![];
let consensus_contract_deploy_payload = vec![];
// let money_contract_deploy_payload = serialize(&faucet_pubkeys);
// let dao_contract_deploy_payload = vec![];
// let consensus_contract_deploy_payload = vec![];
let map_contract_deploy_payload = vec![];

let native_contracts = vec![
// (
// "Money Contract",
// *MONEY_CONTRACT_ID,
// include_bytes!("../contract/money/money_contract.wasm").to_vec(),
// money_contract_deploy_payload,
// ),
// (
// "DAO Contract",
// *DAO_CONTRACT_ID,
// include_bytes!("../contract/dao/dao_contract.wasm").to_vec(),
// dao_contract_deploy_payload,
// ),
// (
// "Consensus Contract",
// *CONSENSUS_CONTRACT_ID,
// include_bytes!("../contract/consensus/consensus_contract.wasm").to_vec(),
// consensus_contract_deploy_payload,
// ),
(
"Money Contract",
*MONEY_CONTRACT_ID,
include_bytes!("../contract/money/money_contract.wasm").to_vec(),
money_contract_deploy_payload,
),
(
"DAO Contract",
*DAO_CONTRACT_ID,
include_bytes!("../contract/dao/dao_contract.wasm").to_vec(),
dao_contract_deploy_payload,
),
(
"Consensus Contract",
*CONSENSUS_CONTRACT_ID,
include_bytes!("../contract/consensus/consensus_contract.wasm").to_vec(),
consensus_contract_deploy_payload,
"Map Contract",
*MAP_CONTRACT_ID,
include_bytes!("../contract/map/map_contract.wasm").to_vec(),
map_contract_deploy_payload,
),
];

Expand Down
2 changes: 2 additions & 0 deletions src/contract/map/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
map_contract.wasm
proof/*.zk.bin
48 changes: 48 additions & 0 deletions src/contract/map/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
[package]
name = "darkfi-map-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"

# The following dependencies are used for the client API and
# probably shouldn't be in WASM
chacha20poly1305 = { version = "0.10.1", optional = true }
# why is darkfi undeclared?
darkfi = { path = "../../../", features = ["zk", "rpc", "blockchain"], optional = true }
halo2_proofs = { version = "0.3.0", optional = true }
log = { version = "0.4.17", optional = true }
rand = { version = "0.8.5", optional = true }

# These are used just for the integration tests
[dev-dependencies]
async-std = {version = "1.12.0", features = ["attributes"]}
bs58 = "0.4.0"
darkfi = {path = "../../../", features = ["tx", "blockchain"]}
simplelog = "0.12.1"
sled = "0.34.7"
sqlx = {version = "0.6.3", features = ["runtime-async-std-rustls", "sqlite"]}

# 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 = []
client = [
"darkfi",
"rand",
"chacha20poly1305",
"log",
"halo2_proofs",
]
45 changes: 45 additions & 0 deletions src/contract/map/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.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 = map_contract.wasm

all: $(WASM_BIN)

$(WASM_BIN): $(WASM_SRC) $(PROOFS_BIN)
$(CARGO) build --release --package darkfi-map-contract --target wasm32-unknown-unknown
cp -f ../../../target/wasm32-unknown-unknown/release/darkfi_map_contract.wasm $@

client:
$(CARGO) build --release --features=no-entrypoint,client \
--package darkfi-map-contract \

$(PROOFS_BIN): $(ZKAS) $(PROOFS_SRC)
$(ZKAS) $(basename $@) -o $@

test-integration: all
$(CARGO) test --release --features=no-entrypoint,client \
--package darkfi-map-contract \
--test integration

test: test-integration

clean:
rm -f $(PROOFS_BIN) $(WASM_BIN)

.PHONY: all test-integration
51 changes: 51 additions & 0 deletions src/contract/map/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Darkmap

`Darkmap` aims to be a permissionless name system.

Anyone can have a number of pseudonyms, each pseudonym can own a number of
namespaces.

There is a strong gurantee of immutability, so values can be safely
cached locally (even the secret is leaked).

The main application is to enable a private and secure software supply chain.

## Dpath

Syntax example: ns1:ns2.key

```
# mutable example

we want master to change, so we make it mutable

mutable
v
darkrenaissance:darkfi.master -> 1fb851750a6b8bfadfe60ca362cff0fc89a9b2ed
^ ^
namespace subnamespace


# immutable example

once we cut the release tag, we don't want the path to change, so we make it immutable

immutable immutable
v v
darkrenaissance:darkfi:v0_4_1 -> 0793fe32a3d7e9bedef9c3c0767647c74db215e9 (tagged commit should never change)
```

```
darkrenaissance:darkfi:v0_4_1 -> 0793fe32a3d7e9bedef9c3c0767647c74db215e9 (tagged commit should never change)
^
namespace is owned by bob
suppose bob's secret is leaked
because v0_4_1 is permanently locked in the darkfi namespace,
adversary cannot change the path's value

```

# Credit

Designed by someone else and with love.

Binary file added src/contract/map/darkmap_plan.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions src/contract/map/proof/set_v1.zk
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
constant "Set_V1" {}

witness "Set_V1" {
Base secret,
Base lock,
# Whether set canonical root
#
# Be nice, don't spam
# setting slots in the canonical root namespace will be paid eventually
# but people can always choose to use an alt root
Base car,
Base key,
Base value,
}

circuit "Set_V1" {
account = poseidon_hash(secret);
constrain_instance(account);
constrain_instance(lock);
constrain_instance(car);
constrain_instance(key);
constrain_instance(value);
bool_check(lock);
bool_check(car);
}

31 changes: 31 additions & 0 deletions src/contract/map/src/client/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* 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/>.
*/

//! This module implements the client-side API for this contract's interaction.
//! What we basically do here is implement an API that creates the necessary
//! structures and is able to export them to create a DarkFi transaction
//! object that can be broadcasted to the network when we want to make a
//! payment with some coins in our wallet.
//!
//! Note that this API does not involve any wallet interaction, but only takes
//! the necessary objects provided by the caller. This is intentional, so we
//! are able to abstract away any wallet interfaces to client implementations.

/// `Map::Set` API
pub mod set_v1;

Loading