ligo/src/proto/alpha/storage.ml

574 lines
17 KiB
OCaml
Raw Normal View History

2016-09-08 21:13:10 +04:00
(**************************************************************************)
(* *)
(* Copyright (c) 2014 - 2016. *)
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* All rights reserved. No warranty, explicit or implicit, provided. *)
(* *)
(**************************************************************************)
open Tezos_hash
open Storage_functors
(* This key should always be populated for every version of the
protocol. It's absence meaning that the context is empty. *)
let version_key = ["version"]
let version_value = "alpha"
type error += Incompatiple_protocol_version
let is_first_block ctxt =
Context.get ctxt version_key >>= function
| None ->
return true
| Some bytes ->
let s = MBytes.to_string bytes in
if Compare.String.(s = version_value) then
return false
else if Compare.String.(s = "genesis") then
return true
else
fail Incompatiple_protocol_version
2016-09-08 21:13:10 +04:00
let version = "v1"
let first_level_key = [ version ; "first_level" ]
2016-09-08 21:13:10 +04:00
let sandboxed_key = [ version ; "sandboxed" ]
type t = Storage_functors.context
type error += Invalid_sandbox_parameter
2016-09-08 21:13:10 +04:00
let current_level { level } = level
let current_timestamp { timestamp } = timestamp
let current_fitness { fitness } = fitness
let set_current_fitness c fitness = { c with fitness }
let get_first_level ctxt =
Context.get ctxt first_level_key >>= function
| None -> failwith "Invalid context"
| Some bytes ->
match
Data_encoding.Binary.of_bytes Raw_level_repr.encoding bytes
with
| None -> failwith "Invalid context"
| Some level -> return level
let set_first_level ctxt level =
let bytes =
Data_encoding.Binary.to_bytes Raw_level_repr.encoding level in
Context.set ctxt first_level_key bytes >>= fun ctxt ->
return ctxt
2016-09-08 21:13:10 +04:00
let get_sandboxed c =
Context.get c sandboxed_key >>= function
| None -> return None
| Some bytes ->
match Data_encoding.Binary.of_bytes Data_encoding.json bytes with
| None -> fail Invalid_sandbox_parameter
| Some json -> return (Some json)
2016-09-08 21:13:10 +04:00
let set_sandboxed c json =
Context.set c sandboxed_key
(Data_encoding.Binary.to_bytes Data_encoding.json json)
2016-09-08 21:13:10 +04:00
let may_tag_first_block ctxt level =
is_first_block ctxt >>=? function
| false ->
get_first_level ctxt >>=? fun level ->
return (ctxt, false, level)
| true ->
Context.set ctxt version_key
(MBytes.of_string version_value) >>= fun ctxt ->
set_first_level ctxt level >>=? fun ctxt ->
return (ctxt, true, level)
let prepare ~level ~timestamp ~fitness ctxt =
Lwt.return (Raw_level_repr.of_int32 level ) >>=? fun level ->
Lwt.return (Fitness_repr.to_int64 fitness) >>=? fun fitness ->
may_tag_first_block ctxt level >>=? fun (ctxt, first_block, first_level) ->
get_sandboxed ctxt >>=? fun sandbox ->
2016-09-08 21:13:10 +04:00
Constants_repr.read sandbox >>=? function constants ->
let level =
Level_repr.from_raw
~first_level
~cycle_length:constants.Constants_repr.cycle_length
~voting_period_length:constants.Constants_repr.voting_period_length
level in
return ({ context = ctxt ; constants ; level ;
timestamp ; fitness ; first_level},
first_block)
let recover { context } : Context.t = context
2016-09-08 21:13:10 +04:00
let first_level { first_level } = first_level
let constants { constants } = constants
2016-09-08 21:13:10 +04:00
module Key = struct
let store_root tail = version :: "store" :: tail
let global_counter = store_root ["global_counter"]
let faucet_counter = store_root ["faucet_counter"]
2016-09-08 21:13:10 +04:00
let next_cycle_to_be_rewarded = store_root ["next_cycle_to_be_rewarded"]
let rewards = store_root ["rewards"]
2016-11-14 20:33:32 +04:00
let public_keys = ["public_keys" ; "ed25519"]
2016-09-08 21:13:10 +04:00
module Roll = struct
let store_root l = store_root ("rolls" :: l)
let next = store_root [ "next" ]
let limbo = store_root [ "limbo" ]
let roll_store roll l =
store_root @@ Int32.to_string (Roll_repr.to_int32 roll) :: l
let successor r = roll_store r ["successor"]
let owner r = roll_store r ["owner"]
end
module Cycle = struct
let store_root l = store_root ("cycles" :: l)
let cycle_store c l =
store_root @@ Int32.to_string (Cycle_repr.to_int32 c) :: l
let last_roll c = cycle_store c [ "last_roll" ]
let random_seed c = cycle_store c [ "random_seed" ]
let reward_date c = cycle_store c [ "reward_date" ]
let roll_owner (c, r) =
cycle_store c [ "roll_owners" ; Int32.to_string (Roll_repr.to_int32 r)]
let unrevealed_nonce_hash l =
let c = l.Level_repr.cycle in
cycle_store c [ "unrevealed_nonce_hash" ;
Int32.to_string l.Level_repr.cycle_position ]
end
module Contract = struct
2016-09-08 21:13:10 +04:00
let store_root l = store_root ("contracts" :: l)
let set = store_root ["set"]
2016-11-14 20:33:32 +04:00
let pubkey_contract l = store_root ("pubkey" :: l)
let generic_contract l = store_root ("generic" :: l)
2016-09-08 21:13:10 +04:00
let contract_store c l =
match c with
| Contract_repr.Default k ->
2016-11-14 20:33:32 +04:00
pubkey_contract @@ Ed25519.Public_key_hash.to_path k @ l
| Contract_repr.Originated h ->
2016-11-14 20:33:32 +04:00
generic_contract @@ Contract_hash.to_path h @ l
2016-09-08 21:13:10 +04:00
let roll_list c = contract_store c ["roll_list"]
let change c = contract_store c ["change"]
let balance c = contract_store c ["balance"]
let manager c = contract_store c ["manager"]
let spendable c = contract_store c ["spendable"]
let delegatable c = contract_store c ["delegatable"]
let delegate c = contract_store c ["delegate"]
let counter c = contract_store c ["counter"]
let code c = contract_store c ["code"]
let storage c = contract_store c ["storage"]
let code_fees c = contract_store c ["code_fees"]
let storage_fees c = contract_store c ["storage_fees"]
2016-09-08 21:13:10 +04:00
end
module Vote = struct
let store_root l = store_root ("votes" :: l)
let period_kind = store_root ["current_period_kind"]
let quorum = store_root ["current_quorum"]
let proposition = store_root ["current_proposition"]
let proposals = store_root ["proposals"]
let ballots = store_root ["ballots"]
let listings_size = store_root ["listings_size"]
let listings = store_root ["listings"]
end
end
(** Rolls *)
module Roll = struct
module Next =
Make_single_data_storage(struct
type value = Roll_repr.t
let name = "next fresh roll"
let key = Key.Roll.next
let encoding = Roll_repr.encoding
end)
module Limbo =
Make_single_optional_data_storage(struct
type value = Roll_repr.t
let name = "limbo"
let key = Key.Roll.limbo
let encoding = Roll_repr.encoding
end)
module Last_for_cycle =
Make_indexed_data_storage(struct
type key = Cycle_repr.t
type value = Roll_repr.t
let name = "last roll for current cycle"
let key = Key.Cycle.last_roll
let encoding = Roll_repr.encoding
end)
module Successor =
Make_indexed_optional_data_storage(struct
type key = Roll_repr.t
type value = Roll_repr.t
let name = "roll successor"
let key = Key.Roll.successor
let encoding = Roll_repr.encoding
end)
module Owner =
Make_indexed_data_storage(struct
type key = Roll_repr.t
type value = Contract_repr.t
let name = "roll owner"
let key = Key.Roll.owner
let encoding = Contract_repr.encoding
end)
module Owner_for_cycle =
Make_indexed_data_storage(struct
type key = Cycle_repr.t * Roll_repr.t
type value = Ed25519.Public_key_hash.t
2016-09-08 21:13:10 +04:00
let name = "roll owner for current cycle"
let key = Key.Cycle.roll_owner
let encoding = Ed25519.Public_key_hash.encoding
2016-09-08 21:13:10 +04:00
end)
module Contract_roll_list =
Make_indexed_optional_data_storage(struct
type key = Contract_repr.t
type value = Roll_repr.t
let name = "contract roll list"
let key = Key.Contract.roll_list
let encoding = Roll_repr.encoding
end)
module Contract_change =
Make_indexed_data_storage(struct
type key = Contract_repr.t
type value = Tez_repr.t
let name = "contract change"
let key = Key.Contract.change
let encoding = Tez_repr.encoding
end)
end
(** Contracts handling *)
module Contract = struct
module Global_counter =
Make_single_data_storage(struct
type value = int32
let name = "global counter"
let key = Key.global_counter
let encoding = Data_encoding.int32
end)
module Faucet_counter =
Make_single_data_storage(struct
type value = int32
let name = "faucet counter"
let key = Key.faucet_counter
let encoding = Data_encoding.int32
end)
(** FIXME REMOVE : use 'list' *)
2016-09-08 21:13:10 +04:00
module Set =
Make_data_set_storage(struct
type value = Contract_repr.t
let name = "contract set"
let key = Key.Contract.set
let encoding = Contract_repr.encoding
end)
module Balance =
Make_indexed_data_storage(
struct
type key = Contract_repr.t
type value = Tez_repr.t
let name = "contract balance"
let key = Key.Contract.balance
let encoding = Tez_repr.encoding
end)
module Manager =
Make_indexed_data_storage(struct
type key = Contract_repr.t
type value = Ed25519.Public_key_hash.t
2016-09-08 21:13:10 +04:00
let name = "contract manager"
let key = Key.Contract.manager
let encoding = Ed25519.Public_key_hash.encoding
2016-09-08 21:13:10 +04:00
end)
module Spendable =
Make_indexed_data_storage(struct
type key = Contract_repr.t
type value = bool
let name = "contract spendable"
let key = Key.Contract.spendable
let encoding = Data_encoding.bool
end)
module Delegatable =
Make_indexed_data_storage(struct
type key = Contract_repr.t
type value = bool
let name = "contract delegatable"
let key = Key.Contract.delegatable
let encoding = Data_encoding.bool
end)
module Delegate =
Make_indexed_data_storage(struct
type key = Contract_repr.t
type value = Ed25519.Public_key_hash.t
2016-09-08 21:13:10 +04:00
let name = "contract delegate"
let key = Key.Contract.delegate
let encoding = Ed25519.Public_key_hash.encoding
2016-09-08 21:13:10 +04:00
end)
module Counter =
Make_indexed_data_storage(struct
type key = Contract_repr.t
type value = Int32.t
let name = "contract counter"
let key = Key.Contract.counter
let encoding = Data_encoding.int32
end)
module Code =
Make_indexed_data_storage(struct
type key = Contract_repr.t
type value = Script_repr.code
let name = "contract code"
let key = Key.Contract.code
let encoding = Script_repr.code_encoding
end)
module Storage =
Make_indexed_data_storage(struct
type key = Contract_repr.t
type value = Script_repr.storage
let name = "contract storage"
let key = Key.Contract.storage
let encoding = Script_repr.storage_encoding
end)
module Code_fees =
Make_indexed_data_storage(struct
type key = Contract_repr.t
type value = Tez_repr.t
let name = "contract code fees"
let key = Key.Contract.code_fees
let encoding = Tez_repr.encoding
end)
module Storage_fees =
Make_indexed_data_storage(struct
type key = Contract_repr.t
type value = Tez_repr.t
let name = "contract storage fees"
let key = Key.Contract.storage_fees
let encoding = Tez_repr.encoding
end)
2016-09-08 21:13:10 +04:00
end
(** Votes **)
module Vote = struct
module Current_period_kind =
Make_single_data_storage(struct
type value = Voting_period_repr.kind
let name = "current period kind"
let key = Key.Vote.period_kind
let encoding = Voting_period_repr.kind_encoding
end)
module Current_quorum =
Make_single_data_storage(struct
type value = int32
let name = "current quorum"
let key = Key.Vote.quorum
let encoding = Data_encoding.int32
end)
module Current_proposal =
Make_single_data_storage(struct
type value = Protocol_hash.t
let name = "current proposal"
let key = Key.Vote.proposition
let encoding = Protocol_hash.encoding
end)
module Listings_size =
Make_single_data_storage(struct
type value = int32
let name = "listing size"
let key = Key.Vote.listings_size
let encoding = Data_encoding.int32
end)
module Listings =
Make_iterable_data_storage (Ed25519.Public_key_hash)
(struct
type value = int32
let key = Key.Vote.listings
let name = "listings"
let encoding = Data_encoding.int32
end)
module Proposals =
Make_data_set_storage
(struct
type value = Protocol_hash.t * Ed25519.Public_key_hash.t
2016-09-08 21:13:10 +04:00
let name = "proposals"
let encoding =
Data_encoding.tup2
Protocol_hash.encoding Ed25519.Public_key_hash.encoding
let key = Key.Vote.proposals
end)
module Ballots =
Make_iterable_data_storage (Ed25519.Public_key_hash)
(struct
type value = Vote_repr.ballot
let key = Key.Vote.ballots
let name = "ballot"
let encoding = Vote_repr.ballot_encoding
end)
end
(** Keys *)
module Public_key =
Make_iterable_data_storage (Ed25519.Public_key_hash)
(struct
type value = Ed25519.Public_key.t
2016-11-14 20:33:32 +04:00
let key = Key.public_keys
2016-09-08 21:13:10 +04:00
let name = "public keys"
let encoding = Ed25519.Public_key.encoding
2016-09-08 21:13:10 +04:00
end)
(** Seed *)
module Seed = struct
type nonce_status =
| Unrevealed of {
nonce_hash: Tezos_hash.Nonce_hash.t ;
delegate_to_reward: Ed25519.Public_key_hash.t ;
2016-09-08 21:13:10 +04:00
reward_amount: Tez_repr.t ;
}
| Revealed of Seed_repr.nonce
module Nonce =
Make_indexed_data_storage(struct
type key = Level_repr.level
type value = nonce_status
let name = "unrevealed nonce hash"
let key = Key.Cycle.unrevealed_nonce_hash
let encoding =
let open Data_encoding in
union [
case ~tag:0
(tup3
Nonce_hash.encoding
Ed25519.Public_key_hash.encoding
Tez_repr.encoding
)
(function
| Unrevealed { nonce_hash ; delegate_to_reward ; reward_amount } ->
Some (nonce_hash, delegate_to_reward, reward_amount)
| _ -> None)
(fun (nonce_hash, delegate_to_reward, reward_amount) ->
Unrevealed { nonce_hash ; delegate_to_reward ; reward_amount }) ;
case ~tag:1
Seed_repr.nonce_encoding
(function
| Revealed nonce -> Some nonce
| _ -> None)
(fun nonce -> Revealed nonce)
]
end)
module For_cycle =
Make_indexed_data_storage(struct
type key = Cycle_repr.t
type value = Seed_repr.seed
let name = "cycle random seed"
let key = Key.Cycle.random_seed
let encoding = Seed_repr.seed_encoding
end)
end
(** Rewards *)
module Rewards = struct
module Next =
Make_single_data_storage(struct
type value = Cycle_repr.t
let name = "reward cycle"
let key = Key.next_cycle_to_be_rewarded
let encoding = Cycle_repr.encoding
end)
module Date =
Make_indexed_data_storage(struct
type key = Cycle_repr.t
type value = Time_repr.t
let name = "reward timestamp"
let key = Key.Cycle.reward_date
let encoding = Time_repr.encoding
end)
module Amount =
Raw_make_iterable_data_storage(struct
type t = Ed25519.Public_key_hash.t * Cycle_repr.t
2016-09-08 21:13:10 +04:00
let prefix = Key.rewards
let length = Ed25519.Public_key_hash.path_length + 1
2016-09-08 21:13:10 +04:00
let to_path (pkh, c) =
Ed25519.Public_key_hash.to_path pkh @
[Int32.to_string (Cycle_repr.to_int32 c)]
let of_path p =
match List.rev p with
| [] -> assert false
| cycle :: rev_pkh ->
(Ed25519.Public_key_hash.of_path_exn (List.rev rev_pkh),
2016-09-08 21:13:10 +04:00
Cycle_repr.of_int32_exn @@ Int32.of_string cycle)
let compare (pkh1, c1) (pkh2, c2) =
let cmp1 = Ed25519.Public_key_hash.compare pkh1 pkh2 in
if Compare.Int.(cmp1 = 0) then Cycle_repr.compare c1 c2
else cmp1
end)(struct
type value = Tez_repr.t
let name = "level miner contract"
let encoding = Tez_repr.encoding
end)
end
let activate ({ context = c } as s) h =
Updater.activate c h >>= fun c -> Lwt.return { s with context = c }
let fork_test_network ({ context = c } as s) protocol expiration =
Updater.fork_test_network c ~protocol ~expiration >>= fun c ->
Lwt.return { s with context = c }
(** Resolver *)
let () =
Storage_functors.register_resolvers
(module Contract_hash)
[ Key.Contract.generic_contract [] ] ;
Storage_functors.register_resolvers
(module Ed25519.Public_key_hash)
[ Key.Contract.pubkey_contract [] ;
Key.public_keys ]