diff --git a/src/proto_alpha/lib_protocol/contract_repr.ml b/src/proto_alpha/lib_protocol/contract_repr.ml index 1fd9d0c5d43ccceab5c24cb927979eff35435dbb..02dd7440c7e9599842a3558620910f997b7e2648 100644 --- a/src/proto_alpha/lib_protocol/contract_repr.ml +++ b/src/proto_alpha/lib_protocol/contract_repr.ml @@ -188,7 +188,7 @@ let rpc_arg = ~destruct () -module Index = struct +module Index_008 = struct type t = contract let path_length = 7 @@ -228,3 +228,27 @@ module Index = struct let compare = compare end + +module Index = struct + type t = contract + + let path_length = 1 + + let to_path c l = + let raw_key = Data_encoding.Binary.to_bytes_exn encoding c in + let (`Hex key) = Hex.of_bytes raw_key in + key :: l + + let of_path = function + | [key] -> + let raw_key = Hex.to_bytes (`Hex key) in + Data_encoding.Binary.of_bytes encoding raw_key + | _ -> + None + + let rpc_arg = rpc_arg + + let encoding = encoding + + let compare = compare +end diff --git a/src/proto_alpha/lib_protocol/contract_repr.mli b/src/proto_alpha/lib_protocol/contract_repr.mli index 53935e460bbb6e57453a45d5b8593319c4d4de0c..bc49c917926a1c53b47ed0502bc4d1453f90be50 100644 --- a/src/proto_alpha/lib_protocol/contract_repr.mli +++ b/src/proto_alpha/lib_protocol/contract_repr.mli @@ -77,4 +77,6 @@ val origination_nonce_encoding : origination_nonce Data_encoding.t val rpc_arg : contract RPC_arg.arg +module Index_008 : Storage_description.INDEX with type t = t + module Index : Storage_description.INDEX with type t = t diff --git a/src/proto_alpha/lib_protocol/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index 1c312c5f256454463a3a3a80b0beacee008d7a1a..e95f73a1ea404e163b1f318bc8cea8a34ae6aa00 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -24,6 +24,64 @@ (* *) (*****************************************************************************) +module Migrate_from_008_to_009 = struct + let rec path_remove_prefix = function + | (h1 :: t1, h2 :: t2) when String.(equal h1 h2) -> + path_remove_prefix (t1, t2) + | ([], t2) -> + return t2 + | (_, _) -> + (*can't happens because the path have been digged starting with that + prefix *) + assert false + + let fold_keys (type t) ~index ~init ~f ~index_path ctxt = + let (module Index : Storage_functors.INDEX with type t = t) = index in + let rec dig len path acc = + if Compare.Int.(len <= 0) then + path_remove_prefix (index_path, path) + >>=? fun key_path -> + match Index.of_path key_path with + | None -> + (* can't happens as the path have been digged and can't be false *) + assert false + | Some value -> + f path value acc + else + Raw_context.fold ctxt path ~init:(Ok acc) ~f:(fun k acc -> + Lwt.return acc + >>=? fun acc -> + match k with `Dir k | `Key k -> dig (len - 1) k acc) + in + dig Index.path_length index_path init + + let migrate_indexed_storage (type t) ctxt ~from_index ~to_index ~index_path = + let (module To_index : Storage_functors.INDEX with type t = t) = + to_index + in + let tmp_index_path = + let rev_path = List.rev index_path in + List.rev (("tmp_" ^ List.hd rev_path) :: List.tl rev_path) + in + fold_keys + ~index:from_index + ~init:(ctxt, false) + ~f:(fun old_path value (ctxt, _has_value) -> + let new_path = tmp_index_path @ To_index.to_path value [] in + Raw_context.copy ctxt ~from:old_path ~to_:new_path + >>=? fun ctxt -> return (ctxt, true)) + ~index_path + ctxt + >>=? fun (ctxt, has_value) -> + if has_value then + Raw_context.remove_rec ctxt index_path + >>= fun ctxt -> + Raw_context.copy ctxt tmp_index_path index_path + >>=? fun ctxt -> + Raw_context.remove_rec ctxt tmp_index_path >>= fun ctxt -> return ctxt + else return ctxt +end + (* This is the genesis protocol: initialise the state *) let prepare_first_block ctxt ~typecheck ~level ~timestamp ~fitness = Raw_context.prepare_first_block ~level ~timestamp ~fitness ctxt @@ -61,6 +119,94 @@ let prepare_first_block ctxt ~typecheck ~level ~timestamp ~fitness = *) let balance_updates = [] in Storage.Pending_migration_balance_updates.init ctxt balance_updates + >>=? fun ctxt -> + let contract_index_008 = + ( module Storage.Make_index (Contract_repr.Index_008) + : Storage_functors.INDEX + with type t = Contract_repr.t ) + in + let contract_index = + ( module Storage.Make_index (Contract_repr.Index) + : Storage_functors.INDEX + with type t = Contract_repr.t ) + in + Migrate_from_008_to_009.migrate_indexed_storage + ctxt + ~from_index:contract_index_008 + ~to_index:contract_index + ~index_path:["contracts"; "index"] + >>=? fun ctxt -> + Storage.Contract.fold + ~init:(ok ctxt) + ~f:(fun contract ctxt -> + Lwt.return ctxt + >>=? fun ctxt -> + Migrate_from_008_to_009.migrate_indexed_storage + ~from_index:contract_index_008 + ~to_index:contract_index + ~index_path: + ( ["contracts"; "index"] + @ Contract_repr.Index.to_path contract [] + @ ["delegated"] ) + ctxt) + ctxt + >>=? fun ctxt -> + let bigmap_index_008 = + ( module Storage.Make_index (Storage.Big_map.Index_008) + : Storage_functors.INDEX + with type t = Storage.Big_map.id ) + in + let bigmap_index = + ( module Storage.Make_index (Storage.Big_map.Index) + : Storage_functors.INDEX + with type t = Storage.Big_map.id ) + in + Migrate_from_008_to_009.migrate_indexed_storage + ctxt + ~from_index:bigmap_index_008 + ~to_index:bigmap_index + ~index_path:["big_maps"; "index"] + >>=? fun ctxt -> + let rolls_index_008 = + ( module Storage.Make_index (Roll_repr.Index_008) + : Storage_functors.INDEX + with type t = Roll_repr.t ) + in + let rolls_index = + (module Storage.Make_index (Roll_repr.Index) : Storage_functors.INDEX + with type t = Roll_repr.t ) + in + let snapshot_rolls_index_008 = + let (module Rolls_index_008) = rolls_index_008 in + ( module Storage_functors.Pair + (Storage.Roll.Snapshoted_owner_index) + (Rolls_index_008) : Storage_functors.INDEX + with type t = (Cycle_repr.t * int) * Roll_repr.t ) + in + let snapshot_rolls_index = + let (module Rolls_index) = rolls_index in + ( module Storage_functors.Pair + (Storage.Roll.Snapshoted_owner_index) + (Rolls_index) : Storage_functors.INDEX + with type t = (Cycle_repr.t * int) * Roll_repr.t ) + in + Migrate_from_008_to_009.migrate_indexed_storage + ctxt + ~from_index:rolls_index_008 + ~to_index:rolls_index + ~index_path:["rolls"; "index"] + >>=? fun ctxt -> + Migrate_from_008_to_009.migrate_indexed_storage + ctxt + ~from_index:snapshot_rolls_index_008 + ~to_index:snapshot_rolls_index + ~index_path:["rolls"; "owner"; "snapshot"] + >>=? fun ctxt -> + Migrate_from_008_to_009.migrate_indexed_storage + ctxt + ~from_index:rolls_index_008 + ~to_index:rolls_index + ~index_path:["rolls"; "owner"; "current"] let prepare ctxt ~level ~predecessor_timestamp ~timestamp ~fitness = Raw_context.prepare ~level ~predecessor_timestamp ~timestamp ~fitness ctxt diff --git a/src/proto_alpha/lib_protocol/roll_repr.ml b/src/proto_alpha/lib_protocol/roll_repr.ml index 74b47360b2ace54d0ad6efac2f2fdcd620a3ba57..5af663463bc30cc9aa90dc8e5e865462e3722a81 100644 --- a/src/proto_alpha/lib_protocol/roll_repr.ml +++ b/src/proto_alpha/lib_protocol/roll_repr.ml @@ -39,7 +39,7 @@ let rpc_arg = RPC_arg.like RPC_arg.int32 "roll" let to_int32 v = v -module Index = struct +module Index_008 = struct type t = roll let path_length = 3 @@ -63,3 +63,19 @@ module Index = struct let compare = compare end + +module Index = struct + type t = roll + + let path_length = 1 + + let to_path roll l = Int32.to_string roll :: l + + let of_path = function s :: _ -> Int32.of_string_opt s | _ -> None + + let rpc_arg = rpc_arg + + let encoding = encoding + + let compare = compare +end diff --git a/src/proto_alpha/lib_protocol/roll_repr.mli b/src/proto_alpha/lib_protocol/roll_repr.mli index cb792b0128e73203abec091ee1aadf019aa356a1..c3ddd19cf617ab0a74683d1f2e585c5586fa7141 100644 --- a/src/proto_alpha/lib_protocol/roll_repr.mli +++ b/src/proto_alpha/lib_protocol/roll_repr.mli @@ -41,4 +41,6 @@ val to_int32 : roll -> Int32.t val ( = ) : roll -> roll -> bool +module Index_008 : Storage_description.INDEX with type t = roll + module Index : Storage_description.INDEX with type t = roll diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index cf1d39cabde90b5e5f1b62b98a49136724eef42b..8199f09f158fe389a896d68e4f0bbc50984c9420 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -337,9 +337,9 @@ module Big_map = struct let init ctxt = init ctxt Lazy_storage_kind.Big_map.Id.init end - module Index = struct - (* After flat storage, just use module Index = Lazy_storage_kind.Big_map.Id *) + module Index = Lazy_storage_kind.Big_map.Id + module Index_008 = struct include Lazy_storage_kind.Big_map.Id let path_length = 6 + path_length diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 4ec426976050805080486bd31c59e8c60e024645..28866035fff04052c7d7bbcb544d3b3034d4508c 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -44,10 +44,27 @@ module Block_priority : sig val init : Raw_context.t -> int -> Raw_context.t tzresult Lwt.t end +module Make_index (H : Storage_description.INDEX) : sig + type t = H.t + + val path_length : int + + val to_path : t -> string list -> string list + + val of_path : string list -> t option + + type 'a ipath = 'a * t + + val args : ('a, t, 'a ipath) Storage_description.args +end + module Roll : sig (** Storage from this submodule must only be accessed through the module `Roll`. *) + module Snapshoted_owner_index : + Storage_functors.INDEX with type t = Cycle_repr.t * int + module Owner : Indexed_data_snapshotable_storage with type key = Roll_repr.t @@ -223,6 +240,10 @@ end module Big_map : sig type id = Lazy_storage_kind.Big_map.Id.t + module Index_008 : Storage_description.INDEX with type t = id + + module Index : Storage_description.INDEX with type t = id + module Next : sig val incr : Raw_context.t -> (Raw_context.t * id) tzresult Lwt.t diff --git a/tezt/_regressions/rpc/alpha.delegates.out b/tezt/_regressions/rpc/alpha.delegates.out index 9488b536100bf71b25262a775e201f96b97073c3..ba15ba124239331145209af693faecc92bab54a5 100644 --- a/tezt/_regressions/rpc/alpha.delegates.out +++ b/tezt/_regressions/rpc/alpha.delegates.out @@ -37,13 +37,13 @@ false ./tezos-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' Fatal error: Command failed : Storage error: - Missing key 'contracts/index/63/cb/4c/cb/6c/4c/0000b443c2c85e0aeb6a4c0a37783f4d8251a956e8ad/balance'. + Missing key 'contracts/index/0000b443c2c85e0aeb6a4c0a37783f4d8251a956e8ad/balance'. ./tezos-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/balance' Fatal error: Command failed : Storage error: - Missing key 'contracts/index/63/cb/4c/cb/6c/4c/0000b443c2c85e0aeb6a4c0a37783f4d8251a956e8ad/balance'. + Missing key 'contracts/index/0000b443c2c85e0aeb6a4c0a37783f4d8251a956e8ad/balance'. ./tezos-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/deactivated' @@ -52,7 +52,7 @@ false ./tezos-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_balance' Fatal error: Command failed : Storage error: - Missing key 'contracts/index/63/cb/4c/cb/6c/4c/0000b443c2c85e0aeb6a4c0a37783f4d8251a956e8ad/balance'. + Missing key 'contracts/index/0000b443c2c85e0aeb6a4c0a37783f4d8251a956e8ad/balance'. ./tezos-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_contracts' @@ -67,7 +67,7 @@ Fatal error: ./tezos-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/grace_period' Fatal error: Command failed : Storage error: - Missing key 'contracts/index/63/cb/4c/cb/6c/4c/0000b443c2c85e0aeb6a4c0a37783f4d8251a956e8ad/delegate_desactivation'. + Missing key 'contracts/index/0000b443c2c85e0aeb6a4c0a37783f4d8251a956e8ad/delegate_desactivation'. ./tezos-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_balance'