nash_protocol/protocol/sign_states/blockchain/
mod.rs

1use super::super::place_order::blockchain::eth::FillOrder as FillOrderEth;
2use super::types::{ClientSignedState, ContractBalanceState, RecycledOrder, StateData};
3use crate::errors::{ProtocolError, Result};
4use crate::types::Blockchain;
5use crate::utils::{decode_hexstr, hash_eth_message, hash_neo_message};
6use nash_mpc::rust_bigint::BigInt;
7
8use super::super::signer::Signer;
9#[cfg(feature = "num_bigint")]
10use num_traits::Num;
11
12pub mod eth;
13pub mod neo;
14
15use eth::StateUpdatePayloadEth;
16
17/// Representation of state update payload. User signs this payload to
18/// confirm the current balance of their account and aggregate previous
19/// previous state changes that may have occurred via orders.
20pub enum StateUpdatePayload {
21    Eth(StateUpdatePayloadEth),
22}
23
24impl ContractBalanceState {
25    pub fn verify(&self) -> bool {
26        let state_data = &self.0;
27        match state_data.blockchain {
28            Blockchain::Ethereum => {
29                if let Ok(_state) = StateUpdatePayloadEth::from_hex(&state_data.payload) {
30                    // TODO: verify other properties here
31                    true
32                } else {
33                    println!("{:?}", state_data);
34                    false
35                }
36            }
37            // TODO:
38            Blockchain::NEO => true,
39            Blockchain::Bitcoin => true,
40        }
41    }
42}
43
44impl RecycledOrder {
45    pub fn verify(&self) -> bool {
46        let order_data = &self.0;
47        match order_data.blockchain {
48            Blockchain::Ethereum => {
49                if let Ok(_order) = FillOrderEth::from_hex(&order_data.payload) {
50                    // TODO: verify other properties here
51                    true
52                } else {
53                    false
54                }
55            }
56            Blockchain::NEO => true,
57            Blockchain::Bitcoin => true,
58        }
59    }
60}
61
62/// Sign off on a piece of state data such as an account balance or a recycled open order
63/// with a higher nonce. These states can be submitted by the ME to the settlement contract
64pub fn sign_state_data(state_data: &StateData, signer: &Signer) -> Result<ClientSignedState> {
65    let (message, hash) = match state_data.blockchain {
66        // Recycled orders should not be double hashed, but that is what we are doing here
67        Blockchain::Ethereum => { 
68            let message = state_data.payload.clone();
69            let hash = hash_eth_message(&decode_hexstr(&message)?);
70            (message, hash) 
71        },
72        Blockchain::NEO => { 
73            let message = state_data.payload.clone(); 
74            let hash = hash_neo_message(&decode_hexstr(&message)?);
75            (message, hash)
76        },
77        Blockchain::Bitcoin => { 
78            // Bug/inconsistency in ME, it wants hash instead of message
79            let message = state_data.payload_hash.clone();
80            let hash = BigInt::from_str_radix(&state_data.payload_hash, 16)
81            .map_err(|_| ProtocolError("Could not parse BTC hash as BigInt"))?;
82            (message, hash) 
83        },
84    };
85    let (sig, r, _pub) = signer.sign_child_key(hash, state_data.blockchain)?;
86    Ok(ClientSignedState::new(&message, state_data.blockchain, r, sig))
87}
88
89impl From<std::array::TryFromSliceError> for ProtocolError {
90    fn from(_error: std::array::TryFromSliceError) -> Self {
91        ProtocolError("Could not convert slice into correct number of bytes")
92    }
93}