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
use bitcoin::util::amount::CoinAmount;
use sapio::contract::*;
use sapio::*;
use sapio_base::Clause;
use schemars::*;
use serde::*;
use std::convert::TryInto;
use std::marker::PhantomData;
#[derive(JsonSchema, Deserialize, Default)]
pub struct CanBeginRecovery;
#[derive(JsonSchema, Deserialize, Default)]
pub struct CanFinishRecovery;
pub trait RecoveryState {}
impl RecoveryState for CanFinishRecovery {}
impl RecoveryState for CanBeginRecovery {}
#[derive(JsonSchema, Deserialize)]
pub struct FederatedPegIn<T: RecoveryState> {
keys: Vec<bitcoin::PublicKey>,
thresh_normal: usize,
keys_recovery: Vec<bitcoin::PublicKey>,
thresh_recovery: usize,
amount: CoinAmount,
#[serde(skip)]
_pd: PhantomData<T>,
}
pub trait StateDependentActions
where
Self: Sized,
{
guard! {
finish_recovery}
then! {
begin_recovery}
}
impl StateDependentActions for FederatedPegIn<CanBeginRecovery> {
then! {begin_recovery [Self::recovery_signed] |s, ctx| {
ctx.template().add_output(
s.amount.try_into()?,
&FederatedPegIn::<CanFinishRecovery> {
keys: s.keys.clone(),
thresh_normal: s.thresh_normal,
keys_recovery: s.keys_recovery.clone(),
thresh_recovery: s.thresh_recovery,
amount: s.amount,
_pd: PhantomData::default()
},
None
)?.into()
}}
}
impl StateDependentActions for FederatedPegIn<CanFinishRecovery> {
guard! {finish_recovery |s, ctx| {
Clause::And(vec![Clause::Older(4725 ), Clause::Threshold(s.thresh_recovery, s.keys_recovery.iter().cloned().map(Clause::Key).collect())])
}}
}
impl<T: RecoveryState> FederatedPegIn<T> {
guard! {recovery_signed |s, ctx| {
Clause::Threshold(s.thresh_recovery, s.keys_recovery.iter().cloned().map(Clause::Key).collect())
}}
guard! {normal_signed |s, ctx| {
Clause::Threshold(s.thresh_normal, s.keys.iter().cloned().map(Clause::Key).collect())
}}
}
impl<T: RecoveryState> Contract for FederatedPegIn<T>
where
FederatedPegIn<T>: StateDependentActions + 'static,
{
declare! {then, Self::begin_recovery}
declare! {finish, Self::normal_signed, Self::finish_recovery}
declare! {non updatable}
}
pub type PegIn = FederatedPegIn<CanBeginRecovery>;