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
mod ext;

use std::cell::RefCell;

use blockchain_traits::Blockchain as _;
use memchain::Memchain;
use oasis_types::Address;

const SEED_ADDR: Address = Address([0xffu8; 20]);
const BASE_GAS: u64 = 2100;

thread_local! {
    static MEMCHAIN: RefCell<Memchain<'static>> =
        RefCell::new(Memchain::new("testnet".to_string(), {
            let mut genesis_state = std::collections::HashMap::new();
            genesis_state.insert(SEED_ADDR, std::borrow::Cow::Owned(memchain::Account {
                balance: u128::max_value(),
                ..Default::default()
            }));
            genesis_state
        }, BASE_GAS));
    static NEXT_ADDR: RefCell<u64> = RefCell::new(0);
}

pub fn create_account(initial_balance: u128) -> Address {
    MEMCHAIN.with(|memchain| {
        let mut memchain = memchain.borrow_mut();

        let new_addr = NEXT_ADDR.with(|next_addr| {
            let mut next_addr = next_addr.borrow_mut();
            let mut addr = Address::default();
            let last_block = memchain.last_block();
            loop {
                let next_addr_bytes = next_addr.to_le_bytes();
                (addr.0)[..next_addr_bytes.len()].copy_from_slice(&next_addr_bytes);
                *next_addr += 1;
                if last_block.account_meta_at(&addr).is_none() {
                    break addr;
                }
            }
        });

        // TODO(#77)
        memchain.last_block_mut().transact(
            SEED_ADDR,
            new_addr,
            SEED_ADDR,
            initial_balance,
            &[], /* input */
            BASE_GAS,
            0, /* gas price */
        );

        new_addr
    })
}