Mina中的支付交易snark

1. 引言

前序博客有:

Mina中目前的交易类型主要有:

  • Coinbase交易:给产块者激励和手续费的交易,为内部交易。
  • Fee_transfer交易:给snark worker手续费的交易,为内部交易。
  • Payment交易:支付交易,为用户交易。
  • Stake_delegation交易:委托交易,为用户交易。
  • apply_parities_unchecked交易:为支持zkApps智能合约创建的交易类型。

在Mina实际代码实现中,Payment交易和Stake_delegation交易共用Signed_command结构。

  • Payment交易示例为:
{
    "data": [
        "Signed_command",
        {
            "payload": {
                "common": {
                    "fee": "0.03",
                    "fee_token": "1",
                    "fee_payer_pk": "B62qoiyAqMVg4hnWFa3mBLsWVJycekKeHLjZi7KdKUDrvdk2o5hyuAe",
                    "nonce": "0",
                    "valid_until": "4294967295",
                    "memo": "E4YVe5YCtgSZuaBo1RiwHFWqtPzV6Eur8xG6JnbzEigit5nZKobQG"
                },
                "body": [
                    "Payment",
                    {
                        "source_pk": "B62qoiyAqMVg4hnWFa3mBLsWVJycekKeHLjZi7KdKUDrvdk2o5hyuAe",
                        "receiver_pk": "B62qpWaQoQoPL5AGta7Hz2DgJ9CJonpunjzCGTdw8KiCCD1hX8fNHuR",
                        "token_id": "1",
                        "amount": "15270000000"
                    }
                ]
            },
            "signer": "B62qoiyAqMVg4hnWFa3mBLsWVJycekKeHLjZi7KdKUDrvdk2o5hyuAe",
            "signature": "7mXTZ6UJj2ZwGzF39ZvU9wnLeDTmHLitwDz7WfVtaXmwToDoVspgauzNKgrgwSzvxxusWsRMgFXyEZ4cTDHKDxmndDYuGLGM"
        }
    ],
    "status": [
        "Applied",
        {
            "fee_payer_account_creation_fee_paid": null,
            "receiver_account_creation_fee_paid": null,
            "created_token": null
        },
        {
            "fee_payer_balance": "0",
            "source_balance": "0",
            "receiver_balance": "18032234944156559"
        }
    ]
}
  • Stake_delegation交易示例为:
{
    "data": [
        "Signed_command",
        {
            "payload": {
                "common": {
                    "fee": "0.0101",
                    "fee_token": "1",
                    "fee_payer_pk": "B62qp5MgMnCrd2bB8pGpPVmAntym3Qfx3vu7wBWwJ5p9e6eU9srYx9v",
                    "nonce": "0",
                    "valid_until": "4294967295",
                    "memo": "E4YM2vTHhWEg66xpj52JErHUBU4pZ1yageL4TVDDpTTSsv8mK6YaH"
                },
                "body": [
                    "Stake_delegation",
                    [
                        "Set_delegate",
                        {
                            "delegator": "B62qp5MgMnCrd2bB8pGpPVmAntym3Qfx3vu7wBWwJ5p9e6eU9srYx9v",
                            "new_delegate": "B62qns9cPvDwckhJXHpWZZ8b8T8oUgoF4Enpax5zNVBYYMtQwHf4Cmp"
                        }
                    ]
                ]
            },
            "signer": "B62qp5MgMnCrd2bB8pGpPVmAntym3Qfx3vu7wBWwJ5p9e6eU9srYx9v",
            "signature": "7mX2tu8ZxQbYkYWCCUKK6CpWhsAtPtiBWYkaa2BuJLJt4p934TfspRi7End8RKm5MBWXpqXGP4WxLv2NNjUPC1UiPM6KvnRn"
        }
    ],
    "status": [
        "Applied",
        {
            "fee_payer_account_creation_fee_paid": null,
            "receiver_account_creation_fee_paid": null,
            "created_token": null
        },
        {
            "fee_payer_balance": "90989900000",
            "source_balance": "90989900000",
            "receiver_balance": "66002906100000"
        }
    ]
}

本文重点关注Payment支付交易的 snark流程。

在Mina中,引入了snark worker来对交易进行snark:
在这里插入图片描述

Mina的实际代码实现中,其snark_worker模块主要提供了2个异步RPC接口:

  • get_work:snark worker通过get_work RPC接口获取待生成snark的work。
  • submit_work:完成snark的work通过submit_work RPC接口广播到网络。

2. Signed_command基本结构

