@@ -9,12 +9,13 @@ use fvm_ipld_encoding::tuple::*;
9
9
use fvm_ipld_encoding:: Cbor ;
10
10
use fvm_ipld_encoding:: CborStore ;
11
11
use fvm_ipld_encoding:: DAG_CBOR ;
12
- use fvm_ipld_hamt:: Error as HamtError ;
13
12
use fvm_ipld_hamt:: Hamt ;
13
+ use fvm_ipld_hamt:: { BytesKey , Error as HamtError } ;
14
14
use fvm_shared:: address:: Address ;
15
15
use fvm_shared:: bigint:: Zero ;
16
16
use fvm_shared:: econ:: TokenAmount ;
17
17
use fvm_shared:: ActorID ;
18
+ use integer_encoding:: VarInt ;
18
19
use thiserror:: Error ;
19
20
20
21
/// This value has been chosen to optimise to reduce gas-costs when accessing the balances map. Non-
@@ -153,7 +154,7 @@ impl TokenState {
153
154
pub fn get_balance < BS : Blockstore > ( & self , bs : & BS , owner : ActorID ) -> Result < TokenAmount > {
154
155
let balances = self . get_balance_map ( bs) ?;
155
156
156
- let balance = match balances. get ( & owner) ? {
157
+ let balance = match balances. get ( & actor_id_key ( owner) ) ? {
157
158
Some ( amount) => amount. clone ( ) ,
158
159
None => TokenAmount :: zero ( ) ,
159
160
} ;
@@ -177,7 +178,8 @@ impl TokenState {
177
178
}
178
179
179
180
let mut balance_map = self . get_balance_map ( bs) ?;
180
- let balance = balance_map. get ( & owner) ?;
181
+ let owner_key = actor_id_key ( owner) ;
182
+ let balance = balance_map. get ( & owner_key) ?;
181
183
let balance = match balance {
182
184
Some ( amount) => amount. clone ( ) ,
183
185
None => TokenAmount :: zero ( ) ,
@@ -191,9 +193,9 @@ impl TokenState {
191
193
}
192
194
193
195
if new_balance. is_zero ( ) {
194
- balance_map. delete ( & owner ) ?;
196
+ balance_map. delete ( & owner_key ) ?;
195
197
} else {
196
- balance_map. set ( owner , new_balance. clone ( ) ) ?;
198
+ balance_map. set ( owner_key , new_balance. clone ( ) ) ?;
197
199
}
198
200
199
201
self . balances = balance_map. flush ( ) ?;
@@ -214,20 +216,21 @@ impl TokenState {
214
216
}
215
217
216
218
let mut balance_map = self . get_balance_map ( bs) ?;
217
- let old_balance = match balance_map. get ( & owner) ? {
219
+ let owner_key = actor_id_key ( owner) ;
220
+ let old_balance = match balance_map. get ( & owner_key) ? {
218
221
Some ( amount) => amount. clone ( ) ,
219
222
None => TokenAmount :: zero ( ) ,
220
223
} ;
221
224
222
225
// if the new balance is zero, remove from balance map
223
226
if new_balance. is_zero ( ) {
224
- balance_map. delete ( & owner ) ?;
227
+ balance_map. delete ( & owner_key ) ?;
225
228
self . balances = balance_map. flush ( ) ?;
226
229
return Ok ( old_balance) ;
227
230
}
228
231
229
232
// else, set the new balance
230
- balance_map. set ( owner , new_balance. clone ( ) ) ?;
233
+ balance_map. set ( owner_key , new_balance. clone ( ) ) ?;
231
234
self . balances = balance_map. flush ( ) ?;
232
235
Ok ( old_balance)
233
236
}
@@ -236,7 +239,7 @@ impl TokenState {
236
239
pub fn get_balance_map < ' bs , BS : Blockstore > (
237
240
& self ,
238
241
bs : & ' bs BS ,
239
- ) -> Result < Map < ' bs , BS , ActorID , TokenAmount > > {
242
+ ) -> Result < Map < ' bs , BS , BytesKey , TokenAmount > > {
240
243
Ok ( Hamt :: load_with_bit_width ( & self . balances , bs, self . hamt_bit_width ) ?)
241
244
}
242
245
@@ -509,18 +512,24 @@ impl TokenState {
509
512
let mut balance_sum = TokenAmount :: zero ( ) ;
510
513
let mut maybe_err: Option < StateInvariantError > = None ;
511
514
let balances = self . get_balance_map ( bs) ?;
512
- let res = balances. for_each ( |owner, balance| {
515
+ let res = balances. for_each ( |owner_key, balance| {
516
+ let owner = match decode_actor_id ( owner_key) {
517
+ None => {
518
+ bail ! ( "invalid key in balances map" )
519
+ }
520
+ Some ( a) => a,
521
+ } ;
513
522
// all balances must be positive
514
523
if balance. is_negative ( ) {
515
524
maybe_err = Some ( StateInvariantError :: BalanceNegative {
516
- account : * owner,
525
+ account : owner,
517
526
balance : balance. clone ( ) ,
518
527
} ) ;
519
528
bail ! ( "invariant failed" )
520
529
}
521
530
// zero balances should not be stored in the Hamt
522
531
if balance. is_zero ( ) {
523
- maybe_err = Some ( StateInvariantError :: ExplicitZeroBalance ( * owner) ) ;
532
+ maybe_err = Some ( StateInvariantError :: ExplicitZeroBalance ( owner) ) ;
524
533
bail ! ( "invariant failed" )
525
534
}
526
535
balance_sum = balance_sum. clone ( ) + balance. clone ( ) ;
@@ -589,6 +598,14 @@ impl TokenState {
589
598
}
590
599
}
591
600
601
+ pub fn actor_id_key ( a : ActorID ) -> BytesKey {
602
+ a. encode_var_vec ( ) . into ( )
603
+ }
604
+
605
+ pub fn decode_actor_id ( key : & BytesKey ) -> Option < ActorID > {
606
+ u64:: decode_var ( key. 0 . as_slice ( ) ) . map ( |a| a. 0 )
607
+ }
608
+
592
609
impl Cbor for TokenState { }
593
610
594
611
#[ cfg( test) ]
0 commit comments