From d3ec1c79d68807d820c406f9172eb03fab00bd89 Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Mon, 15 Jul 2019 23:16:26 +0000 Subject: [PATCH] Random cards generation --- node/README.md | 14 +++---- node/runtime/src/cards.rs | 72 ++++++++++++++++++++++++++++++++--- node/runtime/src/naive_rsa.rs | 6 +-- node/runtime/src/poker.rs | 20 +++++++--- 4 files changed, 91 insertions(+), 21 deletions(-) diff --git a/node/README.md b/node/README.md index be1886d..903dbb7 100644 --- a/node/README.md +++ b/node/README.md @@ -1,11 +1,5 @@ # Blockchain Poker Node -After building, run `./heads-up.sh` for running two nodes, one for Alice and one for Bob. - -You can check status of launched processes with `./status.sh`. - -# Building - Install Rust: ```bash @@ -21,11 +15,15 @@ Install required tools: Build the WebAssembly binary: ```bash -./scripts/build.sh +./scripts/build.sh --release ``` Build all native code: ```bash -cargo build +cargo build --release ``` + +# Tests + +You can run tests with `cargo test --all` diff --git a/node/runtime/src/cards.rs b/node/runtime/src/cards.rs index a9945ee..3f5731f 100644 --- a/node/runtime/src/cards.rs +++ b/node/runtime/src/cards.rs @@ -15,18 +15,80 @@ pub const CLUBS: Suit = 3; pub const DIAMONDS: Suit = 4; pub const SPADES: Suit = 1; +#[derive(PartialEq, Eq, Debug)] pub struct Card { pub nominal: Nominal, - pub suit: Nominal + pub suit: Suit +} + +impl Card { + pub fn validate(&self) -> bool { + debug_assert!(self.nominal >= 1 && self.nominal <= 13); + debug_assert!(self.suit >= 1 && self.suit <= 4); + + self.nominal >= 1 && self.nominal <= 13 + && self.suit >= 1 && self.suit <= 4 + } +} + +pub fn hearts(n: Nominal) -> Card { + Card { nominal: n, suit: HEARTS } +} + +pub fn clubs(n: Nominal) -> Card { + Card { nominal: n, suit: CLUBS } +} + +pub fn diamonds(n: Nominal) -> Card { + Card { nominal: n, suit: DIAMONDS } +} + +pub fn spades(n: Nominal) -> Card { + Card { nominal: n, suit: SPADES } } pub fn encode(cards: &[Card]) -> Vec { cards.iter() - .map(|c| { - debug_assert!(c.nominal >= 1 && c.nominal <= 13); - debug_assert!(c.suit >= 1 && c.suit <= 4); - vec![c.nominal, c.suit] + .map(|card| { + card.validate(); + vec![card.nominal, card.suit] }) .flatten() .collect() +} + +//a bit unfair random generation, see the test +pub fn from_random(bytes: &[u8]) -> Card { + let card = Card { + nominal: bytes[0] % 13 + 1, + suit: bytes[1] % 4 + 1, + }; + + card.validate(); + card +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn generate_from_random() { + assert!(from_random(&[1, 0]) == spades(2)); + assert!(from_random(&[14, 0]) == spades(2)); + assert!(from_random(&[142, 6]) == clubs(K)); + + assert!(from_random(&[0, 7]) == diamonds(A)); + assert!(from_random(&[247, 7]) == diamonds(A)); + assert!(from_random(&[248, 7]) == diamonds(2)); + assert!(from_random(&[255, 7]) == diamonds(9)); + //this means that 10, J, Q, K are less frequent + + assert!(from_random(&[255, 0]) == spades(9)); + assert!(from_random(&[255, 252]) == spades(9)); + assert!(from_random(&[255, 253]) == hearts(9)); + assert!(from_random(&[255, 254]) == clubs(9)); + assert!(from_random(&[255, 255]) == diamonds(9)); + //for suits, it is fair + } } \ No newline at end of file diff --git a/node/runtime/src/naive_rsa.rs b/node/runtime/src/naive_rsa.rs index 71978f5..e22cd2d 100644 --- a/node/runtime/src/naive_rsa.rs +++ b/node/runtime/src/naive_rsa.rs @@ -69,11 +69,11 @@ mod tests { let exponent: U256 = U256::from_little_endian(privkey); generic_crypter(data, pubkey, exponent) .map(|mut bytes: Vec| { - let mut end = bytes.len() - 1; - while end >= 0 && bytes[end] == 0 { + let mut end = bytes.len() as isize - 1; + while end >= 0 && bytes[end as usize] == 0 { end -= 1; } - bytes.truncate(end + 1); + bytes.truncate((end + 1) as usize); bytes }) } diff --git a/node/runtime/src/poker.rs b/node/runtime/src/poker.rs index aedccc0..4a6226a 100644 --- a/node/runtime/src/poker.rs +++ b/node/runtime/src/poker.rs @@ -8,7 +8,10 @@ use rstd::prelude::*; use core::debug_assert; use runtime_io; -use crate::cards::*; +use runtime_primitives::traits::Hash; +use parity_codec::Encode; + +use crate::cards; use crate::naive_rsa::*; pub trait Trait: system::Trait + balances::Trait { @@ -66,12 +69,19 @@ decl_module! { runtime_io::print("Dealing cards for a player"); - let card1 = Card { nominal: A, suit: SPADES }; - let card2 = Card { nominal: 10, suit: CLUBS }; + //this is fake random for my proof-of-concept + //in future, it has to be replaced with off-chain random generation + //also it probably can be workarounded with sendind a nonce from the player + let random_bytes: Vec = (>::random_seed(), &who, &key) + .using_encoded(::Hashing::hash) + .using_encoded(|x| x.to_vec()); //32 bytes + + let card1 = cards::from_random(&random_bytes[0..2]); + let card2 = cards::from_random(&random_bytes[2..4]); - let cards = encode(&vec![card1, card2][..]); + let cards = cards::encode(&vec![card1, card2][..]); - match encrypt(&cards[..],&key[..]) { + match encrypt(&cards[..], &key[..]) { Ok(cards) => { >::insert(who, cards); Ok(())