Skip to content

Commit

Permalink
Merge pull request #355 from dusk-network/bid-tests
Browse files Browse the repository at this point in the history
Add EXTEND and WITHDRAW tests bor bid-contract
  • Loading branch information
CPerezz authored Aug 13, 2021
2 parents e380c0c + 8add218 commit a472114
Show file tree
Hide file tree
Showing 4 changed files with 329 additions and 107 deletions.
2 changes: 1 addition & 1 deletion contracts/bid/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ dusk-plonk = "0.8"
lazy_static = "1.4"
rand = "0.8"
rusk-profile = { path = "../../rusk-profile" }
rusk-vm = "0.7.0-rc"
rusk-vm = { version = "0.7.0-rc", features = ["persistence"] }
transfer-circuits = { path = "../../circuits/transfer", features = ["builder"] }
transfer-wrapper = { path = "../../test-utils/transfer-wrapper" }
13 changes: 7 additions & 6 deletions contracts/bid/src/hosted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use alloc::vec::Vec;
use canonical::{Canon, CanonError, Sink, Source};
use dusk_abi::{ContractState, ReturnValue};
use dusk_bls12_381::BlsScalar;
use dusk_jubjub::JubJubAffine;
use dusk_pki::{PublicKey, StealthAddress};
use dusk_schnorr::Signature;
use phoenix_core::{Message, Note};
Expand Down Expand Up @@ -64,7 +65,7 @@ fn transaction(bytes: &mut [u8; PAGE_SIZE]) -> Result<(), CanonError> {
let correctness_proof = Vec::<u8>::decode(&mut source)?;
let spending_proof = Vec::<u8>::decode(&mut source)?;
// Call bid contract fn
let success = slf.bid(
slf.bid(
message,
hashed_secret,
stealth_addr,
Expand All @@ -76,7 +77,7 @@ fn transaction(bytes: &mut [u8; PAGE_SIZE]) -> Result<(), CanonError> {
// return new state
ContractState::from_canon(&slf).encode(&mut sink);
// return result
ReturnValue::from_canon(&success).encode(&mut sink);
ReturnValue::from_canon(&true).encode(&mut sink);
Ok(())
}
ops::WITHDRAW => {
Expand All @@ -85,26 +86,26 @@ fn transaction(bytes: &mut [u8; PAGE_SIZE]) -> Result<(), CanonError> {
let pk = PublicKey::decode(&mut source)?;
let note = Note::decode(&mut source)?;
let spending_proof = Vec::<u8>::decode(&mut source)?;
let exec_res = slf.withdraw(sig, pk, note, spending_proof);
slf.withdraw(sig, pk, note, spending_proof);
let mut sink = Sink::new(&mut bytes[..]);

// return new state
ContractState::from_canon(&slf).encode(&mut sink);
// return result
ReturnValue::from_canon(&exec_res).encode(&mut sink);
ReturnValue::from_canon(&true).encode(&mut sink);
Ok(())
}
ops::EXTEND_BID => {
// Read host-sent args
let sig = Signature::decode(&mut source)?;
let pk = PublicKey::decode(&mut source)?;
let exec_res = slf.extend_bid(sig, pk);
slf.extend_bid(sig, pk);
let mut sink = Sink::new(&mut bytes[..]);

// return new state
ContractState::from_canon(&slf).encode(&mut sink);
// return result
ReturnValue::from_canon(&exec_res).encode(&mut sink);
ReturnValue::from_canon(&true).encode(&mut sink);
Ok(())
}
_ => panic!("Unimplemented OP"),
Expand Down
163 changes: 67 additions & 96 deletions contracts/bid/src/hosted/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use core::ops::DerefMut;
use dusk_abi::Transaction;
use dusk_blindbid::Bid;
use dusk_bls12_381::BlsScalar;
use dusk_pki::{Ownable, PublicKey, StealthAddress};
use dusk_jubjub::JubJubAffine;
use dusk_pki::{Ownable, PublicKey, PublicSpendKey, StealthAddress};
use dusk_schnorr::Signature;
use microkelvin::Nth;
use phoenix_core::{Message, Note};
Expand All @@ -36,17 +37,14 @@ impl Contract {
stealth_address: StealthAddress,
correctness_proof: Vec<u8>,
spending_proof: Vec<u8>,
) -> bool {
// Setup sucess var to true
let mut success = true;

) {
// Verify proof of Correctness of the Bid.
if !rusk_abi::verify_proof(
correctness_proof,
crate::BID_CORRECTNESS_VD.to_vec(),
alloc::vec![(message.value_commitment()).into()],
) {
return false;
panic!("Failed to verify BidCorrectness proof")
}

// Obtain the current block_height.
Expand All @@ -72,25 +70,25 @@ impl Contract {
// tree
.get(*bid.stealth_address().pk_r())
.unwrap()
.is_none()
.is_some()
{
// Append Bid to the tree and obtain the position of it.
if let Ok(idx) = self
.tree_mut()
.push(BidLeaf::new(bid, Expiration(expiration)))
{
// Link the One-time PK to the idx in the Map
// Since we checked on the `get` call that the value was not
// inside, there's no need to check that this
// returns `Ok(None)`. So we just unwrap
// the `Result` and keep the `Option` untouched.
self.key_idx_map_mut()
.insert(*bid.stealth_address().pk_r(), idx as usize)
.unwrap();
}
} else {
return false;
};
panic!("Entry already found in the map for this Key. You can't bid twice with the same key")
}

// Append Bid to the tree and obtain the position of it.
if let Ok(idx) = self
.tree_mut()
.push(BidLeaf::new(bid, Expiration(expiration)))
{
// Link the One-time PK to the idx in the Map
// Since we checked on the `get` call that the value was not
// inside, there's no need to check that this
// returns `Ok(None)`. So we just unwrap
// the `Result` and keep the `Option` untouched.
self.key_idx_map_mut()
.insert(*bid.stealth_address().pk_r(), idx as usize)
.unwrap();
}

// Inter-contract call to lock bidder's funds in the Bid contract.
let call = Call::send_to_contract_obfuscated(
Expand All @@ -103,8 +101,6 @@ impl Contract {
let call = Transaction::from_canon(&call);
dusk_abi::transact_raw(self, &rusk_abi::transfer_contract(), &call)
.expect("Failed to send dusk to Bid contract");

true
}

// TODO: Check wether we allow to extend long-time expired Bids.
Expand All @@ -114,29 +110,20 @@ impl Contract {
/// time for his/her `Bid`. That means, remain longer in the Bidding
/// consensus process with the same `Bid` and therefore the same
/// One-time identity.
pub fn extend_bid(&mut self, sig: Signature, pk: PublicKey) -> bool {
// Setup success to true
let mut success = true;
pub fn extend_bid(&mut self, sig: Signature, pk: PublicKey) {
// Check wether there's an entry on the map for the pk.
let idx = match self.key_idx_map().get(pk) {
// If no entries are found for this PK it's just an err since there
// are no bids related to this PK to be extended.
Ok(None) => {
success = false;
usize::MAX
panic!("Key not found on the map");
}
Ok(Some(idx)) => *idx as usize,
Err(_) => {
success = false;
usize::MAX
panic!("Key not found on the map");
}
};

// In case there was an error, we simply return
if !success && idx == usize::MAX {
return false;
}

// Verify the signature by getting `t_e` from the Bid and calling the
// VERIFY_SIG host fn.
// Fetch the bid object from the tree getting a &mut to it.
Expand All @@ -145,7 +132,7 @@ impl Contract {
{
branch
} else {
return false;
panic!("Could not retrieve a mutable branch of the BidTree");
};
let bid: &mut BidLeaf = branch_mut.deref_mut();

Expand All @@ -163,14 +150,13 @@ impl Contract {
pk,
BlsScalar::from(bid_expiration),
) {
return false;
panic!("Failed to verify the Extend Signature");
}

// Assuming now that the result of the verification is true, we now
// should update the expiration of the Bid by `VALIDITY_PERIOD`.
bid.bid_mut().extend_expiration(VALIDITY_PERIOD);
bid.expiration_mut().0 += VALIDITY_PERIOD;
success
}

/// This function allows to the contract caller to withdraw it's `Bid` and
Expand All @@ -189,77 +175,62 @@ impl Contract {
pk: PublicKey,
note: Note,
spend_proof: Vec<u8>,
) -> bool {
// Setup success to true
let mut success = true;
) {
// Check wether there's an entry on the map for the pk.
let idx = match self.key_idx_map().get(pk) {
// If no entries are found for this PK it's just an err since there
// are no bids related to this PK to be extended.
Ok(None) => {
success = false;
usize::MAX
}
Ok(Some(idx)) => *idx as usize,
Err(_) => {
success = false;
usize::MAX
_ => {
panic!("Key not found on the map");
}
};

// In case there was an error, we simply return
if !success && idx == usize::MAX {
return false;
}

// Fetch bid info from the tree. Note that we can safely unwrap here due
// to the checks done previously while getting the idx from the map.
let bid = if let Ok(Some(bid)) = self.tree().get(idx as u64) {
bid
} else {
return false;
panic!("Failed to fetch the Bid from the tree at ids: {:?}", idx)
};

if *bid.bid().expiration() < dusk_abi::block_height() {
// If we arrived here, the bid is elegible for withdrawal.
// Now we need to check wether the signature is correct.
// Verify schnorr sig.
if !rusk_abi::verify_schnorr_sign(
sig,
pk,
BlsScalar::from(*bid.bid().expiration()),
) {
return false;
};

// Withdraw from Obfuscated call to retire the funds of the bidder.
let call = Call::withdraw_from_obfuscated(
*bid.bid().message(),
*bid.bid().stealth_address(),
note,
note.value_commitment().into(),
spend_proof,
);
if *bid.bid().expiration() >= dusk_abi::block_height() {
panic!("Bid::Expiration >= actual block_height")
}
// If we arrived here, the bid is elegible for withdrawal.
// Now we need to check wether the signature is correct.
// Verify schnorr sig.
if !rusk_abi::verify_schnorr_sign(
sig,
pk,
BlsScalar::from(*bid.bid().expiration()),
) {
panic!("Failed to verify the Withdrawal Signature");
};

let call = Transaction::from_canon(&call);
dusk_abi::transact_raw(self, &rusk_abi::transfer_contract(), &call)
.expect("Failed to withdraw dusk from the Bid contract");
// Withdraw from Obfuscated call to retire the funds of the bidder.
let call = Call::withdraw_from_obfuscated(
*bid.bid().message(),
*bid.bid().stealth_address(),
note,
spend_proof,
);

// If the inter-contract call succeeds, we need to clean the
// tree & map. Note that if we clean the entry
// corresponding to this `PublicKey` from the
// map there will be no need to do so from the tree. Since the
// rest of the functions rely on the map to gain
// access to the bid that is inside of the tree.
self.key_idx_map_mut()
.remove(pk)
.expect("Canon Store error happened.");
// TODO: Zeroize in the tree the leaf that corresponds to the idx
// linked to `pk` in the map.
// See: https://github.com/dusk-network/rusk/issues/164
true
} else {
false
}
let call = Transaction::from_canon(&call);
dusk_abi::transact_raw(self, &rusk_abi::transfer_contract(), &call)
.expect("Failed to withdraw dusk from the Bid contract");

// If the inter-contract call succeeds, we need to clean the
// tree & map. Note that if we clean the entry
// corresponding to this `PublicKey` from the
// map there will be no need to do so from the tree. Since the
// rest of the functions rely on the map to gain
// access to the bid that is inside of the tree.
self.key_idx_map_mut()
.remove(pk)
.expect("Canon Store error happened.");
// TODO: Zeroize in the tree the leaf that corresponds to the idx
// linked to `pk` in the map.
// See: https://github.com/dusk-network/rusk/issues/164
}
}
Loading

0 comments on commit a472114

Please sign in to comment.