Skip to content

Commit e99fdbd

Browse files
committed
Add simple tests
1 parent 78089a6 commit e99fdbd

File tree

3 files changed

+119
-6
lines changed

3 files changed

+119
-6
lines changed

vector-commitment/src/binary.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use accumulator::*;
55
use accumulator::witnesses;
66
use rstd::prelude::Vec;
7+
use runtime_io;
78

89
/// Commit a vector of bits(represented as bool array) to an accumulator. The second value of
910
/// the returned tuple is the product of the accumulated elements.

vector-commitment/src/lib.rs

Lines changed: 98 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use support::{decl_module, decl_storage, decl_event, ensure, dispatch::Result, StorageValue, traits::Get};
77
use system::ensure_signed;
88
use codec::{Encode, Decode};
9-
use accumulator::{U2048, Witness};
9+
use accumulator::*;
1010
pub mod binary;
1111
pub mod vc;
1212

@@ -34,7 +34,7 @@ pub trait Trait: system::Trait {
3434
decl_storage! {
3535
trait Store for Module<T: Trait> as StatelessAccounts {
3636
State get(get_state): U2048 = U2048::from(2); // Use 2 as an arbitrary generator with "unknown" order.
37-
WitnessData: Vec<(U2048, U2048)>;
37+
WitnessData get(get_witness_data): Vec<(U2048, U2048)>;
3838
NewKeyValuePairs: Vec<(u8, u8)>;
3939
}
4040
}
@@ -53,6 +53,8 @@ decl_module! {
5353
fn deposit_event() = default;
5454
const KeySpace: u8 = T::KeySpace::get();
5555

56+
/// Arbitrarily add a new key-value store to the accumulator.
57+
/// NOTE: The key must not exist initially.
5658
pub fn mint(origin, key: u8, amount: u8) -> Result {
5759
ensure_signed(origin)?;
5860
let (state, product) = vc::commit(State::get(), &[key as usize], &[amount]);
@@ -61,10 +63,15 @@ decl_module! {
6163
Ok(())
6264
}
6365

66+
/// Submit a transaction to the chain.
67+
/// NOTE: All transactions must be referenced from the same previous "state". In practice,
68+
/// this might be the state of the previous block for example. This is a workaround to
69+
/// prevent having to pass in the product of all of the elements in the accumulator.
6470
pub fn add_transaction(origin, transaction: Transaction, old_state: U2048) -> Result {
6571
ensure_signed(origin)?;
6672
// Get the opening of the sender
6773
let (pi_i_sender, pi_e_sender) = transaction.sender_opening;
74+
6875
// Verify that it is valid
6976
ensure!(vc::verify_at_key(old_state, State::get(), transaction.sender_key as usize,
7077
transaction.sender_balance, pi_i_sender, pi_e_sender), "Opening is invalid.");
@@ -88,9 +95,9 @@ decl_module! {
8895

8996
// Currently omitting non-membership proofs for simplicity
9097

91-
// Temporarily store the existing key-value pairs
92-
NewKeyValuePairs::append(&vec![(transaction.sender_key, transaction.sender_balance)]);
93-
NewKeyValuePairs::append(&vec![(transaction.receiver_key, transaction.receiver_balance)]);
98+
// Temporarily store the new key-value pairs
99+
NewKeyValuePairs::append(&vec![(transaction.sender_key, transaction.sender_balance-transaction.amount)]);
100+
NewKeyValuePairs::append(&vec![(transaction.receiver_key, transaction.receiver_balance+transaction.amount)]);
94101
Ok(())
95102
}
96103

@@ -99,6 +106,7 @@ decl_module! {
99106
let (state, product, proof) = accumulator::batch_delete(State::get(), &WitnessData::get());
100107
Self::deposit_event(Event::Deletion(state, product, proof));
101108

109+
// Get the integer representations of the new key-value pairs.
102110
let elems: Vec<U2048> = NewKeyValuePairs::get()
103111
.into_iter()
104112
.enumerate()
@@ -128,10 +136,11 @@ decl_module! {
128136
mod tests {
129137
use super::*;
130138

139+
use runtime_io::with_externalities;
131140
use primitives::{H256, Blake2Hasher};
132141
use support::{impl_outer_origin, assert_ok, parameter_types};
133142
use sr_primitives::{
134-
traits::{BlakeTwo256, IdentityLookup}, testing::Header, weights::Weight, Perbill,
143+
traits::{BlakeTwo256, IdentityLookup, OnFinalize}, testing::Header, weights::Weight, Perbill,
135144
};
136145

137146
impl_outer_origin! {
@@ -174,11 +183,94 @@ mod tests {
174183
type Event = ();
175184
type KeySpace = KeySpace;
176185
}
186+
177187
type StatelessAccounts = Module<Test>;
188+
type System = system::Module<Test>;
178189

179190
// This function basically just builds a genesis storage key/value store according to
180191
// our desired mockup.
181192
fn new_test_ext() -> runtime_io::TestExternalities<Blake2Hasher> {
182193
system::GenesisConfig::default().build_storage::<Test>().unwrap().into()
183194
}
195+
196+
#[test]
197+
fn test_mint() {
198+
with_externalities(&mut new_test_ext(), || {
199+
let key: u8 = 1;
200+
let value: u8 = 10;
201+
StatelessAccounts::mint(Origin::signed(1), key, value);
202+
203+
let (binary_vec, indices) = vc::convert_key_value(&[key as usize], &[value]);
204+
let (p_ones, _) = binary::get_bit_elems(&binary_vec, &indices);
205+
assert_eq!(StatelessAccounts::get_state(), subroutines::mod_exp(U2048::from(2), p_ones, U2048::from_dec_str(MODULUS).unwrap()));
206+
});
207+
}
208+
209+
#[test]
210+
fn test_transaction() {
211+
with_externalities(&mut new_test_ext(), || {
212+
let generator = StatelessAccounts::get_state();
213+
214+
// Define keys for alice and bob
215+
let alice_key: u8 = 12;
216+
let bob_key: u8 = 58;
217+
218+
// Define balances for alice and bob
219+
let alice_balance: u8 = 10;
220+
let bob_balance: u8 = 5;
221+
222+
// Mint tokens for each user
223+
StatelessAccounts::mint(Origin::signed(1), alice_key, alice_balance);
224+
StatelessAccounts::mint(Origin::signed(1), bob_key, bob_balance);
225+
226+
// Derive integer representations for manual testing
227+
let alice_elem = vc::get_key_value_elem(alice_key as usize, alice_balance); // This value would be received from the emitted event.
228+
let bob_elem = vc::get_key_value_elem(bob_key as usize, bob_balance); // This value would be received from the emitted event.
229+
let product = alice_elem * bob_elem;
230+
231+
// Get state after minting
232+
let state_after_mint = StatelessAccounts::get_state();
233+
234+
// Get openings for each user
235+
let (alice_pi_i, alice_pi_e) = vc::open_at_key(generator, product, alice_key as usize, alice_balance);
236+
let (bob_pi_i, bob_pi_e) = vc::open_at_key(generator, product, bob_key as usize, bob_balance);
237+
238+
// Construct transaction
239+
let transaction = Transaction {
240+
sender_key: alice_key,
241+
sender_balance: alice_balance,
242+
sender_elem: alice_elem,
243+
sender_opening: (alice_pi_i, alice_pi_e),
244+
receiver_key: bob_key,
245+
receiver_balance: bob_balance,
246+
receiver_elem: bob_elem,
247+
receiver_opening: (bob_pi_i, bob_pi_e),
248+
amount: 3,
249+
};
250+
251+
// Submit transaction
252+
StatelessAccounts::add_transaction(Origin::signed(1), transaction, generator);
253+
254+
// Manually get the state after deletion for manual testing
255+
let (state_after_del, _, _) = batch_delete(state_after_mint, &StatelessAccounts::get_witness_data());
256+
257+
// Finalize block
258+
StatelessAccounts::on_finalize(System::block_number());
259+
260+
// Get the new state
261+
let new_state = StatelessAccounts::get_state();
262+
263+
// Derive integer representations for alice and bob's new key-value stores
264+
let new_alice_elem = vc::get_key_value_elem(alice_key as usize, alice_balance-3); // This value would be received from the emitted event.
265+
let new_bob_elem = vc::get_key_value_elem(bob_key as usize, bob_balance+3); // This value would be received from the emitted event.
266+
267+
// Create openings with the new balances
268+
let (alice_pi_i_new, alice_pi_e_new) = vc::open_at_key(state_after_del, new_alice_elem*new_bob_elem, alice_key as usize, alice_balance-3);
269+
let (bob_pi_i_new, bob_pi_e_new) = vc::open_at_key(state_after_del, new_alice_elem*new_bob_elem, bob_key as usize, bob_balance+3);
270+
271+
// Verify that the openings are valid
272+
assert_eq!(vc::verify_at_key(state_after_del, new_state, alice_key as usize, alice_balance-3, alice_pi_i_new, alice_pi_e_new), true);
273+
assert_eq!(vc::verify_at_key(state_after_del, new_state, bob_key as usize, bob_balance+3, bob_pi_i_new, bob_pi_e_new), true);
274+
});
275+
}
184276
}

vector-commitment/src/vc.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ pub fn to_binary(elem: ValueType) -> Vec<bool> {
5555
return bv.iter().collect::<Vec<bool>>();
5656
}
5757

58+
/// Quick helper function that gets the product of the accumulated elements for a given
59+
/// key-value pair.
60+
pub fn get_key_value_elem(key: usize, value: ValueType) -> U2048 {
61+
let (binary_vec, indices) = convert_key_value(&[key], &[value]);
62+
let (elem, _) = binary::get_bit_elems(&binary_vec, &indices);
63+
return elem;
64+
}
65+
5866
#[cfg(test)]
5967
mod tests {
6068
use super::*;
@@ -107,4 +115,16 @@ mod tests {
107115
assert_eq!(verify_at_key(accumulator, new_accumulator, 1, 4, pi_i, pi_e), false);
108116
}
109117

118+
#[test]
119+
fn test_get_key_value_elem() {
120+
let (key, value): (usize, u8) = (0, 5);
121+
let elem = get_key_value_elem(key, value);
122+
123+
let bv = to_binary(value);
124+
let indices: Vec<usize> = (0..8).collect();
125+
let (state, _) = binary::commit(U2048::from(2), &bv, &indices);
126+
127+
assert_eq!(state, subroutines::mod_exp(U2048::from(2), elem, U2048::from_dec_str(MODULUS).unwrap()))
128+
}
129+
110130
}

0 commit comments

Comments
 (0)