fedimint_ln_server/
db.rs

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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
use fedimint_core::encoding::{Decodable, Encodable};
use fedimint_core::secp256k1::PublicKey;
use fedimint_core::{impl_db_lookup, impl_db_record, Amount, OutPoint, PeerId};
use fedimint_ln_common::contracts::incoming::IncomingContractOffer;
use fedimint_ln_common::contracts::{
    ContractId, FundedContract, IdentifiableContract, PreimageDecryptionShare,
};
use serde::Serialize;
use strum_macros::EnumIter;

use crate::{ContractAccount, LightningGatewayRegistration, LightningOutputOutcomeV0};

#[repr(u8)]
#[derive(Clone, EnumIter, Debug)]
pub enum DbKeyPrefix {
    Contract = 0x40,
    Offer = 0x41,
    ProposeDecryptionShare = 0x42,
    AgreedDecryptionShare = 0x43,
    ContractUpdate = 0x44,
    LightningGateway = 0x45,
    BlockCountVote = 0x46,
    EncryptedPreimageIndex = 0x47,
    LightningAuditItem = 0x48,
}

impl std::fmt::Display for DbKeyPrefix {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{self:?}")
    }
}

#[derive(Debug, Clone, Copy, Encodable, Decodable, Serialize)]
pub struct ContractKey(pub ContractId);

#[derive(Debug, Clone, Copy, Encodable, Decodable)]
pub struct ContractKeyPrefix;

impl_db_record!(
    key = ContractKey,
    value = ContractAccount,
    db_prefix = DbKeyPrefix::Contract,
    notify_on_modify = true,
);
impl_db_lookup!(key = ContractKey, query_prefix = ContractKeyPrefix);

#[derive(Debug, Encodable, Decodable, Serialize)]
pub struct ContractUpdateKey(pub OutPoint);

#[derive(Debug, Clone, Copy, Encodable, Decodable)]
pub struct ContractUpdateKeyPrefix;

impl_db_record!(
    key = ContractUpdateKey,
    value = LightningOutputOutcomeV0,
    db_prefix = DbKeyPrefix::ContractUpdate,
);
impl_db_lookup!(
    key = ContractUpdateKey,
    query_prefix = ContractUpdateKeyPrefix
);

/// We keep a separate mapping of incoming and outgoing `ContractId`s to
/// `Amount`s, which allows us to quickly audit the total liabilities in the
/// Lightning module.
///
/// This differs from `MintAuditItemKey`s, since it doesn't include an aggregate
/// *Total key. The motivation for not including the aggregate key is how the
/// Amount associated to the contract mutates in the LN module. When a contract
/// reaches a terminal state, the associated amount updates to 0. The additional
/// complexity to update both the individual incoming/outgoing contract audit
/// keys along with the aggregate audit key is not necessary.
///
/// In contrast to the mint module, the total number of LN audit keys with a
/// non-zero amount will not grow linearly, so querying the LN audit keys with a
/// non-zero amount should remain quick.
#[derive(Debug, Clone, Encodable, Decodable, Serialize, PartialEq)]
pub enum LightningAuditItemKey {
    Incoming(ContractId),
    Outgoing(ContractId),
}

impl LightningAuditItemKey {
    pub fn from_funded_contract(contract: &FundedContract) -> Self {
        match contract {
            FundedContract::Outgoing(outgoing) => {
                LightningAuditItemKey::Outgoing(outgoing.contract_id())
            }
            FundedContract::Incoming(incoming) => {
                LightningAuditItemKey::Incoming(incoming.contract.contract_id())
            }
        }
    }
}

#[derive(Debug, Encodable, Decodable)]
pub struct LightningAuditItemKeyPrefix;

impl_db_record!(
    key = LightningAuditItemKey,
    value = Amount,
    db_prefix = DbKeyPrefix::LightningAuditItem,
);
impl_db_lookup!(
    key = LightningAuditItemKey,
    query_prefix = LightningAuditItemKeyPrefix
);

/// We save the hash of the encrypted preimage from each accepted offer so that
/// we can make sure that no preimage is used twice.
#[derive(Debug, Encodable, Decodable, Serialize)]
pub struct EncryptedPreimageIndexKey(pub bitcoin_hashes::sha256::Hash);

#[derive(Debug, Encodable, Decodable, Serialize)]
pub struct EncryptedPreimageIndexKeyPrefix;

impl_db_record!(
    key = EncryptedPreimageIndexKey,
    value = (),
    db_prefix = DbKeyPrefix::EncryptedPreimageIndex,
);
impl_db_lookup!(
    key = EncryptedPreimageIndexKey,
    query_prefix = EncryptedPreimageIndexKeyPrefix
);

#[derive(Debug, Encodable, Decodable, Serialize)]
pub struct OfferKey(pub bitcoin_hashes::sha256::Hash);

#[derive(Debug, Encodable, Decodable)]
pub struct OfferKeyPrefix;

impl_db_record!(
    key = OfferKey,
    value = IncomingContractOffer,
    db_prefix = DbKeyPrefix::Offer,
    notify_on_modify = true,
);
impl_db_lookup!(key = OfferKey, query_prefix = OfferKeyPrefix);

// TODO: remove redundancy
#[derive(Debug, Encodable, Decodable, Serialize)]
pub struct ProposeDecryptionShareKey(pub ContractId);

/// Our preimage decryption shares that still need to be broadcasted
#[derive(Debug, Encodable)]
pub struct ProposeDecryptionShareKeyPrefix;

impl_db_record!(
    key = ProposeDecryptionShareKey,
    value = PreimageDecryptionShare,
    db_prefix = DbKeyPrefix::ProposeDecryptionShare,
);
impl_db_lookup!(
    key = ProposeDecryptionShareKey,
    query_prefix = ProposeDecryptionShareKeyPrefix
);

/// Preimage decryption shares we received
#[derive(Debug, Encodable, Decodable, Serialize)]
pub struct AgreedDecryptionShareKey(pub ContractId, pub PeerId);

/// Preimage decryption shares we received
#[derive(Debug, Encodable)]
pub struct AgreedDecryptionShareKeyPrefix;

#[derive(Debug, Encodable)]
pub struct AgreedDecryptionShareContractIdPrefix(pub ContractId);

impl_db_record!(
    key = AgreedDecryptionShareKey,
    value = PreimageDecryptionShare,
    db_prefix = DbKeyPrefix::AgreedDecryptionShare,
);
impl_db_lookup!(
    key = AgreedDecryptionShareKey,
    query_prefix = AgreedDecryptionShareKeyPrefix,
    query_prefix = AgreedDecryptionShareContractIdPrefix
);

#[derive(Debug, Encodable, Decodable, Serialize)]
pub struct LightningGatewayKey(pub PublicKey);

#[derive(Debug, Encodable, Decodable)]
pub struct LightningGatewayKeyPrefix;

impl_db_record!(
    key = LightningGatewayKey,
    value = LightningGatewayRegistration,
    db_prefix = DbKeyPrefix::LightningGateway,
);
impl_db_lookup!(
    key = LightningGatewayKey,
    query_prefix = LightningGatewayKeyPrefix
);

#[derive(Debug, Encodable, Decodable, Serialize)]
pub struct BlockCountVoteKey(pub PeerId);

#[derive(Clone, Debug, Encodable, Decodable)]
pub struct BlockCountVotePrefix;

impl_db_record!(
    key = BlockCountVoteKey,
    value = u64,
    db_prefix = DbKeyPrefix::BlockCountVote
);

impl_db_lookup!(key = BlockCountVoteKey, query_prefix = BlockCountVotePrefix);