Client: add a claim operation that activate a commitment account

This commit is contained in:
Grégoire Henry 2018-04-17 10:50:23 +02:00
parent aeaf2a240c
commit 020ef19460
14 changed files with 199 additions and 14 deletions

View File

@ -4,6 +4,8 @@
((name runtest_basic.sh)
(deps (sandbox.json
protocol_parameters.json
king_commitment.json
queen_commitment.json
test_lib.inc.sh
(glob_files contracts/*)
))

View File

@ -0,0 +1,8 @@
{
"mnemonic": ["envelope", "hospital", "mind", "sunset", "cancel", "muscle", "leisure", "thumb", "wine", "market", "exit", "lucky", "style", "picnic", "success"],
"secret": "0f39ed0b656509c2ecec4771712d9cddefe2afac",
"amount": "23932454669343",
"pkh": "tz1MawerETND6bqJqx8GV3YHUrvMBCDasRBF",
"password": "z0eZHQQGKt",
"email": "cjgfoqmk.wpxnvnup@tezos.example.org"
}

View File

@ -0,0 +1,8 @@
{
"mnemonic": ["flag", "quote", "will", "valley", "mouse", "chat", "hold", "prosper", "silk", "tent", "cruel", "cause", "demise", "bottom", "practice"],
"secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4",
"amount": "72954577464032",
"pkh": "tz1X4maqF9tC1Yn4jULjHRAyzjAtc25Z68TX",
"password": "MHErskWPE6",
"email": "oklmcktr.ztljnpzc@tezos.example.org"
}

View File

@ -26,6 +26,8 @@ sleep 1
key1=foo
key2=bar
key3=boo
key4=king
key5=queen
$client gen keys $key1
$client gen keys $key2 --sig secp256k1
@ -106,6 +108,20 @@ $client transfer 400,000 from bootstrap1 to bootstrap5 -fee 0
sleep 1
$client bake for bootstrap1 -max-priority 512
$client get balance for bootstrap5 | assert "4,000,000 ꜩ"
sleep 1
$client activate account $key4 with king_commitment.json --no-confirmation
$client activate account $key5 with queen_commitment.json --no-confirmation
$client bake for bootstrap1 -max-priority 512
sleep 1
$client get balance for $key4 | assert "23,932,454.669,343 ꜩ"
$client get balance for $key5 | assert "72,954,577.464,032 ꜩ"
$client transfer 10 from $key4 to $key5
echo
echo End of test

View File

@ -159,9 +159,8 @@ let append cctxt loc buf =
sign cctxt loc buf >>|? fun signature ->
Signature.concat buf signature
let gen_keys ?(force=false) ?algo ?seed (cctxt : #Client_context.io_wallet) name =
let public_key_hash, public_key, secret_key =
Signature.generate_key ?algo ?seed () in
let register_key cctxt ?(force=false)
(public_key_hash, public_key, secret_key) name =
Secret_key.add ~force cctxt name
(Secret_key_locator.of_unencrypted secret_key) >>=? fun () ->
Public_key.add ~force cctxt name
@ -170,6 +169,9 @@ let gen_keys ?(force=false) ?algo ?seed (cctxt : #Client_context.io_wallet) name
cctxt name public_key_hash >>=? fun () ->
return ()
let gen_keys ?(force=false) ?algo ?seed (cctxt : #Client_context.io_wallet) name =
let key = Signature.generate_key ?algo ?seed () in
register_key cctxt ~force key name
let gen_keys_containing ?(prefix=false) ?(force=false) ~containing ~name (cctxt : #Client_context.full) =
let unrepresentable =

View File

@ -116,6 +116,13 @@ val gen_keys :
?seed:Ed25519.Seed.t ->
#Client_context.io_wallet -> string -> unit tzresult Lwt.t
val register_key :
#Client_context.wallet ->
?force:bool ->
(Signature.Public_key_hash.t *
Signature.Public_key.t *
Signature.Secret_key.t) -> string -> unit tzresult Lwt.t
val gen_keys_containing :
?prefix:bool ->
?force:bool ->

View File

@ -180,6 +180,12 @@ let no_print_source_flag =
This option disables this behaviour."
()
let no_confirmation =
switch
~long:"no-confirmation"
~doc:"don't print wait for the operation to be confirmed."
()
module Daemon = struct
let baking_switch =
switch

View File

@ -26,6 +26,7 @@ val force_switch: (bool, Proto_alpha.full) Clic.arg
val endorsement_delay_arg: (int, Proto_alpha.full) Clic.arg
val no_print_source_flag: (bool, Proto_alpha.full) Clic.arg
val no_confirmation: (bool, Proto_alpha.full) Clic.arg
val tez_arg :
default:string ->

View File

@ -285,3 +285,77 @@ let wait_for_operation_inclusion
end stream >>= fun _ ->
stop () ;
return ()
type activation_key =
{ pkh : Ed25519.Public_key_hash.t ;
amount : Tez.t ;
secret : Blinded_public_key_hash.secret ;
mnemonic : string list ;
password : string ;
email : string ;
}
let activation_key_encoding =
let open Data_encoding in
conv
(fun { pkh ; amount ; secret ; mnemonic ; password ; email } ->
( pkh, amount, secret, mnemonic, password, email ))
(fun ( pkh, amount, secret, mnemonic, password, email ) ->
{ pkh ; amount ; secret ; mnemonic ; password ; email })
(obj6
(req "pkh" Ed25519.Public_key_hash.encoding)
(req "amount" Tez.encoding)
(req "secret" Blinded_public_key_hash.secret_encoding)
(req "mnemonic" (list string))
(req "password" string)
(req "email" string))
let read_key key =
match Bip39.of_words key.mnemonic with
| None ->
failwith ""
| Some t ->
(* TODO: unicode normalization (NFKD)... *)
let sk = Bip39.to_seed ~passphrase:(key.email ^ key.password) t in
let sk = Cstruct.(to_bigarray (sub sk 0 32)) in
let sk : Signature.Secret_key.t =
Ed25519 (Data_encoding.Binary.of_bytes_exn Ed25519.Secret_key.encoding sk) in
let pk = Signature.Secret_key.to_public_key sk in
let pkh = Signature.Public_key.hash pk in
return (pkh, pk, sk)
let claim_commitment (cctxt : #Proto_alpha.full)
?confirmations ?force block key name =
read_key key >>=? fun (pkh, pk, sk) ->
fail_unless (Signature.Public_key_hash.equal pkh (Ed25519 key.pkh))
(failure "@[<v 2>Inconsistent activation key:@ \
Computed pkh: %a@ \
Embedded pkh: %a @]"
Signature.Public_key_hash.pp pkh
Ed25519.Public_key_hash.pp key.pkh) >>=? fun () ->
let op = [ Activation { id = key.pkh ; secret = key.secret } ] in
Block_services.info cctxt block >>=? fun bi ->
Alpha_services.Forge.Anonymous.operations
cctxt block ~branch:bi.hash op >>=? fun bytes ->
Shell_services.inject_operation
cctxt ~chain_id:bi.chain_id bytes >>=? fun oph ->
operation_submitted_message cctxt oph >>=? fun () ->
begin
match confirmations with
| None ->
Client_keys.register_key cctxt ?force (pkh, pk, sk) name >>=? fun () ->
return ()
| Some confirmations ->
cctxt#message "Waiting for the operation to be included..." >>= fun () ->
wait_for_operation_inclusion ~confirmations cctxt oph >>=? fun () ->
Client_keys.register_key cctxt ?force (pkh, pk, sk) name >>=? fun () ->
Alpha_services.Contract.balance
cctxt (`Head 0) (Contract.implicit_contract pkh) >>=? fun balance ->
cctxt#message "Account %s (%a) created with %s%a."
name
Signature.Public_key_hash.pp pkh
Client_proto_args.tez_sym
Tez.pp balance >>= fun () ->
return ()
end

View File

@ -141,3 +141,24 @@ val wait_for_operation_inclusion:
?confirmations:int ->
Operation_hash.t ->
unit tzresult Lwt.t
type activation_key =
{ pkh : Ed25519.Public_key_hash.t ;
amount : Tez.t ;
secret : Blinded_public_key_hash.secret ;
mnemonic : string list ;
password : string ;
email : string ;
}
val activation_key_encoding: activation_key Data_encoding.t
val claim_commitment:
#Proto_alpha.full ->
?confirmations:int ->
?force:bool ->
Block_services.block ->
activation_key ->
string ->
unit tzresult Lwt.t

View File

@ -8,7 +8,8 @@
tezos-protocol-environment
tezos-shell-services
tezos-client-base
tezos-rpc))
tezos-rpc
bip39))
(library_flags (:standard -linkall))
(flags (:standard -w -9+27-30-32-40@8
-safe-string

View File

@ -28,6 +28,13 @@ let report_michelson_errors ?(no_print_source=false) ~msg (cctxt : #Client_conte
| Ok data ->
Lwt.return (Some data)
let file_parameter =
Clic.parameter (fun _ p ->
if not (Sys.file_exists p) then
failwith "File doesn't exist: '%s'" p
else
return p)
let group =
{ Clic.name = "context" ;
title = "Block contextual commands (see option -block)" }
@ -253,6 +260,32 @@ let commands () =
operation_submitted_message cctxt oph
end;
command ~group ~desc:"Register and activate a predefined account using the provided activation key."
(args2 (Secret_key.force_switch ()) (Client_proto_args.no_confirmation))
(prefixes [ "activate" ; "account" ]
@@ Secret_key.fresh_alias_param
@@ prefixes [ "with" ]
@@ param ~name:"activation_key"
~desc:"Activation key (as JSON file) obtained from the Tezos foundation (or the Alphanet faucet)."
file_parameter
@@ stop)
(fun (force, no_confirmation) name activation_key_file cctxt ->
Secret_key.of_fresh cctxt force name >>=? fun name ->
Lwt_utils_unix.Json.read_file activation_key_file >>=? fun json ->
match Data_encoding.Json.destruct
Client_proto_context.activation_key_encoding
json with
| exception (Data_encoding.Json.Cannot_destruct _ as exn) ->
Format.kasprintf (fun s -> failwith "%s" s)
"Invalid activation file: %a %a"
(fun ppf -> Data_encoding.Json.print_error ppf) exn
Data_encoding.Json.pp json
| key ->
let confirmations =
if no_confirmation then None else Some 0 in
claim_commitment cctxt cctxt#block ?confirmations ~force key name
);
command ~group:alphanet ~desc: "Activate a protocol (Alphanet dictator only)."
no_options
(prefixes [ "activate" ; "protocol" ]
@ -306,6 +339,7 @@ let commands () =
wait_for_operation_inclusion ctxt
~confirmations ~predecessors operation_hash
end ;
command ~group:alphanet ~desc: "Fork a test protocol (Alphanet dictator only)."
no_options
(prefixes [ "fork" ; "test" ; "protocol" ]

View File

@ -4,6 +4,7 @@
((name tezos_client_alpha_commands)
(public_name tezos-client-alpha-commands)
(libraries (tezos-base
tezos-stdlib-unix
tezos-protocol-alpha
tezos-protocol-environment
tezos-shell-services
@ -16,6 +17,7 @@
(flags (:standard -w -9+27-30-32-40@8
-safe-string
-open Tezos_base__TzPervasives
-open Tezos_stdlib_unix
-open Tezos_shell_services
-open Tezos_client_base
-open Tezos_client_alpha

View File

@ -36,7 +36,7 @@ type error += Too_early_double_baking_evidence
of { level: Raw_level.t ; current: Raw_level.t } (* `Temporary *)
type error += Outdated_double_baking_evidence
of { level: Raw_level.t ; last: Raw_level.t } (* `Permanent *)
type error += Invalid_activation
type error += Invalid_activation of { pkh : Ed25519.Public_key_hash.t }
type error += Wrong_activation_secret
let () =
@ -295,11 +295,14 @@ let () =
~title:"Invalid activation"
~description:"The given key has already been activated or the given \
key does not correspond to any preallocated contract"
~pp:(fun ppf () ->
Format.fprintf ppf "Invalid activation.")
Data_encoding.unit
(function Invalid_activation -> Some () | _ -> None)
(fun () -> Invalid_activation) ;
~pp:(fun ppf pkh ->
Format.fprintf ppf "Invalid activation. The public key %a does \
not match any commitment."
Ed25519.Public_key_hash.pp pkh
)
Data_encoding.(obj1 (req "pkh" Ed25519.Public_key_hash.encoding))
(function Invalid_activation { pkh } -> Some pkh | _ -> None)
(fun pkh -> Invalid_activation { pkh } ) ;
register_error_kind
`Permanent
~id:"operation.wrong_activation_secret"
@ -579,9 +582,9 @@ let apply_anonymous_operation ctxt _delegate origination_nonce kind =
| Activation { id = pkh ; secret } ->
let h_pkh = Unclaimed_public_key_hash.of_ed25519_pkh pkh in
Commitment.get_opt ctxt h_pkh >>=? function
| None -> fail Invalid_activation
| Some { blinded_public_key_hash = submitted_bpkh ; amount } ->
let blinded_pkh = Blinded_public_key_hash.of_ed25519_pkh secret pkh in
| None -> fail (Invalid_activation { pkh })
| Some { blinded_public_key_hash = blinded_pkh ; amount } ->
let submitted_bpkh = Blinded_public_key_hash.of_ed25519_pkh secret pkh in
fail_unless
Blinded_public_key_hash.(blinded_pkh = submitted_bpkh)
Wrong_activation_secret >>=? fun () ->