@@ -8,13 +8,14 @@ use bincode::{Decode, Encode};
8
8
use protocol:: {
9
9
bitcoin:: { Amount , Block , BlockHash , OutPoint } ,
10
10
constants:: { ChainAnchor , ROLLOUT_BATCH_SIZE , ROLLOUT_BLOCK_INTERVAL } ,
11
- hasher:: { BidHash , KeyHasher , OutpointHash , SpaceHash } ,
12
- prepare:: PreparedTransaction ,
11
+ hasher:: { BidKey , KeyHasher , OutpointKey , SpaceKey } ,
12
+ prepare:: TxContext ,
13
13
sname:: NameLike ,
14
- validate:: { ErrorOut , MetaOutKind , TxInKind , TxOutKind , ValidatedTransaction , Validator } ,
14
+ validate:: { UpdateKind , TxChangeSet , Validator } ,
15
15
Covenant , FullSpaceOut , RevokeReason , SpaceOut ,
16
16
} ;
17
17
use serde:: { Deserialize , Serialize } ;
18
+ use wallet:: bitcoin:: Transaction ;
18
19
19
20
use crate :: {
20
21
source:: BitcoinRpcError ,
@@ -34,11 +35,11 @@ pub struct Node {
34
35
validator : Validator ,
35
36
}
36
37
37
- /// A block structure containing validated transactions
38
+ /// A block structure containing validated transaction metadata
38
39
/// relevant to the Spaces protocol
39
40
#[ derive( Clone , Serialize , Deserialize , Encode , Decode ) ]
40
- pub struct ValidatedBlock {
41
- tx_data : Vec < ValidatedTransaction > ,
41
+ pub struct BlockMeta {
42
+ tx_meta : Vec < TxChangeSet > ,
42
43
}
43
44
44
45
#[ derive( Debug ) ]
@@ -73,7 +74,7 @@ impl Node {
73
74
block_hash : BlockHash ,
74
75
block : Block ,
75
76
get_block_data : bool ,
76
- ) -> Result < Option < ValidatedBlock > > {
77
+ ) -> Result < Option < BlockMeta > > {
77
78
{
78
79
let tip = chain. state . tip . read ( ) . expect ( "read tip" ) ;
79
80
if tip. hash != block. header . prev_blockhash || tip. height + 1 != height {
@@ -85,7 +86,7 @@ impl Node {
85
86
}
86
87
}
87
88
88
- let mut block_data = ValidatedBlock { tx_data : vec ! [ ] } ;
89
+ let mut block_data = BlockMeta { tx_meta : vec ! [ ] } ;
89
90
90
91
if ( height - 1 ) % ROLLOUT_BLOCK_INTERVAL == 0 {
91
92
let batch = Self :: get_rollout_batch ( ROLLOUT_BATCH_SIZE , chain) ?;
@@ -94,155 +95,135 @@ impl Node {
94
95
. expect ( "expected a coinbase tx to be present in the block" )
95
96
. clone ( ) ;
96
97
97
- let validated = self . validator . rollout ( height, coinbase, batch) ;
98
+ let validated = self . validator . rollout ( height, & coinbase, batch) ;
98
99
if get_block_data {
99
- block_data. tx_data . push ( validated. clone ( ) ) ;
100
+ block_data. tx_meta . push ( validated. clone ( ) ) ;
100
101
}
101
102
102
- self . apply_tx ( & mut chain. state , validated) ;
103
+ self . apply_tx ( & mut chain. state , & coinbase , validated) ;
103
104
}
104
105
105
106
for tx in block. txdata {
106
107
let prepared_tx =
107
- { PreparedTransaction :: from_tx :: < LiveSnapshot , Sha256 > ( & mut chain. state , tx) ? } ;
108
+ { TxContext :: from_tx :: < LiveSnapshot , Sha256 > ( & mut chain. state , & tx) ? } ;
108
109
109
110
if let Some ( prepared_tx) = prepared_tx {
110
- let validated_tx = self . validator . process ( height, prepared_tx) ;
111
+ let validated_tx = self . validator . process ( height, & tx, prepared_tx) ;
112
+
111
113
if get_block_data {
112
- block_data. tx_data . push ( validated_tx. clone ( ) ) ;
114
+ block_data. tx_meta . push ( validated_tx. clone ( ) ) ;
113
115
}
114
- self . apply_tx ( & mut chain. state , validated_tx) ;
116
+ self . apply_tx ( & mut chain. state , & tx , validated_tx) ;
115
117
}
116
118
}
117
119
let mut tip = chain. state . tip . write ( ) . expect ( "write tip" ) ;
118
120
tip. height = height;
119
121
tip. hash = block_hash;
120
122
121
- if get_block_data && !block_data. tx_data . is_empty ( ) {
123
+ if get_block_data && !block_data. tx_meta . is_empty ( ) {
122
124
return Ok ( Some ( block_data) ) ;
123
125
}
124
126
Ok ( None )
125
127
}
126
128
127
- fn apply_tx ( & self , state : & mut LiveSnapshot , changeset : ValidatedTransaction ) {
129
+ fn apply_tx ( & self , state : & mut LiveSnapshot , tx : & Transaction , changeset : TxChangeSet ) {
128
130
// Remove spends
129
- for input in changeset. input {
130
- match input {
131
- TxInKind :: CoinIn ( _) => {
132
- // not relevant to spaces
133
- }
134
- TxInKind :: SpaceIn ( spacein) => {
135
- // remove spend
136
- let spend = OutpointHash :: from_outpoint :: < Sha256 > ( spacein. txin . previous_output ) ;
137
- state. remove ( spend) ;
138
- }
139
- }
131
+ for spend in changeset. spends . into_iter ( ) {
132
+ let previous = tx. input [ spend. n ] . previous_output ;
133
+ let spend = OutpointKey :: from_outpoint :: < Sha256 > ( previous) ;
134
+ state. remove ( spend) ;
140
135
}
141
136
142
137
// Apply outputs
143
- for ( index, output) in changeset. output . into_iter ( ) . enumerate ( ) {
144
- match output {
145
- TxOutKind :: CoinOut ( _) => {
146
- // not relevant to spaces
147
- }
148
- TxOutKind :: SpaceOut ( spaceout) => {
149
- if let Some ( space) = spaceout. space . as_ref ( ) {
150
- assert ! (
151
- !matches!( space. covenant, Covenant :: Bid { .. } ) ,
152
- "bid unexpected"
153
- ) ;
154
- }
155
- let outpoint = OutPoint {
156
- txid : changeset. txid ,
157
- vout : index as u32 ,
158
- } ;
159
-
160
- // Space => Outpoint
161
- if let Some ( space) = spaceout. space . as_ref ( ) {
162
- let space_key = SpaceHash :: from ( Sha256 :: hash ( space. name . to_bytes ( ) ) ) ;
163
- state. insert_space ( space_key, outpoint. into ( ) ) ;
164
- }
165
- // Outpoint => SpaceOut
166
- let outpoint_key = OutpointHash :: from_outpoint :: < Sha256 > ( outpoint) ;
167
- state. insert_spaceout ( outpoint_key, spaceout) ;
168
- }
138
+ for create in changeset. creates . into_iter ( ) {
139
+ if let Some ( space) = create. space . as_ref ( ) {
140
+ assert ! (
141
+ !matches!( space. covenant, Covenant :: Bid { .. } ) ,
142
+ "bid unexpected"
143
+ ) ;
144
+ }
145
+ let outpoint = OutPoint {
146
+ txid : changeset. txid ,
147
+ vout : create. n as u32 ,
148
+ } ;
149
+
150
+ // Space => Outpoint
151
+ if let Some ( space) = create. space . as_ref ( ) {
152
+ let space_key = SpaceKey :: from ( Sha256 :: hash ( space. name . to_bytes ( ) ) ) ;
153
+ state. insert_space ( space_key, outpoint. into ( ) ) ;
169
154
}
155
+ // Outpoint => SpaceOut
156
+ let outpoint_key = OutpointKey :: from_outpoint :: < Sha256 > ( outpoint) ;
157
+ state. insert_spaceout ( outpoint_key, create) ;
170
158
}
171
159
172
160
// Apply meta outputs
173
- for meta_output in changeset. meta_output {
174
- match meta_output {
175
- MetaOutKind :: ErrorOut ( errrout) => {
176
- match errrout {
177
- ErrorOut :: Reject ( _) => {
178
- // no state changes as it doesn't
179
- // modify any existing spaces
180
- }
181
- ErrorOut :: Revoke ( params) => {
182
- match params. reason {
183
- RevokeReason :: BidPsbt ( _)
184
- | RevokeReason :: PrematureClaim
185
- | RevokeReason :: BadSpend => {
186
- // Since these are caused by spends
187
- // Outpoint -> Spaceout mapping is already removed,
188
- let space = params. spaceout . spaceout . space . unwrap ( ) ;
189
- let base_hash = Sha256 :: hash ( space. name . to_bytes ( ) ) ;
190
-
191
- // Remove Space -> Outpoint
192
- let space_key = SpaceHash :: from ( base_hash) ;
193
- state. remove ( space_key) ;
194
-
195
- // Remove any bids from pre-auction pool
196
- match space. covenant {
197
- Covenant :: Bid {
198
- total_burned,
199
- claim_height,
200
- ..
201
- } => {
202
- if claim_height. is_none ( ) {
203
- let bid_key =
204
- BidHash :: from_bid ( total_burned, base_hash) ;
205
- state. remove ( bid_key) ;
206
- }
207
- }
208
- _ => { }
161
+ for update in changeset. updates {
162
+ match update. kind {
163
+ UpdateKind :: Revoke ( params) => {
164
+ match params {
165
+ RevokeReason :: BidPsbt ( _)
166
+ | RevokeReason :: PrematureClaim
167
+ | RevokeReason :: BadSpend => {
168
+ // Since these are caused by spends
169
+ // Outpoint -> Spaceout mapping is already removed,
170
+ let space = update. output . spaceout . space . unwrap ( ) ;
171
+ let base_hash = Sha256 :: hash ( space. name . to_bytes ( ) ) ;
172
+
173
+ // Remove Space -> Outpoint
174
+ let space_key = SpaceKey :: from ( base_hash) ;
175
+ state. remove ( space_key) ;
176
+
177
+ // Remove any bids from pre-auction pool
178
+ match space. covenant {
179
+ Covenant :: Bid {
180
+ total_burned,
181
+ claim_height,
182
+ ..
183
+ } => {
184
+ if claim_height. is_none ( ) {
185
+ let bid_key = BidKey :: from_bid ( total_burned, base_hash) ;
186
+ state. remove ( bid_key) ;
209
187
}
210
188
}
211
- RevokeReason :: Expired => {
212
- // Space => Outpoint mapping will be removed
213
- // since this type of revocation only happens when an
214
- // expired space is being re-opened for auction.
215
- // No bids here so only remove Outpoint -> Spaceout
216
- let hash = OutpointHash :: from_outpoint :: < Sha256 > (
217
- params. spaceout . outpoint ,
218
- ) ;
219
- state. remove ( hash) ;
220
- }
189
+ _ => { }
221
190
}
222
191
}
192
+ RevokeReason :: Expired => {
193
+ // Space => Outpoint mapping will be removed
194
+ // since this type of revocation only happens when an
195
+ // expired space is being re-opened for auction.
196
+ // No bids here so only remove Outpoint -> Spaceout
197
+ let hash =
198
+ OutpointKey :: from_outpoint :: < Sha256 > ( update. output . outpoint ( ) ) ;
199
+ state. remove ( hash) ;
200
+ }
223
201
}
224
202
}
225
- MetaOutKind :: RolloutOut ( rollout) => {
203
+ UpdateKind :: Rollout ( rollout) => {
226
204
let base_hash = Sha256 :: hash (
227
- rollout
205
+ update
206
+ . output
228
207
. spaceout
229
208
. space
230
209
. as_ref ( )
231
210
. expect ( "a space in rollout" )
232
211
. name
233
212
. to_bytes ( ) ,
234
213
) ;
235
- let bid_key = BidHash :: from_bid ( rollout. bid_value , base_hash) ;
214
+ let bid_key = BidKey :: from_bid ( rollout. priority , base_hash) ;
236
215
237
- let outpoint_key = OutpointHash :: from_outpoint :: < Sha256 > ( rollout. outpoint ) ;
216
+ let outpoint_key =
217
+ OutpointKey :: from_outpoint :: < Sha256 > ( update. output . outpoint ( ) ) ;
238
218
239
219
state. remove ( bid_key) ;
240
- state. insert_spaceout ( outpoint_key, rollout . spaceout ) ;
220
+ state. insert_spaceout ( outpoint_key, update . output . spaceout ) ;
241
221
}
242
- MetaOutKind :: SpaceOut ( carried ) => {
222
+ UpdateKind :: Bid => {
243
223
// Only bids are expected in meta outputs
244
224
let base_hash = Sha256 :: hash (
245
- carried
225
+ update
226
+ . output
246
227
. spaceout
247
228
. space
248
229
. as_ref ( )
@@ -251,25 +232,27 @@ impl Node {
251
232
. to_bytes ( ) ,
252
233
) ;
253
234
254
- let ( bid_value, previous_bid) = unwrap_bid_value ( & carried. spaceout ) ;
235
+ let ( bid_value, previous_bid) =
236
+ unwrap_bid_value ( & update. output . spaceout ) ;
255
237
256
- let bid_hash = BidHash :: from_bid ( bid_value, base_hash) ;
257
- let space_key = SpaceHash :: from ( base_hash) ;
238
+ let bid_hash = BidKey :: from_bid ( bid_value, base_hash) ;
239
+ let space_key = SpaceKey :: from ( base_hash) ;
258
240
259
- match carried . spaceout . space . as_ref ( ) . expect ( "space" ) . covenant {
241
+ match update . output . spaceout . space . as_ref ( ) . expect ( "space" ) . covenant {
260
242
Covenant :: Bid { claim_height, .. } => {
261
243
if claim_height. is_none ( ) {
262
- let prev_bid_hash = BidHash :: from_bid ( previous_bid, base_hash) ;
244
+ let prev_bid_hash = BidKey :: from_bid ( previous_bid, base_hash) ;
263
245
state. update_bid ( Some ( prev_bid_hash) , bid_hash, space_key) ;
264
246
}
265
247
}
266
248
_ => panic ! ( "expected bid" ) ,
267
249
}
268
250
269
- state. insert_space ( space_key, carried. outpoint . into ( ) ) ;
251
+ let carried_outpoint = update. output . outpoint ( ) ;
252
+ state. insert_space ( space_key, carried_outpoint. into ( ) ) ;
270
253
271
- let outpoint_key = OutpointHash :: from_outpoint :: < Sha256 > ( carried . outpoint ) ;
272
- state. insert_spaceout ( outpoint_key, carried . spaceout ) ;
254
+ let outpoint_key = OutpointKey :: from_outpoint :: < Sha256 > ( carried_outpoint ) ;
255
+ state. insert_spaceout ( outpoint_key, update . output . spaceout ) ;
273
256
}
274
257
}
275
258
}
@@ -291,7 +274,7 @@ impl Node {
291
274
let mut hash = [ 0u8 ; 32 ] ;
292
275
hash. copy_from_slice ( raw_hash. as_slice ( ) ) ;
293
276
294
- let space_hash = SpaceHash :: from_raw ( hash) ?;
277
+ let space_hash = SpaceKey :: from_raw ( hash) ?;
295
278
let full = chain. state . get_space_info ( & space_hash) ?;
296
279
297
280
if let Some ( full) = full {
0 commit comments