Signed_command基本结构为:

	( Payload.Stable.V2.t
      , Public_key.Stable.V1.t
      , Signature.Stable.V1.t )
      Poly.Stable.V1.t

	type ('payload, 'pk, 'signature) t =
        { payload : 'payload; signer : 'pk; signature : 'signature }

(* payload结构为: *)
type t = (Common.Stable.V2.t, Body.Stable.V2.t) Poly.Stable.V1.t
type ('common, 'body) t = { common : 'common; body : 'body }

(* payload.common结构为: *)
	type t =
        ( Currency.Fee.Stable.V1.t
        , Public_key.Compressed.Stable.V1.t
        , Account_nonce.Stable.V1.t
        , Global_slot.Stable.V1.t
        , Memo.Stable.V1.t )
        Poly.Stable.V2.t
	
	type ('fee, 'public_key, 'nonce, 'global_slot, 'memo) t =
          { fee : 'fee
          ; fee_payer_pk : 'public_key
          ; nonce : 'nonce
          ; valid_until : 'global_slot
          ; memo : 'memo
          }
(* payload.body结构为: *)
	type t = Binable_arg.Stable.V2.t =
        | Payment of Payment_payload.Stable.V2.t
        | Stake_delegation of Stake_delegation.Stable.V1.t

(* payload.body为Payment时的结构为: *)
type t =
      (Public_key.Compressed.Stable.V1.t, Amount.Stable.V1.t) Poly.Stable.V2.t

type ('public_key, 'amount) t =
        { source_pk : 'public_key; receiver_pk : 'public_key; amount : 'amount }

3. Snark worker生成交易snark流程

3.1 Snark worker生成交易snark关键结构

  • 1)of_non_parties_transaction函数中的transaction_in_block参数,为Transaction.Valid.t Transaction_protocol_state.t类型:

    Transaction.Valid.t Transaction_protocol_state.t
    
    type 'a t = { transaction : 'a; block_data : Block_data.Stable.V2.t }
    (* transaction类型,Transaction.Valid.t为: *)
    type t = User_command.Valid.Stable.V2.t Poly.Stable.V2.t
    type 'command t =
            | Command of 'command
            | Fee_transfer of Fee_transfer.Stable.V2.t
            | Coinbase of Coinbase.Stable.V1.t
    
    (* 本文只考虑Command类型,User_command.Valid.Stable.V2.t : *)
    type t =
            ( Signed_command.With_valid_signature.Stable.V2.t
            , Parties.Valid.Stable.V1.t )
            Poly.Stable.V2.t
    type ('u, 's) t = Signed_command of 'u | Parties of 's
    
    (* 本文只考虑Signed_command类型, Signed_command.With_valid_signature.Stable.V2.t: *)
    type t = Stable.V2.t (* 对应为上面第2节的Signed_command结构。 *)
    
    (* block_data类型, Block_data.Stable.V2.t为:*)
    type t = Mina_state.Protocol_state.Body.Value.Stable.V2.t
    	type t = (* 为protocol_state结构 *)
              ( State_hash.Stable.V1.t
              , Blockchain_state.Value.Stable.V2.t
              , Consensus.Data.Consensus_state.Value.Stable.V1.t
              , Protocol_constants_checked.Value.Stable.V1.t )
              Poly.Stable.V1.t
    
    	type ('state_hash, 'blockchain_state, 'consensus_state, 'constants) t =
              { genesis_state_hash : 'state_hash
              ; blockchain_state : 'blockchain_state
              ; consensus_state : 'consensus_state
              ; constants : 'constants
              }
    
  • 2)perform函数中有参数({ instances; fee } as spec : Work.Spec.t)

    (* Work.Spec.t结构为: *)
    type t = Single.Spec.t Work.Spec.t
    type 'single t = 'single Stable.Latest.t =
    { instances : 'single One_or_two.t; fee : Currency.Fee.t }
    
    (* 其中instances类型,One_or_two.t为: *)
    type 'a t = [ `One of 'a | `Two of 'a * 'a ]
    (*  Single.Spec.t结构为: *)
    type t = (Transaction_witness.t, Ledger_proof.t) Work.Single.Spec.t
    
    (* Work.Single.Spec.t类型为: *)
    type ('witness, 'ledger_proof) t =
          ('witness, 'ledger_proof) Stable.Latest.t =
      | Transition of Transaction_snark.Statement.t * 'witness
      | Merge of Transaction_snark.Statement.t * 'ledger_proof * 'ledger_proof
    

    本文只考虑“Transition”情况,其中Transaction_witness.t结构为:

    (* 本文只考虑“Transition”情况: *)
    ( * Transition_witness.t结构为: *)
    type t =
      { transaction : Mina_transaction.Transaction.Stable.V2.t
      ; ledger : Mina_ledger.Sparse_ledger.Stable.V2.t
      ; protocol_state_body : Mina_state.Protocol_state.Body.Value.Stable.V2.t
      ; init_stack : Mina_base.Pending_coinbase.Stack_versioned.Stable.V1.t
      ; status : Mina_base.Transaction_status.Stable.V2.t
      }
    

    本文只考虑“Transition”情况,其中Transaction_snark.Statement.t结构为:

    type t =
        ( Frozen_ledger_hash.Stable.V1.t (* 为Field.t,即为哈希值。 *)
        , Currency.Amount.Stable.V1.t (* 为Unsigned.UInt64.t *)
        , Pending_coinbase.Stack_versioned.Stable.V1.t (* data为Field.t,state中的init和curr均为哈希值。 *)
        , Fee_excess.Stable.V1.t  (* 包含fee_token_l/fee_excess_l/fee_token_r/fee_excess_r 四个字段。 *)
        , unit
        , Local_state.Stable.V1.t )
        Poly.Stable.V2.t
    (*   Poly.Stable.V2.t结构为:  *)
    	type ( 'ledger_hash  (* 为哈希值。 *)
             , 'amount (* 为Unsigned.UInt64.t *)
             , 'pending_coinbase  (* data为Field.t,state中的init和curr均为哈希值。 *)
             , 'fee_excess  (* 包含fee_token_l/fee_excess_l/fee_token_r/fee_excess_r 四个字段。 *)
             , 'sok_digest (* 为uint。 *)
             , 'local_state )
             t =
          { source :
              ( 'ledger_hash  (* 为哈希值。 *)
              , 'pending_coinbase  (* data为Field.t,state中的init和curr均为哈希值。 *)
              , 'local_state )
              Registers.Stable.V1.t
          ; target :
              ( 'ledger_hash  (* 为哈希值。 *)
              , 'pending_coinbase  (* data为Field.t,state中的init和curr均为哈希值。 *)
              , 'local_state )
              Registers.Stable.V1.t
          ; supply_increase : 'amount (* 为Unsigned.UInt64.t *)
          ; fee_excess : 'fee_excess  (* 包含fee_token_l/fee_excess_l/fee_token_r/fee_excess_r 四个字段。 *)
          ; sok_digest : 'sok_digest (* 为uint。 *)
          }
    (* Registers.Stable.V1.t结构为: *)
    type ('ledger, 'pending_coinbase_stack, 'local_state) t =
      { ledger : 'ledger (* 为哈希值。 *)
      ; pending_coinbase_stack : 'pending_coinbase_stack (* data为Field.t,state中的init和curr均为哈希值。 *)
      ; local_state : 'local_state
      }
    

    其中Pending_coinbase.Stack_versioned.Stable.V1.t结构为:

    (* Pending_coinbase.Stack_versioned.Stable.V1.t结构为: *)
    type t =
        (Coinbase_stack.Stable.V1.t, State_stack.Stable.V1.t) Poly.Stable.V1.t
    type ('data_stack, 'state_stack) t =
          { data : 'data_stack; state : 'state_stack }
    (* data类型,Coinbase_stack.Stable.V1.t为:Field.t *)
    (*state类型, State_stack.Stable.V1.t为: *)
    type t = Stack_hash.Stable.V1.t Poly.Stable.V1.t
    type 'stack_hash t = { init : 'stack_hash; curr : 'stack_hash }
    (* 其中init/curr均为 Stack_hash.Stable.V1.t ,本质即为Filed.t,即为哈希值 *)
    

    其中Fee_excess.Stable.V1.t结构为:

    (* Fee_excess.Stable.V1.t 结构为: *)
    type t =
      ( Token_id.Stable.V1.t (* 为Pickles.Backend.Tick.Field.Stable.V1.t,对应Tick曲线的scalar域 *)
      , (Fee.Stable.V1.t, Sgn.Stable.V1.t) Signed_poly.Stable.V1.t ) (* 其中的magnitude字段为Unsigned.UInt64.t,sgn字段为枚举类型Pos|Neg *)
      Poly.Stable.V1.t (* 包含fee_token_l/fee_excess_l/fee_token_r/fee_excess_r 四个字段。 *)
    
    (* Poly.Stable.V1.t结构为: *)
    type ('token, 'fee) t =
        { fee_token_l : 'token
        ; fee_excess_l : 'fee
        ; fee_token_r : 'token
        ; fee_excess_r : 'fee
        }
    (* Signed_poly.Stable.V1.t 结构为: *)
    type ('magnitude, 'sgn) t = { magnitude : 'magnitude; sgn : 'sgn }
    (* 其中magnitude类型,Fee.Stable.V1.t为:Unsigned.UInt64.t *)
    (* 其中sgn类型, Sgn.Stable.V1.t枚举类型Pos|Neg:*)
    type t = Sgn_type.Sgn.Stable.V1.t = Pos | Neg
    

    其中Local_state.Stable.V1.t结构为:【src/lib/transaction_logic/parties_logic.ml中的Local_state模块有:】

    type t =
          ( Mina_base.Stack_frame.Digest.Stable.V1.t
          , Mina_base.Call_stack_digest.Stable.V1.t
          , Token_id.Stable.V1.t
          , ( Currency.Amount.Stable.V1.t
            , Sgn.Stable.V1.t )
            Currency.Signed_poly.Stable.V1.t
          , Ledger_hash.Stable.V1.t
          , bool
          , Parties.Transaction_commitment.Stable.V1.t
          , Transaction_status.Failure.Collection.Stable.V1.t )
          Stable.V1.t
    
    type ( 'stack_frame
           , 'call_stack
           , 'token_id
           , 'excess
           , 'ledger
           , 'bool
           , 'comm
           , 'failure_status_tbl )
           t =
        { stack_frame : 'stack_frame
        ; call_stack : 'call_stack
        ; transaction_commitment : 'comm
        ; full_transaction_commitment : 'comm
        ; token_id : 'token_id
        ; excess : 'excess
        ; ledger : 'ledger
        ; success : 'bool
        ; failure_status_tbl : 'failure_status_tbl
        }	
    
  • 3)perform_single中的参数 message:Mina_base.Sok_message.t:【其中的“fee”表示snark worker对其提供的snark work的定价;“prover”为snark worker用于生成交易snark的公钥。】

    (* Sok_message.t类型为: *)
    type t =
      { fee : Currency.Fee.Stable.V1.t
      ; prover : Public_key.Compressed.Stable.V1.t
      }
    
  • 4)perform_single中有一个隐含参数“single: single_spec”,为Work.Single.Spec.t类型。

3.2 Snark worker生成交易snark关键流程

Snark worker生成交易snark流程为:

  • 1)src/lib/snark_worker/prod.ml中的perform_single
    let perform (s : Worker_state.t) public_key
          ({ instances; fee } as spec : Work.Spec.t) =
        One_or_two.Deferred_result.map instances ~f:(fun w ->
            let open Deferred.Or_error.Let_syntax in
            let%map proof, time =
              perform_single s
                ~message:(Mina_base.Sok_message.create ~fee ~prover:public_key)
                w
            in
            ( proof
            , (time, match w with Transition _ -> `Transition | Merge _ -> `Merge)
            ) )
            
    val perform_single :
           Worker_state.t
        -> message:Mina_base.Sok_message.t
        -> (Transaction_witness.t, Ledger_proof.t) Work.Single.Spec.t (* 对应隐含参数“single: signle_spec” *)
        -> (Ledger_proof.t * Time.Span.t) Deferred.Or_error.t
    
    let perform_single ({ m; cache; proof_level } : Worker_state.t) ~message = (* 其中还有一个隐含参数“single: single_spec”,为Work.Single.Spec.t类型。 *)
    
    ||
    \/
  • 2)只考虑“Work.Single.Spec.Transition”类型,不考虑“Merge”类型。
    ||
    \/
  • 3)若交易是“Parties”类型,则额外处理;否则,对于“Signed_commnad”/“Fee_transfer”/"Coinbase"类型的交易,同一调用Transaction_snark的of_non_parties_transaction函数来生成相应的proof,会将proof添加到cache中。
    						M.of_non_parties_transaction
                                ~statement:{ input with sok_digest }
                                { Transaction_protocol_state.Poly.transaction =
                                    t
                                ; block_data = w.protocol_state_body
                                } (* 为transaction_in_block参数,为Transaction.Valid.t Transaction_protocol_state.t类型 *)
                                ~init_stack:w.init_stack
                                (unstage
                                   (Mina_ledger.Sparse_ledger.handler w.ledger) )
     
     val of_non_parties_transaction :
           statement:Statement.With_sok.t
        -> init_stack:Pending_coinbase.Stack.t
        -> Transaction.Valid.t Transaction_protocol_state.t
        -> Tick.Handler.t
        -> t Async.Deferred.t
                                
    let of_non_parties_transaction ~statement ~init_stack transaction_in_block
          handler =
    
    transaction_in_block.transactiontransaction,取transaction_in_block.block_datastate_body
    ||
    \/
  • 4)对transaction仍然调用Transaction_union.of_transaction,结果仍命名为transaction——目的是:恢复Signed_command结构,会在common内插入fee_token = Token_id.default字段,在body内插入token_id = Token_id.default字段。
    ||
    \/

参考资料

[1] Guide to Snark Work

附录1. Mina系列博客

Mina系列博客有:

猜你喜欢

转载自blog.csdn.net/mutourend/article/details/125739139