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
use ceres_runtime::{Error, Metadata, Result, Runtime};
use ceres_std::BTreeMap;
use etc::{Etc, FileSystem, Meta};
use sled::Db;
use std::{cell::RefCell, fs, path::PathBuf, process, rc::Rc};
#[derive(Clone)]
pub struct Storage(pub Db);
impl Storage {
fn quit() {
println!(
"The following required arguments were not provided: \n\t\t\
<*.contract | name | code-hash>"
);
process::exit(1);
}
pub fn new() -> crate::Result<Self> {
let etc =
Etc::new(&dirs::home_dir().ok_or(crate::Error::Custom("Could not find home dir"))?)?;
let storage = Storage(sled::open(etc.open(".ceres/contracts")?.real_path()?)?);
Ok(storage)
}
pub fn rt(&mut self, contract: &str) -> crate::Result<Runtime> {
let if_path = PathBuf::from(contract);
let storage = Rc::new(RefCell::new(self.clone()));
Ok(if if_path.exists() {
let source = fs::read(if_path)?;
let rt = Runtime::from_contract_and_storage(&source, storage)?;
self.0.insert(
&rt.metadata.contract.name,
bincode::serialize(&rt.metadata.clone())?,
)?;
rt
} else if let Ok(Some(contract)) = if contract.is_empty() {
let mut recent = None;
for c in self.0.iter() {
let (k, v) = c?;
if k.len() != 32 {
recent = Some(Ok(Some(v)));
break;
}
}
if let Some(r) = recent {
r
} else {
return Err(crate::Error::ParseContractFailed(
"Get recent contract failed".to_string(),
));
}
} else {
self.0.get(contract.as_bytes())
} {
Runtime::from_metadata_and_storage(
bincode::deserialize::<Metadata>(&contract)?,
storage,
)?
} else {
Self::quit();
return Err(crate::Error::ParseContractFailed(contract.to_string()));
})
}
}
impl ceres_runtime::Storage for Storage {
fn set(&mut self, code_hash: [u8; 32], data: BTreeMap<[u8; 32], Vec<u8>>) -> Result<()> {
self.0
.insert(
&code_hash,
bincode::serialize(&data).map_err(|_| Error::Custom {
err: "Serialize failed",
})?,
)
.map_err(|_| Error::InsertContractFailed)?;
Ok(())
}
fn get(&self, code_hash: [u8; 32]) -> Option<BTreeMap<[u8; 32], Vec<u8>>> {
bincode::deserialize(&self.0.get(&code_hash).ok()??).ok()
}
fn new_state(&self) -> BTreeMap<[u8; 32], Vec<u8>> {
BTreeMap::new()
}
}