Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/lib/transaction_logic/mina_transaction_logic.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,9 @@ module Make (L : Ledger_intf.S) : S with type ledger := L.t = struct
~f:Party.Update.Timing_info.to_account_timing timing
}

let is_timed (a : t) =
match a.timing with Account_timing.Untimed -> false | _ -> true

let set_token_id (a : t) (id : Token_id.t) : t = { a with token_id = id }

let balance (a : t) : Balance.t = a.balance
Expand Down
7 changes: 6 additions & 1 deletion src/lib/transaction_logic/parties_logic.ml
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,8 @@ module type Account_intf = sig

val set_timing : t -> timing -> t

val is_timed : t -> bool

val set_token_id : t -> token_id -> t

type balance
Expand Down Expand Up @@ -1075,13 +1077,16 @@ module Make (Inputs : Inputs_intf) = struct
let a = Account.set_token_id a (Party.token_id party) in
let party_token = Party.token_id party in
let party_token_is_default = Token_id.(equal default) party_token in
let account_is_untimed = Bool.not (Account.is_timed a) in
(* Set account timing for new accounts, if specified. *)
let a, local_state =
let timing = Party.Update.timing party in
let local_state =
Local_state.add_check local_state
Update_not_permitted_timing_existing_account
Bool.(account_is_new ||| Set_or_keep.is_keep timing)
Bool.(
Set_or_keep.is_keep timing
||| (account_is_untimed &&& signature_verifies))
in
let timing =
Set_or_keep.set_or_keep ~if_:Timing.if_ timing (Account.timing a)
Expand Down
80 changes: 80 additions & 0 deletions src/lib/transaction_snark/test/account_timing/account_timing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1563,4 +1563,84 @@ let%test_module "account timing check" =
~state_view ledger parties
in
check_zkapp_failure Transaction_status.Failure.Overflow result ) )

let%test_unit "zkApp command, create timed account with wrong authorization"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you write a test for correct authorization and a test for the new case (fails when the account is already timed)?

