1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
use std::error::Error;

use crate::account::account::Account;
use crate::account::node_ref::NodeRef;
use crate::account::state_node::StateNode;
use crate::serialization::state::Account as ProtoAccount;
use crate::serialization::state::NodeRef as ProtoNodeRef;
use crate::serialization::state::StateNode as ProtoStateNode;
use crate::serialization::state::{DBState as ProtoDBState, DBState_oneof_state};
use crate::traits::{Decode, Encode, Exception, Proto};
use protobuf::Message as ProtoMessage;
use protobuf::RepeatedField;

#[derive(Clone, Debug, PartialEq)]
pub struct DBState {
    pub account: Option<Account>,
    pub node: Option<StateNode>,
    pub ref_count: u32,
}

impl DBState {
    pub fn new(account: Option<Account>, node: Option<StateNode>, ref_count: u32) -> DBState {
        DBState {
            account: account,
            node: node,
            ref_count: ref_count,
        }
    }
}

impl Decode for DBState {
    fn decode(buffer: &[u8]) -> Result<DBState, Box<Error>> {
        let mut proto_db_state = ProtoDBState::new();
        proto_db_state.merge_from_bytes(buffer)?;
        let mut db_state = DBState::new(None, None, 0);
        let state = match proto_db_state.state {
            Some(state_node) => state_node,
            None => return Err(Box::new(Exception::new("ProtoDBState has no state node"))),
        };

        match state {
            DBState_oneof_state::account(data_acc) => {
                db_state.account = Some(Account {
                    balance: data_acc.balance,
                    nonce: data_acc.nonce,
                });
            }
            DBState_oneof_state::node(data_node) => {
                let mut refs: Vec<NodeRef> = vec![];
                for proto_node_ref in data_node.nodeRefs.into_iter() {
                    let r = NodeRef::new(&proto_node_ref.address, &proto_node_ref.child);
                    refs.push(r);
                }
                db_state.node = Some(StateNode::new(refs));
            }
        }
        db_state.ref_count = proto_db_state.refCount;

        Ok(db_state)
    }
}

impl Proto for DBState {
    type ProtoType = ProtoDBState;
    fn to_proto(&self) -> Result<Self::ProtoType, Box<Error>> {
        let mut data = Self::ProtoType::new();
        match &self.account {
            Some(account) => {
                let mut proto_account = ProtoAccount::new();
                proto_account.set_balance(account.balance);
                proto_account.set_nonce(account.nonce);
                data.set_account(proto_account);
            }
            None => (),
        }

        match &self.node {
            Some(node) => {
                let mut proto_state_node = ProtoStateNode::new();
                let mut proto_refs: Vec<ProtoNodeRef> = Vec::with_capacity(node.node_refs.len());
                for tmp in &node.node_refs {
                    proto_refs.push(tmp.1.to_proto().unwrap());
                }
                let refs = RepeatedField::from(proto_refs);
                proto_state_node.set_nodeRefs(refs);
                data.set_node(proto_state_node);
            }
            None => (),
        }

        data.refCount = self.ref_count;

        Ok(data)
    }

    fn from_proto(_prototype: &Self::ProtoType) -> Result<Self, Box<Error>> {
        unimplemented!()
    }
}

impl Encode for DBState {
    fn encode(&self) -> Result<Vec<u8>, Box<Error>> {
        let proto_db_state = self.to_proto()?;
        Ok(proto_db_state.write_to_bytes()?)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_makes_a_dbstate() {
        let account = Account::new(10, 20);
        let dbstate = DBState::new(Some(account.clone()), None, 0);
        assert_eq!(dbstate.account, Some(account.clone()));
    }

    #[test]
    fn it_encodes_like_javascript_for_non_zero() {
        let addr_slice = vec![109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let child = vec![
            137, 28, 167, 193, 135, 226, 96, 56, 197, 123, 221, 237, 249, 5, 134, 194, 38, 184,
            100, 131, 41, 152, 47, 186, 185, 70, 18, 162, 105, 115, 14, 42,
        ];
        let state_node = StateNode::new(vec![NodeRef::new(&addr_slice, &child)]);
        let dbstate: DBState = DBState::new(None, Some(state_node), 1);
        let encoding = dbstate.encode().unwrap();
        let javascript_encoding = vec![
            24, 1, 18, 58, 10, 56, 10, 20, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 18, 32, 137, 28, 167, 193, 135, 226, 96, 56, 197, 123, 221, 237, 249, 5, 134,
            194, 38, 184, 100, 131, 41, 152, 47, 186, 185, 70, 18, 162, 105, 115, 14, 42,
        ];
        let decoding = DBState::decode(&encoding).unwrap();
        assert_eq!(encoding, javascript_encoding);
        assert_eq!(decoding.account, dbstate.account);
        assert_eq!(decoding.node, dbstate.node);
        assert_eq!(decoding.ref_count, dbstate.ref_count);
    }

    #[test]
    fn it_encodes_like_javascript_for_zero() {
        let addr_slice = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let child = vec![
            0, 28, 0, 193, 0, 226, 0, 56, 0, 123, 0, 237, 0, 5, 0, 194, 0, 184, 0, 131, 0, 152, 0,
            186, 0, 70, 0, 162, 0, 115, 0, 42,
        ];
        let state_node = StateNode::new(vec![NodeRef::new(&addr_slice, &child)]);
        let dbstate: DBState = DBState::new(None, Some(state_node), 0);
        let encoding = dbstate.encode().unwrap();
        let javascript_encoding = vec![
            24, 0, 18, 58, 10, 56, 10, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 18, 32, 0, 28, 0, 193, 0, 226, 0, 56, 0, 123, 0, 237, 0, 5, 0, 194, 0, 184, 0, 131,
            0, 152, 0, 186, 0, 70, 0, 162, 0, 115, 0, 42,
        ];
        let decoding = DBState::decode(&encoding).unwrap();
        assert_eq!(encoding, javascript_encoding);
        assert_eq!(decoding.account, dbstate.account);
        assert_eq!(decoding.node, dbstate.node);
        assert_eq!(decoding.ref_count, dbstate.ref_count);
    }
}