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
#![allow(dead_code)]
#![allow(unused_imports)]
use crate::contractapi::contract::*;
use crate::{contract::ContractError, contractapi::contractdefn, dataapi::WireBuffer, blockchain::TransactionContext};
use lazy_static::lazy_static;
use log::{debug, info, trace, warn};
use std::collections::HashMap;
use std::sync::Mutex;
lazy_static! {
static ref CONTRACT_MGR: Mutex<ContractManager> = Mutex::new(ContractManager::new());
}
pub struct ContractManager {
contracts: HashMap<String, contractdefn::ContractDefn>,
}
impl ContractManager {
pub fn new() -> ContractManager {
ContractManager {
contracts: HashMap::new(),
}
}
fn register_contract_impl(self: &mut ContractManager, contract: Box<dyn Contract + Send>) {
let name = contract.name();
let contract_defn = contractdefn::ContractDefn::new(contract);
self.contracts.insert(name, contract_defn);
}
fn evaluate(
self: &mut ContractManager,
ctx: &TransactionContext,
contract_name: String,
tx: String,
args: &[Vec<u8>],
transient: &HashMap<String,Vec<u8>>,
) -> Result<WireBuffer, ContractError> {
debug!("contractmanager::evaluate {} {}", contract_name, tx);
match self.contracts.get(&contract_name) {
Some(defn) => {
defn.invoke(ctx, tx, args, transient)
}
None => {
warn!(
"Unable to find contract Failed {}.{},{:?}",
contract_name, tx, args
);
Err(ContractError::from(format!("Unable to find contract Failed {}:{}",contract_name, tx)))
}
}
}
pub fn register_contract(contract: Box<dyn Contract + Send>) {
CONTRACT_MGR
.lock()
.unwrap()
.register_contract_impl(contract);
}
pub fn route(
ctx: &TransactionContext,
tx: String,
args: &[Vec<u8>],
transient: &HashMap<String,Vec<u8>>,
) -> Result<WireBuffer, ContractError> {
trace!("contractmanager::route>>");
let namespace: String;
let fn_name: String;
match tx.find(':') {
None => {
namespace = "default".to_string();
fn_name = tx.clone();
}
Some(s) => {
namespace = tx[..s].to_string();
fn_name = tx[s + 1..].to_string();
}
}
if namespace.is_empty() {
return Err(ContractError::from(String::from("Emptry namespace, for default just give fn name")));
};
if fn_name.is_empty() {
return Err(ContractError::from(String::from("Empty function name")));
};
let r = match CONTRACT_MGR
.lock() {
Ok(mut ccm) => {
ccm.evaluate(ctx, namespace, fn_name, args, transient)
}
Err(poisoned) => {panic!("I've been poisoned")}
};
trace!("contractmanager::route<<");
r
}
}