=
let ledger_init_state =
List.map keypairs ~f:(fun keypair ->
let balance = Currency.Amount.of_int 100_000_000_000_000 in
let nonce = Mina_numbers.Account_nonce.zero in
(keypair, balance, nonce, Account_timing.Untimed) )
|> Array.of_list
in
let sender_keypair = List.hd_exn keypairs in
let zkapp_keypair = Signature_lib.Keypair.create () in
let (create_timed_account_spec : Transaction_snark.For_tests.Spec.t) =
{ sender = (sender_keypair, Account.Nonce.zero)
; fee = Currency.Fee.of_int 1_000_000
; fee_payer = None
; receivers = []
; amount = Currency.Amount.of_int 50_000_000_000_000
; zkapp_account_keypairs = [ zkapp_keypair ]
; memo =
Signed_command_memo.create_from_string_exn
"zkApp create timed account"
; new_zkapp_account = true
; snapp_update =
(let timing =
Zkapp_basic.Set_or_keep.Set
( { initial_minimum_balance =
Currency.Balance.of_int 1_000_000_000
; cliff_time = Mina_numbers.Global_slot.of_int 10
; cliff_amount = Currency.Amount.of_int 1_000_000_000
; vesting_period = Mina_numbers.Global_slot.of_int 10
; vesting_increment = Currency.Amount.of_int 1_000_000_000
}
: Party.Update.Timing_info.value )
in
{ Party.Update.dummy with timing } )
; current_auth = Permissions.Auth_required.Proof
; call_data = Snark_params.Tick.Field.zero
; events = []
; sequence_events = []
; protocol_state_precondition = None
; account_precondition = None
}
in
let timing_account_id =
Account_id.create
(zkapp_keypair.public_key |> Signature_lib.Public_key.compress)
Token_id.default
in
let create_timed_account_parties, _, _, _ =
( Transaction_snark.For_tests.deploy_snapp ~no_auth:true
~constraint_constants create_timed_account_spec
, timing_account_id
, create_timed_account_spec.snapp_update
, zkapp_keypair )
in
let gen =
Quickcheck.Generator.return
(ledger_init_state, create_timed_account_parties)
in
Quickcheck.test
~seed:
(`Deterministic
"zkapp command, create timed account with wrong authorization" )
~sexp_of:[%sexp_of: Mina_ledger.Ledger.init_state * Parties.t] ~trials:1
gen ~f:(fun (ledger_init_state, create_timed_account_parties) ->
Mina_ledger.Ledger.with_ephemeral_ledger
~depth:constraint_constants.ledger_depth ~f:(fun ledger ->
Mina_ledger.Ledger.apply_initial_ledger_state ledger
ledger_init_state ;
let state_view =
Transaction_snark_tests.Util.genesis_state_view
in
let result =
Mina_ledger.Ledger.apply_parties_unchecked ~state_view
~constraint_constants ledger create_timed_account_parties
in
check_zkapp_failure
Transaction_status.Failure
.Update_not_permitted_timing_existing_account result ) )
end )
52 changes: 32 additions & 20 deletions src/lib/transaction_snark/transaction_snark.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,12 @@ module Base = struct
let set_timing (account : t) (timing : timing) : t =
{ account with data = { account.data with timing } }

let is_timed ({ data = account; _ } : t) =
let open Account.Poly in
let open Account.Timing.As_record in
let { is_timed; _ } = account.timing in
is_timed

let set_token_id (account : t) (token_id : Token_id.Checked.t) : t =
account_with_hash { account.data with token_id }

Expand Down Expand Up @@ -4451,7 +4457,7 @@ module For_tests = struct
, `Txn_commitment commitment
, `Full_txn_commitment full_commitment )

let deploy_snapp ~constraint_constants (spec : Spec.t) =
let deploy_snapp ?(no_auth = false) ~constraint_constants (spec : Spec.t) =
let `VK vk, `Prover _trivial_prover =
create_trivial_snapp ~constraint_constants ()
in
Expand All @@ -4463,15 +4469,17 @@ module For_tests = struct
|| (spec.new_zkapp_account && List.length spec.zkapp_account_keypairs = 1) ) ;
let update_vk =
let update = spec.snapp_update in
{ update with
verification_key = Zkapp_basic.Set_or_keep.Set vk
; permissions =
Zkapp_basic.Set_or_keep.Set
{ Permissions.user_default with
edit_state = Permissions.Auth_required.Proof
; edit_sequence_state = Proof
}
}
if no_auth then update
else
{ update with
verification_key = Zkapp_basic.Set_or_keep.Set vk
; permissions =
Zkapp_basic.Set_or_keep.Set
{ Permissions.user_default with
edit_state = Permissions.Auth_required.Proof
; edit_sequence_state = Proof
}
}
in
let ( `Parties { Parties.fee_payer; other_parties; memo }
, `Sender_party sender_party
Expand All @@ -4487,16 +4495,20 @@ module For_tests = struct
in
let snapp_parties =
List.map snapp_parties_keypairs ~f:(fun (snapp_party, keypair) ->
let commitment =
if snapp_party.body.use_full_commitment then full_commitment
else commitment
in
let signature =
Signature_lib.Schnorr.Chunked.sign keypair.private_key
(Random_oracle.Input.Chunked.field commitment)
in
( { body = snapp_party.body; authorization = Signature signature }
: Party.Wire.t ) )
if no_auth then
( { body = snapp_party.body; authorization = None_given }
: Party.Wire.t )
else
let commitment =
if snapp_party.body.use_full_commitment then full_commitment
else commitment
in
let signature =
Signature_lib.Schnorr.Chunked.sign keypair.private_key
(Random_oracle.Input.Chunked.field commitment)
in
( { body = snapp_party.body; authorization = Signature signature }
: Party.Wire.t ) )
in
let other_parties = Option.to_list sender_party @ snapp_parties in
let parties : Parties.t =
Expand Down
3 changes: 2 additions & 1 deletion src/lib/transaction_snark/transaction_snark.mli
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,8 @@ module For_tests : sig
end

val deploy_snapp :
constraint_constants:Genesis_constants.Constraint_constants.t
?no_auth:bool
-> constraint_constants:Genesis_constants.Constraint_constants.t
-> Spec.t
-> Parties.t

Expand Down