@@ -452,6 +452,13 @@ impl TopLevelState {
452452 self . create_shard ( & shard_creation_cost, fee_payer) ?;
453453 Ok ( ParcelInvoice :: SingleSuccess )
454454 }
455+ Action :: ChangeShardOwners {
456+ shard_id,
457+ owners,
458+ } => {
459+ self . change_shard_owners ( * shard_id, owners, fee_payer) ?;
460+ Ok ( ParcelInvoice :: SingleSuccess )
461+ }
455462 Action :: Custom ( bytes) => {
456463 let handlers = self . db . custom_handlers ( ) . to_vec ( ) ;
457464 for h in handlers {
@@ -790,6 +797,18 @@ impl TopState<StateDB> for TopLevelState {
790797 Ok ( ( ) )
791798 }
792799
800+ fn change_shard_owners ( & mut self , shard_id : ShardId , owners : & [ Address ] , sender : & Address ) -> StateResult < ( ) > {
801+ let old_owners = self . shard_owners ( shard_id) ?. ok_or_else ( || ParcelError :: InvalidShardId ( shard_id) ) ?;
802+ if !old_owners. contains ( sender) {
803+ return Err ( ParcelError :: InsufficientPermission . into ( ) )
804+ }
805+ if !owners. contains ( sender) {
806+ return Err ( ParcelError :: NewOwnersMustContainSender . into ( ) )
807+ }
808+
809+ self . set_shard_owners ( shard_id, owners. to_vec ( ) )
810+ }
811+
793812 fn set_shard_root ( & mut self , shard_id : ShardId , old_root : & H256 , new_root : & H256 ) -> StateResult < ( ) > {
794813 let mut shard = self . require_shard ( shard_id) ?;
795814 assert_eq ! ( old_root, shard. root( ) ) ;
@@ -2224,4 +2243,166 @@ mod tests_parcel {
22242243 assert_eq ! ( Ok ( 2 . into( ) ) , state. nonce( & sender) ) ;
22252244 assert_eq ! ( Ok ( Some ( World :: new_with_nonce( new_owners, 1 ) ) ) , state. world( shard_id, world_id) ) ;
22262245 }
2246+
2247+ #[ test]
2248+ fn change_shard_owners ( ) {
2249+ let ( sender, sender_public) = address ( ) ;
2250+
2251+ let mut state = get_temp_state ( ) ;
2252+ assert_eq ! ( Ok ( ( ) ) , state. create_shard_level_state( & sender) ) ;
2253+ assert_eq ! ( Ok ( ( ) ) , state. add_balance( & sender, & U256 :: from( 69u64 ) ) ) ;
2254+ assert_eq ! ( Ok ( ( ) ) , state. commit( ) ) ;
2255+
2256+ let network_id = 0xCA ;
2257+ let shard_id = 0 ;
2258+ let owners = vec ! [ Address :: random( ) , Address :: random( ) , sender] ;
2259+
2260+ let parcel = Parcel {
2261+ fee : 5 . into ( ) ,
2262+ action : Action :: ChangeShardOwners {
2263+ shard_id,
2264+ owners : owners. clone ( ) ,
2265+ } ,
2266+ nonce : 0 . into ( ) ,
2267+ network_id,
2268+ } ;
2269+
2270+ assert_eq ! ( Ok ( Some ( vec![ sender] ) ) , state. shard_owners( shard_id) ) ;
2271+
2272+ assert_eq ! ( Ok ( ParcelInvoice :: SingleSuccess ) , state. apply( & parcel, & sender, & sender_public) ) ;
2273+
2274+ assert_eq ! ( Ok ( 64 . into( ) ) , state. balance( & sender) ) ;
2275+ assert_eq ! ( Ok ( 1 . into( ) ) , state. nonce( & sender) ) ;
2276+ assert_eq ! ( Ok ( Some ( owners) ) , state. shard_owners( shard_id) ) ;
2277+ }
2278+
2279+ #[ test]
2280+ fn new_owners_must_contain_sender ( ) {
2281+ let ( sender, sender_public) = address ( ) ;
2282+
2283+ let mut state = get_temp_state ( ) ;
2284+ assert_eq ! ( Ok ( ( ) ) , state. create_shard_level_state( & sender) ) ;
2285+ assert_eq ! ( Ok ( ( ) ) , state. add_balance( & sender, & U256 :: from( 69u64 ) ) ) ;
2286+ assert_eq ! ( Ok ( ( ) ) , state. commit( ) ) ;
2287+
2288+ let network_id = 0xCA ;
2289+ let shard_id = 0 ;
2290+ let owners = {
2291+ let a1 = loop {
2292+ let a = Address :: random ( ) ;
2293+ if a != sender {
2294+ break a
2295+ }
2296+ } ;
2297+ let a2 = loop {
2298+ let a = Address :: random ( ) ;
2299+ if a != sender {
2300+ break a
2301+ }
2302+ } ;
2303+ vec ! [ a1, a2]
2304+ } ;
2305+
2306+ let parcel = Parcel {
2307+ fee : 5 . into ( ) ,
2308+ action : Action :: ChangeShardOwners {
2309+ shard_id,
2310+ owners,
2311+ } ,
2312+ nonce : 0 . into ( ) ,
2313+ network_id,
2314+ } ;
2315+
2316+ assert_eq ! ( Ok ( Some ( vec![ sender] ) ) , state. shard_owners( shard_id) ) ;
2317+
2318+ assert_eq ! ( Err ( ParcelError :: NewOwnersMustContainSender . into( ) ) , state. apply( & parcel, & sender, & sender_public) ) ;
2319+
2320+ assert_eq ! ( Ok ( 69 . into( ) ) , state. balance( & sender) ) ;
2321+ assert_eq ! ( Ok ( 0 . into( ) ) , state. nonce( & sender) ) ;
2322+ assert_eq ! ( Ok ( Some ( vec![ sender] ) ) , state. shard_owners( shard_id) ) ;
2323+ }
2324+
2325+ #[ test]
2326+ fn only_owner_can_change_owners ( ) {
2327+ let ( original_owner, _) = address ( ) ;
2328+
2329+ let mut state = get_temp_state ( ) ;
2330+ assert_eq ! ( Ok ( ( ) ) , state. create_shard_level_state( & original_owner) ) ;
2331+ let ( sender, sender_public) = address ( ) ;
2332+ assert_eq ! ( Ok ( ( ) ) , state. add_balance( & sender, & U256 :: from( 69u64 ) ) ) ;
2333+ assert_eq ! ( Ok ( ( ) ) , state. commit( ) ) ;
2334+
2335+ let network_id = 0xCA ;
2336+ let shard_id = 0 ;
2337+
2338+ let owners = {
2339+ let a1 = loop {
2340+ let a = Address :: random ( ) ;
2341+ if a != original_owner {
2342+ break a
2343+ }
2344+ } ;
2345+ let a2 = loop {
2346+ let a = Address :: random ( ) ;
2347+ if a != original_owner {
2348+ break a
2349+ }
2350+ } ;
2351+ vec ! [ a1, a2, sender]
2352+ } ;
2353+
2354+ let parcel = Parcel {
2355+ fee : 5 . into ( ) ,
2356+ action : Action :: ChangeShardOwners {
2357+ shard_id,
2358+ owners,
2359+ } ,
2360+ nonce : 0 . into ( ) ,
2361+ network_id,
2362+ } ;
2363+
2364+ assert_eq ! ( Ok ( Some ( vec![ original_owner] ) ) , state. shard_owners( shard_id) ) ;
2365+
2366+ assert_eq ! ( Err ( ParcelError :: InsufficientPermission . into( ) ) , state. apply( & parcel, & sender, & sender_public) ) ;
2367+
2368+ assert_eq ! ( Ok ( 69 . into( ) ) , state. balance( & sender) ) ;
2369+ assert_eq ! ( Ok ( 0 . into( ) ) , state. nonce( & sender) ) ;
2370+ assert_eq ! ( Ok ( Some ( vec![ original_owner] ) ) , state. shard_owners( shard_id) ) ;
2371+ }
2372+
2373+ #[ test]
2374+ fn change_shard_owners_fail_on_invalid_shard_id ( ) {
2375+ let ( sender, sender_public) = address ( ) ;
2376+
2377+ let mut state = get_temp_state ( ) ;
2378+ assert_eq ! ( Ok ( ( ) ) , state. create_shard_level_state( & sender) ) ;
2379+ assert_eq ! ( Ok ( ( ) ) , state. add_balance( & sender, & U256 :: from( 69u64 ) ) ) ;
2380+ assert_eq ! ( Ok ( ( ) ) , state. commit( ) ) ;
2381+
2382+ let network_id = 0xCA ;
2383+ let real_shard_id = 0 ;
2384+ let shard_id = 0xF ;
2385+
2386+ let owners = vec ! [ Address :: random( ) , Address :: random( ) , sender] ;
2387+
2388+ let parcel = Parcel {
2389+ fee : 5 . into ( ) ,
2390+ action : Action :: ChangeShardOwners {
2391+ shard_id,
2392+ owners : owners. clone ( ) ,
2393+ } ,
2394+ nonce : 0 . into ( ) ,
2395+ network_id,
2396+ } ;
2397+
2398+ assert_eq ! ( Ok ( Some ( vec![ sender] ) ) , state. shard_owners( real_shard_id) ) ;
2399+ assert_eq ! ( Ok ( None ) , state. shard_owners( shard_id) ) ;
2400+
2401+ assert_eq ! ( Err ( ParcelError :: InvalidShardId ( shard_id) . into( ) ) , state. apply( & parcel, & sender, & sender_public) ) ;
2402+
2403+ assert_eq ! ( Ok ( 69 . into( ) ) , state. balance( & sender) ) ;
2404+ assert_eq ! ( Ok ( 0 . into( ) ) , state. nonce( & sender) ) ;
2405+ assert_eq ! ( Ok ( Some ( vec![ sender] ) ) , state. shard_owners( real_shard_id) ) ;
2406+ assert_eq ! ( Ok ( None ) , state. shard_owners( shard_id) ) ;
2407+ }
22272408}
0 commit comments