dao-test: mint gov token

This commit is contained in:
x
2022-12-26 11:09:59 +01:00
parent 57d4cd899f
commit e02daace77
2 changed files with 180 additions and 5 deletions

View File

@@ -145,12 +145,19 @@ async fn integration_test() -> Result<()> {
cache.track(dao_th.dao_kp.secret);
// We use this to receive coins
//let mut cache = WalletCache::new();
//let (params, proofs) = builder.build(&zk_bins)?;
// Address of deployed contract in our example is dao::exec::FUNC_ID
// This field is public, you can see it's being sent to a DAO
// but nothing else is visible.
//
// In the python code we wrote:
//
// spend_hook = b"0xdao_ruleset"
//
// TODO: this should be the contract/func ID
let spend_hook = pallas::Base::from(110);
// The user_data can be a simple hash of the items passed into the ZK proof
// up to corresponding linked ZK proof to interpret however they need.
// In out case, it's the bulla for the DAO
let user_data = dao_bulla.inner();
let builder = money_client::Builder {
@@ -234,7 +241,154 @@ async fn integration_test() -> Result<()> {
debug!("DAO received a coin worth {} xDRK", treasury_note.value);
///////////////////////////////////////////////////
// =======================================================
// Money::Transfer
//
// Mint the governance token
// Send it to three hodlers
// =======================================================
debug!(target: "demo", "Stage 3. Minting governance token");
cache.track(money_th.alice_kp.secret);
cache.track(money_th.bob_kp.secret);
cache.track(money_th.charlie_kp.secret);
// Spend hook and user data disabled
let spend_hook = pallas::Base::from(0);
let user_data = pallas::Base::from(0);
let output1 = money_client::BuilderOutputInfo {
value: 400000,
token_id: gdrk_token_id,
public: money_th.alice_kp.public,
serial: pallas::Base::random(&mut OsRng),
coin_blind: pallas::Base::random(&mut OsRng),
spend_hook,
user_data,
};
let output2 = money_client::BuilderOutputInfo {
value: 400000,
token_id: gdrk_token_id,
public: money_th.bob_kp.public,
serial: pallas::Base::random(&mut OsRng),
coin_blind: pallas::Base::random(&mut OsRng),
spend_hook,
user_data,
};
let output3 = money_client::BuilderOutputInfo {
value: 200000,
token_id: gdrk_token_id,
public: money_th.charlie_kp.public,
serial: pallas::Base::random(&mut OsRng),
coin_blind: pallas::Base::random(&mut OsRng),
spend_hook,
user_data,
};
assert!(2 * 400000 + 200000 == gdrk_supply);
let builder = money_client::Builder {
clear_inputs: vec![money_client::BuilderClearInputInfo {
value: gdrk_supply,
token_id: gdrk_token_id,
// This might be different for various tokens but lets reuse it here
signature_secret: money_th.faucet_kp.secret,
}],
inputs: vec![],
outputs: vec![output1, output2, output3],
};
let (params, proofs) = builder.build(
&money_th.mint_zkbin,
&money_th.mint_pk,
&money_th.burn_zkbin,
&money_th.burn_pk,
)?;
let contract_id = *MONEY_CONTRACT_ID;
let mut data = vec![MoneyFunction::Transfer as u8];
params.encode(&mut data)?;
let calls = vec![ContractCall { contract_id, data }];
let proofs = vec![proofs];
let mut tx = Transaction { calls, proofs, signatures: vec![] };
let sigs = tx.create_sigs(&mut OsRng, &vec![money_th.faucet_kp.secret])?;
tx.signatures = vec![sigs];
money_th.faucet_state.read().await.verify_transactions(&[tx.clone()], true).await?;
money_th.faucet_merkle_tree.append(&MerkleNode::from(params.outputs[0].coin));
// Wallet
{
assert_eq!(tx.calls.len(), 1);
let calldata = &tx.calls[0].data;
let params_data = &calldata[1..];
let params: MoneyTransferParams = Decodable::decode(params_data)?;
for output in params.outputs {
let coin = output.coin;
let enc_note =
EncryptedNote { ciphertext: output.ciphertext, ephem_public: output.ephem_public };
let coin = Coin(coin);
cache.try_decrypt_note(coin, &enc_note);
}
}
let gov_keypairs = vec![money_th.alice_kp, money_th.bob_kp, money_th.charlie_kp];
let mut gov_recv = vec![None, None, None];
// Check that each person received one coin
for (i, key) in gov_keypairs.iter().enumerate() {
let gov_recv_coin = {
let mut recv_coins = cache.get_received(&key.secret);
assert_eq!(recv_coins.len(), 1);
let recv_coin = recv_coins.pop().unwrap();
let note = &recv_coin.note;
assert_eq!(note.token_id, gdrk_token_id);
// Normal payment
assert_eq!(note.spend_hook, pallas::Base::from(0));
assert_eq!(note.user_data, pallas::Base::from(0));
let (pub_x, pub_y) = key.public.xy();
let coin = poseidon_hash::<8>([
pub_x,
pub_y,
pallas::Base::from(note.value),
note.token_id.inner(),
note.serial,
note.spend_hook,
note.user_data,
note.coin_blind,
]);
assert_eq!(coin, recv_coin.coin.0);
debug!("Holder{} received a coin worth {} gDRK", i, note.value);
recv_coin
};
gov_recv[i] = Some(gov_recv_coin);
}
// unwrap them for this demo
let gov_recv: Vec<_> = gov_recv.into_iter().map(|r| r.unwrap()).collect();
// =======================================================
// Dao::Propose
//
// Propose the vote
// In order to make a valid vote, first the proposer must
// meet a criteria for a minimum number of gov tokens
//
// DAO rules:
// 1. gov token IDs must match on all inputs
// 2. proposals must be submitted by minimum amount
// 3. all votes >= quorum
// 4. outcome > approval_ratio
// 5. structure of outputs
// output 0: value and address
// output 1: change address
// =======================================================
debug!(target: "demo", "Stage 4. Propose the vote");
Ok(())
}

View File

@@ -70,10 +70,12 @@ pub struct MoneyTestHarness {
pub faucet_kp: Keypair,
pub alice_kp: Keypair,
pub bob_kp: Keypair,
pub charlie_kp: Keypair,
pub faucet_pubkeys: Vec<PublicKey>,
pub faucet_state: ValidatorStatePtr,
pub alice_state: ValidatorStatePtr,
pub bob_state: ValidatorStatePtr,
pub charlie_state: ValidatorStatePtr,
pub money_contract_id: ContractId,
pub proving_keys: HashMap<[u8; 32], Vec<(&'static str, ProvingKey)>>,
pub mint_zkbin: ZkBinary,
@@ -83,6 +85,7 @@ pub struct MoneyTestHarness {
pub faucet_merkle_tree: BridgeTree<MerkleNode, MERKLE_DEPTH>,
pub alice_merkle_tree: BridgeTree<MerkleNode, MERKLE_DEPTH>,
pub bob_merkle_tree: BridgeTree<MerkleNode, MERKLE_DEPTH>,
pub charlie_merkle_tree: BridgeTree<MerkleNode, MERKLE_DEPTH>,
}
impl MoneyTestHarness {
@@ -90,15 +93,18 @@ impl MoneyTestHarness {
let faucet_kp = Keypair::random(&mut OsRng);
let alice_kp = Keypair::random(&mut OsRng);
let bob_kp = Keypair::random(&mut OsRng);
let charlie_kp = Keypair::random(&mut OsRng);
let faucet_pubkeys = vec![faucet_kp.public];
let faucet_wallet = WalletDb::new("sqlite::memory:", "foo").await?;
let alice_wallet = WalletDb::new("sqlite::memory:", "foo").await?;
let bob_wallet = WalletDb::new("sqlite::memory:", "foo").await?;
let charlie_wallet = WalletDb::new("sqlite::memory:", "foo").await?;
let faucet_sled_db = sled::Config::new().temporary(true).open()?;
let alice_sled_db = sled::Config::new().temporary(true).open()?;
let bob_sled_db = sled::Config::new().temporary(true).open()?;
let charlie_sled_db = sled::Config::new().temporary(true).open()?;
let faucet_state = ValidatorState::new(
&faucet_sled_db,
@@ -133,6 +139,17 @@ impl MoneyTestHarness {
)
.await?;
let charlie_state = ValidatorState::new(
&charlie_sled_db,
*TESTNET_BOOTSTRAP_TIMESTAMP,
*TESTNET_GENESIS_TIMESTAMP,
*TESTNET_GENESIS_HASH_BYTES,
charlie_wallet,
faucet_pubkeys.clone(),
false,
)
.await?;
let money_contract_id = *MONEY_CONTRACT_ID;
let alice_sled = alice_state.read().await.blockchain.sled_db.clone();
@@ -166,15 +183,18 @@ impl MoneyTestHarness {
let faucet_merkle_tree = BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(100);
let alice_merkle_tree = BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(100);
let bob_merkle_tree = BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(100);
let charlie_merkle_tree = BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(100);
Ok(Self {
faucet_kp,
alice_kp,
bob_kp,
charlie_kp,
faucet_pubkeys,
faucet_state,
alice_state,
bob_state,
charlie_state,
money_contract_id,
proving_keys,
mint_pk,
@@ -184,6 +204,7 @@ impl MoneyTestHarness {
faucet_merkle_tree,
alice_merkle_tree,
bob_merkle_tree,
charlie_merkle_tree,
})
}