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
use exonum::api::ServiceApiBuilder;
use exonum::blockchain::{
Schema as CoreSchema, Service, ServiceContext, Transaction, TransactionSet,
};
use exonum::crypto::Hash;
use exonum::messages::RawTransaction;
use exonum::storage::{Fork, Snapshot};
use serde_json::json;
use std::sync::{Arc, RwLock};
use std::collections::HashMap;
use crate::api;
use crate::blockchain::{BtcAnchoringSchema, Transactions};
use crate::btc::{Address, PrivateKey};
use crate::config::GlobalConfig;
use crate::handler::{SyncWithBtcRelayTask, UpdateAnchoringChainTask};
use crate::rpc::BtcRelay;
use crate::ResultEx;
pub const BTC_ANCHORING_SERVICE_ID: u16 = 3;
pub const BTC_ANCHORING_SERVICE_NAME: &str = "btc_anchoring";
pub(crate) type KeyPool = Arc<RwLock<HashMap<Address, PrivateKey>>>;
pub struct BtcAnchoringService {
global_config: GlobalConfig,
private_keys: KeyPool,
btc_relay: Option<Box<dyn BtcRelay>>,
}
impl ::std::fmt::Debug for BtcAnchoringService {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
f.debug_struct("BtcAnchoringService").finish()
}
}
impl BtcAnchoringService {
pub fn new(
global_config: GlobalConfig,
private_keys: KeyPool,
btc_relay: Option<Box<dyn BtcRelay>>,
) -> Self {
Self {
global_config,
private_keys,
btc_relay,
}
}
}
impl Service for BtcAnchoringService {
fn service_id(&self) -> u16 {
BTC_ANCHORING_SERVICE_ID
}
fn service_name(&self) -> &'static str {
BTC_ANCHORING_SERVICE_NAME
}
fn state_hash(&self, snapshot: &dyn Snapshot) -> Vec<Hash> {
BtcAnchoringSchema::new(snapshot).state_hash()
}
fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<dyn Transaction>, failure::Error> {
let tx = Transactions::tx_from_raw(raw)?;
Ok(tx.into())
}
fn initialize(&self, _fork: &mut Fork) -> serde_json::Value {
json!(self.global_config)
}
fn before_commit(&self, fork: &mut Fork) {
let block_header_hash = CoreSchema::new(&fork)
.block_hashes_by_height()
.last()
.expect("An attempt to invoke execute during the genesis block initialization.");
let mut schema = BtcAnchoringSchema::new(fork);
schema.anchored_blocks_mut().push(block_header_hash);
}
fn after_commit(&self, context: &ServiceContext) {
let keys = &self.private_keys.read().unwrap();
let task = UpdateAnchoringChainTask::new(context, keys);
task.run().log_error();
if let Some(ref relay) = self.btc_relay.as_ref() {
let task = SyncWithBtcRelayTask::new(context, relay.as_ref());
task.run().log_error();
}
}
fn wire_api(&self, builder: &mut ServiceApiBuilder) {
api::wire(builder);
}
}