Client: add a claim operation that activate a commitment account
This commit is contained in:
parent
aeaf2a240c
commit
020ef19460
@ -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/*)
|
||||
))
|
||||
|
8
src/bin_client/test/king_commitment.json
Normal file
8
src/bin_client/test/king_commitment.json
Normal 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"
|
||||
}
|
8
src/bin_client/test/queen_commitment.json
Normal file
8
src/bin_client/test/queen_commitment.json
Normal 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"
|
||||
}
|
@ -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
|
||||
|
@ -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 =
|
||||
|
@ -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 ->
|
||||
|
@ -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
|
||||
|
@ -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 ->
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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" ]
|
||||
|
@ -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
|
||||
|
@ -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 () ->
|
||||
|
Loading…
Reference in New Issue
Block a user