Mina早期项目名为Coda,2020年品牌重塑为Mina Protocol。
Mina致力于成为web3的隐私和安全层。
Mina为世界上最轻的区块链,其大小约为22KB,使得用户可快速直接地从其手机和其它链访问Mina的当前状态。
Mina主要特性有:
相关开源代码见:
Mina中的交易类型分为:
let to_preunion (t : Transaction.t) =
match t with
| Command (Signed_command x) ->
`Transaction (Transaction.Command x)
| Fee_transfer x ->
`Transaction (Fee_transfer x)
| Coinbase x ->
`Transaction (Coinbase x)
| Command (Parties x) ->
`Parties x
Mina中的区块类型分为:
对应地有:
(* block.ml: *)
type t = { header : Header.Stable.V1.t; body : Body.Stable.V1.t }
(* Header: *)
type t =
{ protocol_state : Protocol_state.Value.Stable.V2.t
; protocol_state_proof : Proof.Stable.V2.t [@sexp.opaque]
; delta_block_chain_proof :
(* TODO: abstract *)
State_hash.Stable.V1.t * State_body_hash.Stable.V1.t list
; current_protocol_version : Protocol_version.Stable.V1.t
; proposed_protocol_version_opt : Protocol_version.Stable.V1.t option
; body_reference : Body_reference.Stable.V1.t (* 当前为对Body的哈希值 *)
}
(* Body: *)
type t = { staged_ledger_diff : Staged_ledger_diff.Stable.V2.t }
(* external_transitioin.ml: *)
type t =
{ protocol_state : Protocol_state.Value.Stable.V2.t
; protocol_state_proof : Proof.Stable.V2.t [@sexp.opaque]
; staged_ledger_diff : Staged_ledger_diff.Stable.V2.t
; delta_transition_chain_proof :
State_hash.Stable.V1.t * State_body_hash.Stable.V1.t list
; current_protocol_version : Protocol_version.Stable.V1.t
; proposed_protocol_version_opt : Protocol_version.Stable.V1.t option
; mutable validation_callback : Validate_content.t (* 有:type t = unit,主要用作a stub to keep the bin_io for external transition from changing *)
}
(* 其中validation_callback为enum类型:接受、拒绝、忽略、超时 *)
enum ValidationResult {
accept @0;
reject @1;
ignore @2;
}
(* 在mina_net2/subscription.ml中的handle_and_validate()函数内有: *)
match%map Validation_callback.await validation_callback with
| Some `Accept ->
`Validation_result Accept
| Some `Reject ->
`Validation_result Reject
| Some `Ignore ->
`Validation_result Ignore
| None ->
`Validation_timeout )
ChainSafe/mina-rs的结构体定义为:
pub struct ExternalTransition {
/// The blockchain state, including consensus and the ledger
pub protocol_state: ProtocolStateV1,
/// Proof that the protocol state and entire history of the chain is valid
pub protocol_state_proof: ProtocolStateProofV1,
/// Diff of the proposed next state of the blockchain
pub staged_ledger_diff: StagedLedgerDiffV1,
/// Proof that the block was produced within the allotted slot time
pub delta_transition_chain_proof: DeltaTransitionChainProof,
/// Current protocol version
pub current_protocol_version: ProtocolVersionV1,
/// Proposed protocol version
pub proposed_protocol_version_opt: Option<ProtocolVersionV1>,
/// Callback used for validating external transition received over the network.
/// This is not actually send over the network but requires a unit type to meet the
/// serialization requirements
pub validation_callback: (),
}
(* snark_transition.ml: *)
type ( 'blockchain_state (* 为protocol_state中的一个元素 *)
, 'consensus_transition (* consensus/proof_of_stake.ml中赋值为let consensus_transition = block_data.global_slot*)
, 'pending_coinbase_update )
t =
{ blockchain_state : 'blockchain_state
; consensus_transition : 'consensus_transition (* 实际即为global slot *)
; pending_coinbase_update : 'pending_coinbase_update
}
(* pending_coinbase_update结构为: *)
type t = (Action.Stable.V1.t, Amount.Stable.V1.t) Poly.Stable.V1.t
(* Action类型有: *)
type t =
| Update_none
| Update_one
| Update_two_coinbase_in_first
| Update_two_coinbase_in_second
【通常global slot >= blockchain length ,因为Mina中支持空块。blockchain length为Mina链上的实际非空区块。global slot = epoch * 7140 + slot,即有111965=15 * 7140+4865。】
Role | Description | Storage Requirements |
---|---|---|
Archive Node | archival service tracking chain dynamics and state | { 1. genesis ledger, 2. daemon config, 3. runtime state, 4. postgres database state } |
Block Producer | active participant in a chain’s block production protocol | { 1. genesis ledger, 2. wallet keys, 3. daemon config, 4. runtime state } |
Seed Node | standalone client acting as a bootstrapping and peer discovery source for network participants | { 1. genesis ledger, 2. daemon config, 3. runtime state } |
SNARK coordinator/worker | entities responsible for producing SNARK proofs used in validating chain transactions | { 1. genesis ledger, 2. wallet keys, 3. daemon config, 4. runtime state } |
User agent | (test) bot tasked with sending chain transactions as a means of fabricating network/chain dynamics | { 1. genesis ledger, 2. wallet keys, 3. daemon config, 4. runtime state } |
Faucet | (test) bot tasked with dispersing testnet funds to participants as means of enabling network activity | { 1. genesis ledger, 2. wallet keys, 3. daemon config, 4. runtime state } |
Echo Service | (test) bot tasked with echo’ing participant transactions for simulating an end-to-end transaction experience | { 1. genesis ledger, 2. wallet keys, 3. daemon config, 4. runtime state } |
Mina的共识算法为Ouroboros Samisika,是一种provably-secure proof-of-stake (PoS)共识协议 for succinct blockchains。
Ouroboros Samisika是在Cardano Ouroboros proof-of-stake的基础上进行了改进:最大限度地提高了共识包容性。
在Mina链上,所有参与者都充当全节点,任何人都可参与共识并保护区块链。
Mina大大减少了每个用户需要下载的数据量。参与者不是从一开始就验证整个链,而是使用递归零知识证明(或zk-SNARK)完全验证网络和交易。节点可以存储小的proof,而不是整个链。而且因为它的大小是一致的,Mina保持可访问性——即使它扩展到许多用户并积累了多年的交易数据。
Mina会将整个区块链的状态捕获为一个轻量级快照,并将其发送出去,而不是将链本身发送出去。当网络中的下一个区块被创建时,它会拍摄自身的快照——以区块链上一个状态的快照为背景。这张新的快照将依次用作下一个区块的背景,依此类推。令人惊讶的是,虽然快照可以包含无限量信息的proof,但快照的大小始终保持不变。
Mina的区块结构主要为:【可将protocol_state
看成是传统的区块头,staged_ledger_diff
看成是传统的区块body。】
Field | Type | Description |
---|---|---|
version |
u8 (= 0x01) |
Block structure version |
protocol_state |
Protocol_state.Value.Stable.V1.t |
The blockchain state, including consensus and the ledger |
protocol_state_proof |
Proof.Stable.V1.t sexp_opaque |
Proof that the protocol state and entire history of the chain is valid |
staged_ledger_diff |
Staged_ledger_diff.Stable.V1.t |
Diff of the proposed next state of the blockchain |
delta_transition_chain_proof |
State_hash.Stable.V1.t * State_body_hash.Stable.V1.t list |
Proof that the block was produced within the allotted slot time |
current_protocol_version |
Protocol_version.Stable.V1.t |
Current protocol version |
proposed_protocol_version_opt |
Protocol_version.Stable.V1.t option |
Proposed protocol version |
Mina区块内容JSON示例见:
详细的参数含义见:
Mina主网genesis block结构为:
{
"data":{
"block":{
"blockHeight":1,
"canonical":true,
"creator":"B62qiy32p8kAKnny8ZFwoMhYpBppM1DWVCqAPBYNcXnsAHhnfAAuXgg",
"creatorAccount":{
"publicKey":"B62qiy32p8kAKnny8ZFwoMhYpBppM1DWVCqAPBYNcXnsAHhnfAAuXgg"
},
"dateTime":"2021-03-17T00:00:00Z",
"protocolState":{
"blockchainState":{
"date":"1615939200000",
"snarkedLedgerHash":"jx7buQVWFLsXTtzRgSxbYcT8EYLS8KCZbLrfDcJxMtyy4thw2Ee",
"stagedLedgerHash":"jx7buQVWFLsXTtzRgSxbYcT8EYLS8KCZbLrfDcJxMtyy4thw2Ee",
"utcDate":"1615939200000"
},
"consensusState":{
"blockchainLength":1,
"epochCount":0,
"minWindowDensity":77,
"sub_window_densities":[
1,
7,
7,
7,
7,
7,
7,
7,
7,
7,
7
],
"lastVrfOutput":"NfThG1r1GxQuhaGLSJWGxcpv24SudtXG4etB0TnGqwg=",
"totalCurrency":805385692840039233,
"currGlobalSlot":0,
"slotSinceGenesis":0,
"stakingEpochData":{
"epochLength":1,
"ledger":{
"hash":"jx7buQVWFLsXTtzRgSxbYcT8EYLS8KCZbLrfDcJxMtyy4thw2Ee",
"totalCurrency":805385692840039300
},
"lockCheckpoint":"3NK2tkzqqK5spR2sZ7tujjqPksL45M3UUrcA4WhCkeiPtnugyE2x",
"seed":"2va9BGv9JrLTtrzZttiEMDYw1Zj6a6EHzXjmP9evHDTG3oEquURA",
"startCheckpoint":"3NK2tkzqqK5spR2sZ7tujjqPksL45M3UUrcA4WhCkeiPtnugyE2x"
},
"nextEpochData":{
"epochLength":2,
"ledger":{
"hash":"jx7buQVWFLsXTtzRgSxbYcT8EYLS8KCZbLrfDcJxMtyy4thw2Ee",
"totalCurrency":805385692840039300
},
"lockCheckpoint":"3NLoKn22eMnyQ7rxh5pxB6vBA3XhSAhhrf7akdqS6HbAKD14Dh1d",
"seed":"2vaRh7FQ5wSzmpFReF9gcRKjv48CcJvHs25aqb3SSZiPgHQBy5Dt",
"startCheckpoint":"3NK2tkzqqK5spR2sZ7tujjqPksL45M3UUrcA4WhCkeiPtnugyE2x"
},
"hasAncestorInSameCheckpointWindow":true,
"block_stake_winner":"B62qiy32p8kAKnny8ZFwoMhYpBppM1DWVCqAPBYNcXnsAHhnfAAuXgg",
"block_creator":"B62qiy32p8kAKnny8ZFwoMhYpBppM1DWVCqAPBYNcXnsAHhnfAAuXgg",
"coinbase_receiver":"B62qiy32p8kAKnny8ZFwoMhYpBppM1DWVCqAPBYNcXnsAHhnfAAuXgg",
"supercharge_coinbase":true,
"receivedTime":"2021-03-17T00:00:00Z",
"snarkFees":"0",
"stateHash":"3NKeMoncuHab5ScarV5ViyF16cJPT4taWNSaTLS64Dp67wuXigPZ",
"stateHashField":"9884505309989150310604636992054488263310056292998048242928359357807664465744",
"txFees":"0"
}
}
}
}
}
Archive节点定义的区块结构为:
module Block = struct
type t =
{ state_hash : State_hash.Stable.Latest.t
; parent_hash : State_hash.Stable.Latest.t
; creator : Public_key.Compressed.Stable.Latest.t
; block_winner : Public_key.Compressed.Stable.Latest.t
; snarked_ledger_hash : Frozen_ledger_hash.Stable.Latest.t
; staking_epoch_data : Mina_base.Epoch_data.Value.Stable.Latest.t
; next_epoch_data : Mina_base.Epoch_data.Value.Stable.Latest.t
; min_window_density : Mina_numbers.Length.Stable.Latest.t
; total_currency : Currency.Amount.Stable.Latest.t
; ledger_hash : Ledger_hash.Stable.Latest.t
; height : Unsigned_extended.UInt32.Stable.Latest.t
; global_slot_since_hard_fork : Mina_numbers.Global_slot.Stable.Latest.t
; global_slot_since_genesis : Mina_numbers.Global_slot.Stable.Latest.t
; timestamp : Block_time.Stable.Latest.t
; user_cmds : User_command.t list
; internal_cmds : Internal_command.t list
; chain_status : Chain_status.t
}
[@@deriving yojson, equal, bin_io_unversioned]
end
module User_command = struct
(* for `typ` and `status`, a string is enough
in any case, there aren't existing string conversions for the
original OCaml types
The versioned modules in Transaction_hash.Stable don't have yojson functions
it would be difficult to add them, so we just use the ones for the
top-level Transaction.t
*)
type t =
{ sequence_no : int
; typ : string
; fee_payer : Public_key.Compressed.Stable.Latest.t
; source : Public_key.Compressed.Stable.Latest.t
; receiver : Public_key.Compressed.Stable.Latest.t
; fee_token : Token_id.Stable.Latest.t
; token : Token_id.Stable.Latest.t
; nonce : Account.Nonce.Stable.Latest.t
; amount : Currency.Amount.Stable.Latest.t option
; fee : Currency.Fee.Stable.Latest.t
; valid_until : Mina_numbers.Global_slot.Stable.Latest.t option
; memo : Signed_command_memo.Stable.Latest.t
; hash : Transaction_hash.Stable.Latest.t
[@to_yojson Transaction_hash.to_yojson]
[@of_yojson Transaction_hash.of_yojson]
; status : string
; failure_reason : Transaction_status.Failure.Stable.Latest.t option
; source_balance : Currency.Balance.Stable.Latest.t option
; fee_payer_account_creation_fee_paid :
Currency.Amount.Stable.Latest.t option
; fee_payer_balance : Currency.Balance.Stable.Latest.t
; receiver_account_creation_fee_paid :
Currency.Amount.Stable.Latest.t option
; receiver_balance : Currency.Balance.Stable.Latest.t option
; created_token : Token_id.Stable.Latest.t option
}
[@@deriving yojson, equal, bin_io_unversioned]
end
module Internal_command = struct
(* for `typ`, a string is enough
no existing string conversion for the original OCaml type
*)
type t =
{ sequence_no : int
; secondary_sequence_no : int
; typ : string
; receiver : Public_key.Compressed.Stable.Latest.t
; receiver_account_creation_fee_paid :
Currency.Amount.Stable.Latest.t option
; receiver_balance : Currency.Balance.Stable.Latest.t
; fee : Currency.Fee.Stable.Latest.t
; token : Token_id.Stable.Latest.t
; hash : Transaction_hash.Stable.Latest.t
[@to_yojson Transaction_hash.to_yojson]
[@of_yojson Transaction_hash.of_yojson]
}
[@@deriving yojson, equal, bin_io_unversioned]
end
Protocol_state
:可将该结构看成是区块头,包含了区块中的最重要的信息。
This structure can be thought of like the block header. It contains the most essential information of a block.
Field | Type | Description |
---|---|---|
version |
u8 (= 0x01) |
Block structure version |
previous_state_hash |
State_hash.Stable.V1.t |
Commitment to previous block (hash of previous protocol state hash and body hash) |
body |
Protocol_state.Body.Value.Stable.V1 |
The body of the protocol state |
Field | Value | Description |
---|---|---|
delta |
0 |
Maximum permissable delay of packets (in slots after the current) |
k |
290 |
Depth of finality (number of confirmations) |
slots_per_epoch |
7140 |
Number of slots per epoch |
slots_duration |
180000 (= 3m) |
Slot duration in ms |
epoch_duration |
1285200000 (= 14d21h) |
Duration of an epoch in ms |
grace_period_end |
1440 |
Number of slots before minimum window density is used in chain selection |
genesis_state_timestamp |
1615939200000 (Mar 17, 2021 00:00:00 GMT+0000) |
Timestamp of genesis block in unixtime |
acceptable_network_delay |
180000 (= 3m) |
Acceptable network delay in ms |
slots_per_sub_window |
7 |
Slots per sub window (see Section 5.4) |
sub_windows_per_window |
11 |
Sub windows per window (see Section 5.4) |
slots_per_window |
slots_per_sub_window*sub_windows_per_window (= 77) |
Slots per window |
protocol_ state内相应的OCaml结构体定义为:
(* protocol_state结构体定义: *)
type ('state_hash, 'body) t =
{ previous_state_hash : 'state_hash; body : 'body }
(* protocol_state结构体中body结构体定义: *)
type t =
( 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
val create_value :
previous_state_hash:State_hash.t
-> genesis_state_hash:State_hash.t
-> blockchain_state:Blockchain_state.Value.t
-> consensus_state:Consensus.Data.Consensus_state.Value.t
-> constants:Protocol_constants_checked.Value.t
-> Value.t
(* state_hash定义为:*)
type t = Field.t
module Field = struct
include Tick0.Field
include Hashable.Make (Tick0.Field)
module Bits = Bits.Make_field (Tick0.Field) (Tick0.Bigint)
let size_in_triples = Int.((size_in_bits + 2) / 3)
end
module Make_field
(Field : Snarky_backendless.Field_intf.S)
(Bigint : Big_int_intf with type field := Field.t) :
Bits_intf.S with type t = Field.t =
Make_field0 (Field) (Bigint)
(struct
let bit_length = Field.size_in_bits
end)
(* blockchain_state结构体定义: *)
type ('staged_ledger_hash, 'snarked_ledger_hash, 'local_state, 'time) t =
{ staged_ledger_hash : 'staged_ledger_hash
; genesis_ledger_hash : 'snarked_ledger_hash
; registers :
('snarked_ledger_hash, unit, 'local_state) Registers.Stable.V1.t
; timestamp : 'time
}
val create_value :
staged_ledger_hash:Staged_ledger_hash.t
-> genesis_ledger_hash:Frozen_ledger_hash.t
-> registers:(Frozen_ledger_hash.t, unit, Local_state.t) Registers.Stable.V1.t
-> timestamp:Block_time.t
-> Value.t
(* staged_ledger_hash结构体定义为: *)
type ('non_snark, 'pending_coinbase_hash) t =
{ non_snark : 'non_snark
; pending_coinbase_hash : 'pending_coinbase_hash
}
val pending_coinbase_hash : t -> Pending_coinbase.Hash.t
(* Non_snark结构体定义为:*)
type t =
{ ledger_hash : Ledger_hash.Stable.V1.t
; aux_hash : Aux_hash.Stable.V1.t
; pending_coinbase_aux : Pending_coinbase_aux.Stable.V1.t
}
(* registers结构体定义为: *)
type ('ledger, 'pending_coinbase_stack, 'local_state) t =
{ ledger : 'ledger
; pending_coinbase_stack : 'pending_coinbase_stack
; local_state : 'local_state
}
(* Local_state结构体定义为 *)
type ( 'parties
, 'call_stack
, 'token_id
, 'excess
, 'ledger
, 'bool
, 'comm
, 'failure_status_tbl )
t =
{ parties : 'parties
; 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
}
(* Consensus_state结构体定义为: *)
(* We have a list of state hashes. When we extend the blockchain,
we see if the **previous** state should be saved as a checkpoint.
This is because we have convenient access to the entire previous
protocol state hash.
We divide the slots of an epoch into "checkpoint windows": chunks of
size [checkpoint_window_size]. The goal is to record the first block
in a given window as a check-point if there are any blocks in that
window, and zero checkpoints if the window was empty.
To that end, we store in each state a bit [checkpoint_window_filled] which
is true iff there has already been a state in the history of the given state
which is in the same checkpoint window as the given state.
*)
module Consensus_state = struct
module Poly = struct
[%%versioned
module Stable = struct
module V1 = struct
type ( 'length
, 'vrf_output
, 'amount
, 'global_slot
, 'global_slot_since_genesis
, 'staking_epoch_data
, 'next_epoch_data
, 'bool
, 'pk )
t =
{ blockchain_length : 'length
; epoch_count : 'length
; min_window_density : 'length
; sub_window_densities : 'length list
; last_vrf_output : 'vrf_output
; total_currency : 'amount
; curr_global_slot : 'global_slot
; global_slot_since_genesis : 'global_slot_since_genesis
; staking_epoch_data : 'staking_epoch_data
; next_epoch_data : 'next_epoch_data
; has_ancestor_in_same_checkpoint_window : 'bool
; block_stake_winner : 'pk
; block_creator : 'pk
; coinbase_receiver : 'pk
; supercharge_coinbase : 'bool
}
[@@deriving sexp, equal, compare, hash, yojson, fields, hlist]
end
end]
end
(* consensus constants结构体定义为:*)
type ('length, 'time, 'timespan) t =
{ k : 'length
; delta : 'length
; slots_per_sub_window : 'length
; slots_per_window : 'length
; sub_windows_per_window : 'length
; slots_per_epoch : 'length (* The first slot after the grace period. *)
; grace_period_end : 'length
; checkpoint_window_slots_per_year : 'length
; checkpoint_window_size_in_slots : 'length
; block_window_duration_ms : 'timespan
; slot_duration_ms : 'timespan
; epoch_duration : 'timespan
; delta_duration : 'timespan
; genesis_state_timestamp : 'time
}
protocol state中包含:
"staged_ledger_hash":{
"non_snark":{
"ledger_hash":"jww8oCgvdNPZujYVLh1oHyCzMupX5DeGBeavb7C8YEUbeZu7UUN",
"aux_hash":"VJDsgppyZcz9CK8cFT23QXTfQiujCesL2uUnfktubQzqWjr6PL",
"pending_coinbase_aux":"XH9htC21tQMDKM6hhATkQjecZPRUGpofWATXPkjB5QKxpTBv7H"
},
"pending_coinbase_hash":"2n2Dr16Ft9cgknFUfVFXpcq6gE3rWoW5jtgAW5SDduE2am98kRSE"
},
"registers":{
"ledger":"jxRZMzMSPVEMJ9wE4yqKEwQqVS3KZfDewHLYCC9aeqdig68Trco",
"pending_coinbase_stack":null,
"local_state":{
"parties":"0x0000000000000000000000000000000000000000000000000000000000000000",
"call_stack":"0x0000000000000000000000000000000000000000000000000000000000000000",
"transaction_commitment":"0x0000000000000000000000000000000000000000000000000000000000000000",
"full_transaction_commitment":"0x0000000000000000000000000000000000000000000000000000000000000000",
"token_id":"wSHV2S4qX9jFsLjQo8r1BsMLH2ZRKsZx6EJd1sbozGPieEC4Jf",
"excess":"0",
"ledger":"jw6bz2wud1N6itRUHZ5ypo3267stk4UgzkiuWtAMPRZo9g4Udyd",
"success":true,
"failure_status_tbl":[
]
}
},
"staking_epoch_data":{
"ledger":{
"hash":"jxRZMzMSPVEMJ9wE4yqKEwQqVS3KZfDewHLYCC9aeqdig68Trco",
"total_currency":"66000000000000"
},
"seed":"2va9BGv9JrLTtrzZttiEMDYw1Zj6a6EHzXjmP9evHDTG3oEquURA",
"start_checkpoint":"3NK2tkzqqK5spR2sZ7tujjqPksL45M3UUrcA4WhCkeiPtnugyE2x",
"lock_checkpoint":"3NK2tkzqqK5spR2sZ7tujjqPksL45M3UUrcA4WhCkeiPtnugyE2x",
"epoch_length":"1"
},
"next_epoch_data":{
"ledger":{
"hash":"jxRZMzMSPVEMJ9wE4yqKEwQqVS3KZfDewHLYCC9aeqdig68Trco",
"total_currency":"66000000000000"
},
"seed":"2vaHfBaUHKS7GYG6VpEp4Kn6Xjhc35wrDExNiZkwVj5aC95jvyk8",
"start_checkpoint":"3NK2tkzqqK5spR2sZ7tujjqPksL45M3UUrcA4WhCkeiPtnugyE2x",
"lock_checkpoint":"3NLqscU3JrErHUiBs4ipxqvn49uiwC2FdzfPCg61huBMXcDXNRvq",
"epoch_length":"3"
},
"constants":{
"k":"290",
"slots_per_epoch":"7140",
"slots_per_sub_window":"7",
"delta":"0",
"genesis_state_timestamp":"1600251300000"
}
protocol state proof为a blockchain proof,用于证明产块者新生成的protocol state是正确的。由于采用了recursive SNARKs,该protocol state proof证明了the entire history of the chain is valid。
"protocol_state_proof":"AgICAgEBAQEBAgEB_B-KzzaRoZB_AfziFjdF7mUfuwABAfyFDB6cUSv0kQH8bK7ooDD12xcAAQH8kABnVET_5A0B_ITVaxc-e-maAAIBAfzAvmsJpz8YJwH8DGKC8G-OV_0AAQCdCffOVUZW4gI_IpwEhZc-V2_3Eo1FkGiWw61W-xkgAQEArQvbebLxb00UJ-Da_nDAYxD6Rga5PrRCglOPg9oo8T8CAQH81fM6kgZ4sQEB_Ayp3waPKGt3AAEBAQIBAfy5KqdWtHBzrQH8_J7x1SP5TzYAAQIBAfwAfC-OYhyHWQH8h8wmonP2x5wAAQIBAfyv8raeHYJUIwH8fvV99tFrudUAAQIBAfz2hpCg0Pd7FAH8aCokQM5iXmIAAQIBAfwOrVYyYxvGrwH8--EfoRBygAkAAQIBAfyRQazKvh5Y-QH8psm3PpnVHlcAAQIBAfy9w2TNo1BOqgH8aMX-wQrnFNgAAQIBAfxt3l6C36wdsgH8pQfbxReiCP4AAQIBAfx_qubp1g9OggH8LH-5Tpg69vwAAQIBAfzKBBtxK4gxwwH8KSautsesOZEAAQIBAfzvUYH9R48P3AH8h5U7xEN6qQAAAQIBAfy_MobRHtg4YAH8qwWqonC8s_kAAQIBAfxaR6_l4NJ1lAH89tLDrgKny9EAAQIBAfwEfC359g94vgH8VOL7MpFYPeEAAQIBAfwTdTG4ErdwxgH8CD5ImjPMdRYAAQIBAfzRuMqxorDBSAH8zrFxwOMEZhsAAAEAAQEBAAEAAQABAAABYplUSRXwm-fBeRFELSVIQFO0WQXbn0FWMGH9fbwy0w-s11KF98GiT8ex5uJ8PBY6Vaax5zY5Ax0E66VeUAQFFgECAQEBAgEB_G-_5qzJs4IzAfxjGHb5WEOXeQABAgEB_JeHiOkGKzrdAfzHoUQpQOZ63QABAgEB_MufnPQw5ejGAfzdnKDNZbvdBwABAgEB_BMaaYeiWSxTAfx7b2UqsLwhqQABAgEB_IsHEI-xd5ziAfzuDGvfAF9c-AABAgEB_IecsActp70dAfygJl_p4pcbTQABAgEB_BFfgFZ8dHWcAfzo8c76aWP-oQABAgEB_E1g6dvfiitcAfyb9xDyjHGMWgABAgEB_Ehr4FFcs8AiAfztbalAc4uIpgABAgEB_G5kdl611weQAfwSjk7bOYvGwQABAgEB_MkrPzde40VEAfzlzYz8FcdAnQABAgEB_E6qvEuEgphCAfy8t6_Q1yeplwABAgEB_Hdu_f9bPcqZAfyUQlwVVWrm7wABAgEB_FSZlyFxsn1LAfxAyJNh4KIflQABAgEB_LNHB7K-zNEsAfwdAmTyPN7RWwAAAgEBAQIBAfxvv-asybOCMwH8Yxh2-VhDl3kAAQIBAfyXh4jpBis63QH8x6FEKUDmet0AAQIBAfzLn5z0MOXoxgH83ZygzWW73QcAAQIBAfwTGmmHolksUwH8e29lKrC8IakAAQIBAfyLBxCPsXec4gH87gxr3wBfXPgAAQIBAfyHnLAHLae9HQH8oCZf6eKXG00AAQIBAfwRX4BWfHR1nAH86PHO-mlj_qEAAQIBAfxNYOnb34orXAH8m_cQ8oxxjFoAAQIBAfxIa-BRXLPAIgH87W2pQHOLiKYAAQIBAfxuZHZetdcHkAH8Eo5O2zmLxsEAAQIBAfzJKz83XuNFRAH85c2M_BXHQJ0AAQIBAfxOqrxLhIKYQgH8vLev0NcnqZcAAQIBAfx3bv3_Wz3KmQH8lEJcFVVq5u8AAQIBAfxUmZchcbJ9SwH8QMiTYeCiH5UAAQIBAfyzRweyvszRLAH8HQJk8jze0VsAAAABAAECSLU26EZUpV9P_f_99ZG9nTyhcEvO8FylncJkSN7f0xFrGixE3SHHzVlV7xnD86u4Qg4beuUXFN7XioRNIgf1BUi1NuhGVKVfT_3__fWRvZ08oXBLzvBcpZ3CZEje39MRaxosRN0hx81ZVe8Zw_OruEIOG3rlFxTe14qETSIH9QUBAgEBAQIBAfy5KqdWtHBzrQH8_J7x1SP5TzYAAQIBAfwAfC-OYhyHWQH8h8wmonP2x5wAAQIBAfyv8raeHYJUIwH8fvV99tFrudUAAQIBAfz2hpCg0Pd7FAH8aCokQM5iXmIAAQIBAfwOrVYyYxvGrwH8--EfoRBygAkAAQIBAfyRQazKvh5Y-QH8psm3PpnVHlcAAQIBAfy9w2TNo1BOqgH8aMX-wQrnFNgAAQIBAfxt3l6C36wdsgH8pQfbxReiCP4AAQIBAfx_qubp1g9OggH8LH-5Tpg69vwAAQIBAfzKBBtxK4gxwwH8KSautsesOZEAAQIBAfzvUYH9R48P3AH8h5U7xEN6qQAAAQIBAfy_MobRHtg4YAH8qwWqonC8s_kAAQIBAfxaR6_l4NJ1lAH89tLDrgKny9EAAQIBAfwEfC359g94vgH8VOL7MpFYPeEAAQIBAfwTdTG4ErdwxgH8CD5ImjPMdRYAAQIBAfzRuMqxorDBSAH8zrFxwOMEZhsAAAEBAQIBAfy5KqdWtHBzrQH8_J7x1SP5TzYAAQIBAfwAfC-OYhyHWQH8h8wmonP2x5wAAQIBAfyv8raeHYJUIwH8fvV99tFrudUAAQIBAfz2hpCg0Pd7FAH8aCokQM5iXmIAAQIBAfwOrVYyYxvGrwH8--EfoRBygAkAAQIBAfyRQazKvh5Y-QH8psm3PpnVHlcAAQIBAfy9w2TNo1BOqgH8aMX-wQrnFNgAAQIBAfxt3l6C36wdsgH8pQfbxReiCP4AAQIBAfx_qubp1g9OggH8LH-5Tpg69vwAAQIBAfzKBBtxK4gxwwH8KSautsesOZEAAQIBAfzvUYH9R48P3AH8h5U7xEN6qQAAAQIBAfy_MobRHtg4YAH8qwWqonC8s_kAAQIBAfxaR6_l4NJ1lAH89tLDrgKny9EAAQIBAfwEfC359g94vgH8VOL7MpFYPeEAAQIBAfwTdTG4ErdwxgH8CD5ImjPMdRYAAQIBAfzRuMqxorDBSAH8zrFxwOMEZhsAAAEBldFiLMCn8tuKmdgVZTTVcgeq87vGpaahoxXNkkJogh8CAQFS0reBvhwwDB3LQCBfYCQHWpkLPtZAaF6khi9l6UbpGgE2iY4ANf6-Fu6V2JAx31oQ1WHZmK7QZi9deLsMF8vYDAFxI5ougXdG8pcPqt7xrkNRXIrf_CCxbxlGt8LnQLK-MgEhErp_10lnQVY7lIh4YSpf6hH-4X9Iu7ALrs9733jkIwHu3CQpAe6rrMu2XSVx_8Jo__W7ZvdUJaWnt1n_4rMoDwF7DTz4lANzls8z1DLGEf_TNvmGWkqP0h9NuNNHbmBoOwFdyzC-_PLz2ZYuTi5MogrWTHpyxzBwlHIaR1F3n8oiIwHEbrA7kGr-BD0iUMbnHPhQd3bBvCJGInmA_EJ3BP4qBQEKzCtv_aYC-uIHNevghsaQ__iLWwvw3e2xnwM6vm3wJgE3jMlSF-_fiEjkbNvvN-xMoO8jqbkknuJIHbkZU5CCCwHhXODBNtpjzl85oYYtmwUEuH7GswTgiAeZfYZLKuXnAwENViE30_FxaxBbMuOMCBvP-iB4vqKIjSdvNUlKRR2ZMAG7wdpIm816ZRuiURpesbuExUAOd4IrVVru3_BarFqZGAFXzb1Ke2lZRwF_8Qw00e8J5Amy1Wvmx1y8wnSsHygTCwHmfEbSm7zz9JhzAnA_Y4w2DABjmIxM_PL6LQTr-clhAgABNlHjmG9eJIVz0Ve5jYQc2V0JvszkBkoIUSv_aTiBXxEBAZEX0e1FG4nLu0N1MdJAwLVGatZRH80ZvgAavPRhtH4LAWzDZw_sx8tADUbsx48_IAegzqJeOsx2MGnefDFL978sAaVjyZXx_4_H6qAbE7LBbfTVNkKhm6hvB87h7e_7Mi0eAYufcqSsyzfhQRuUKlx5vve_FbZ0pLK6rqGtIzUneBUWAXk9UdPO_qT3Q8huliwKwxfrfgLBkggUaAmWfSgEkF47AfmmornJCka3Q5CjMhj1N81hV-5tGmy7m3lybjlyn7s5AAEADEZptNyvuzC6VEKWLA41KBizlxVqpZwAfh8q-Ym5OAFAX7cR6un8p4h12422YYnFbUJv6gaPKCb-XLCwr-BqDgEOUBnvWVt5b4cu2uh03z5r0elEJK7Xuk16xf5a4iUkFQIBAc7OkkrxKJsib7tsvvgJuUQiqdkfB4KtoNh-_IPQGbkbAUpO6djO835wTVeDbivULGlkZuJxl-Fm5aSsh69vF6kkAd5-V-0CNe0TFe58dlgv6F7xNBBXGnU3vNe9ORnyZuweAX6owPslflEY5UjZx9WfWFjKFTufeFBiMT0lDiTiAykUAZ1TyFvbyLn4lf088oVAmt4k0HfGsfuIS-jtA6YJIHoVAZmE3lrTCRxSP5DbZ5JSazaz0JNr2oqoqoIRJ0jhqvstAdI9RFVcVpMkBn2CgXYypLSL4xQmcQGgmHMZcnXQKE8FAY0e-OJKzzXmj0BEgDJDUukhZFvDVLBWROe9TrOoDp0TAa2xr8-v_nVpZWtU1c4598EaVZWPY_Qy77qaqWM04_ATAQ0Z7brLnPArv1wcEFPUIkeVJoVQOMBydyoKlw86VNUlAYmscFLDb1Com80GC6Z_qURt_rC22Ap072F91K9mzCA5AaxdEFXm3IXmls3i5M1Y5BF1VmIt5hbASzQn689OeSE5AaLgVMZbkUsuzKOpuqM1oNalAZz7sZzgc-rVLh8Plj8wAd5kv_MWM4OvImh3TSn5c4JlaSWjhG4I0bnb_YEHCVAIARp5ySBnrzqT4447erVR7TDLJZi-PVMa_LMWH_RkUnkMAAHDGB2H0KtKmc7IhbPU3lGwvKMrMG6-zo3KGocrwO_EHQEBKIjCcWS5CzQal6iCxUVPWGio1oeWs_GO9UKA7j-WKDoBz-b1_MdSOT3L_JQSVsK6hJnTIiiuGt0SDQ--zNk4kjMBF-b82gBjIdJvaOKWiwhIdjYH-DL5rbC6pxoVuS95iCUB_9tOkJ13KWV17xYttzFYFpOorhomKOnXsRT25kgyMAoBQBKK3DI87NJLX03v-DS-lgyQpcl9Fs5tEj7ejJWyvzwBkvX83AxM0_beQnlIsHgxLgs3RLZJMrVa9hQc6P5u2CwAAUyx4bzshD-rfjd4D0SIDVjr-jwotMDJE65BSVpbz1sZAcDITf6hUwa7licVuSHAEX_enz-d_6lzT8qXfK6GVJA3rWzyWf_q0Y06_TgvQQ53Gj1dDyYUVPpplpPYHEXMgDwCAgIBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwEHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuyrtyiN6zxlxRz0z1Ftlj1TueGPwqd9TfJMSCqO1dBsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuyrtyiN6zxlxRz0z1Ftlj1TueGPwqd9TfJMSCqO1dBsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwIBDwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuyrtyiN6zxlxRz0z1Ftlj1TueGPwqd9TfJMSCqO1dBsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuyrtyiN6zxlxRz0z1Ftlj1TueGPwqd9TfJMSCqO1dBsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuyrtyiN6zxlxRz0z1Ftlj1TueGPwqd9TfJMSCqO1dBsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuyrtyiN6zxlxRz0z1Ftlj1TueGPwqd9TfJMSCqO1dBsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuyrtyiN6zxlxRz0z1Ftlj1TueGPwqd9TfJMSCqO1dBsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuyrtyiN6zxlxRz0z1Ftlj1TueGPwqd9TfJMSCqO1dBsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuyrtyiN6zxlxRz0z1Ftlj1TueGPwqd9TfJMSCqO1dBsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuyrtyiN6zxlxRz0z1Ftlj1TueGPwqd9TfJMSCqO1dBsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuyrtyiN6zxlxRz0z1Ftlj1TueGPwqd9TfJMSCqO1dBsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuyrtyiN6zxlxRz0z1Ftlj1TueGPwqd9TfJMSCqO1dBsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GyVTlvxswhYpzvajjZyYblAxa7QuHyij4a-HH3Vp-ssNRs_rddU_qtvcYFVMmbzdaoUl8qb057CoI-1A3VD8DQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALsq7cojes8ZcUc9M9RbZY9U7nhj8KnfU3yTEgqjtXQbAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7Ku3KI3rPGXFHPTPUW2WPVO54Y_Cp31N8kxIKo7V0GwIBATvXd2YAh6jWpag_ZAAGvKfBNt_MNZMI68RE_gDmgmsYAXMXa7vEw1pAywL42XIYys2Y8mPdWLWuj8G4FfLJxd0pATxhquw6m2ESb7OBlZ-VdgeUrx1ipTlIIzC8SDu5aUwGAbWUMVDxqsXeU2I7i61f-mNljqu8Y456Yyex_6krMXoeAbJzsLxx_-vxxcTgFIpl6QZbJIiHu-iZYH0C8RcMe0YCAeVJuaNsucaBdRfn1m36cfu22AmU21N_m1GSfPMNcIQnAXUz3r-qPXovuFZ9Gb9iVhRsorwSG1I8--QnkuCzUyIsAVf6n7Zxvg2KMRUE8TEiEYahi-BEdxBzDEu6p0yjSN4yAfTR8Icwfpal3S1B_SIBfAnkkG9WJMmp5w6FFYMr1Ew1AQGF71eQABy-bk4IlED8UiScebtNMSCK98XYgQjcx4kWAdw-P8ei6BNwYFA1-WDLiFT7gzUZhsyIM_3fev86_LAVAVNJr1CR480YwJLtlXvjcdebyj4aM78Pg4isGJEllEEEAecivws4T8FIO6UNiUYE3FVG5DTEyrYAHMK8WfrHmFoqAXpKhKdWXxXytcpMDc3xn5mTcQm5ayHnpUHRQgEkFlE2AegJP1bEjlQA_tXCqGro2zOFY_Wn6jGmay0IM-K3OtYMAAGmYWM-1Jcew6UBONu2fH1IQr_-77ED5Y2TQBr3BPTMHQEB9oE-cfEh-6pmHcuAlF7xGD7DzxC3xjcYSlA7Gq6RCAsBUr6b8PC7EZGdUG3wO7if9rU6ktb4DwGWHcVAJVyYVCABfliyT9Ip77FuEgWmS1y7mGVmr4Qa7GpNjaVCAF05dhUBl5r4JgvM6SeV9BI4zzTXe0Ng4eQU0ceTfaxreedN5TkB83KNFoDhCWgbS2-AEf6mp1j46SfcLhbs88QZvm-VdhYBeGT_NZ1qIHtyPxh_d4YV0vBzKzevFpl3lM-DSWTYeTkAASemdT48FrmJIdU9GFQC6HTzGKgZ_fLzrGZnJiBFqoomAWZOfKb-k_FR8GlQi4Jq1dBscVSTGMvJEdprdNBu_igGAgEBt3qHiLB_fNHJxhYYdVzKPQ0wOnsJYSTODALcX0UaDwMBLh5ocx0AuEcgA4gjd37GUi2aHp42WSDD584GSt4MLh4B2W1i5UoKSdOkTJGetLCJMz1kojbtzaGSEnSsaQO62TcBzOOnjfokLYxT6JRnzJht_TMtuYfXbGbnc1pH7zTpDygBw31pLIRzqpoka7heXEMjzQxaaeS5zhrhYPlhRHwxri4B2C04cXhCveMXFX7fGGpbKlrCoDWgabGKG7eQ2KG2DiYBaZTicPKEpVfEGK_r-qyieUyK9qR2yxuUeMIF6KkBFw8BcXEV5ZcTyE-Iur4uwCklGAYNLMgrVOmpyaLSqHzpHhUBXdk8myw_zuMPo0lg8kcvzQTZ3oSG9jXJuW13b64xIh8BqE-UoNbWS-C5cEm5KuLFioy5Pnkhefq1f6MsRpWr5yQBLHxqpRI7QaqOrOhafu6467IiGck1O5J2cRGZqqgBghcBFuui69qf6sRC4p75KT9cRXaTPVMabjwHUY41IkEFXz0B3PWy4SRTuDacQg52raD7bG4XPyJxqhnsbbgBARJhFgUBNTYtmG8gxZjlPD3guPxBMASEJDFyr4k8yZyhmaoWFjwB8JUeajhftOqLXizw6J5UgHqZk4sKtpx38bmyEKBdFS4AATe--p2Axij7iz9_UxaRLBdUJqCtmoPbeAhH1jbxzKsJAQHgDTbMK2B2wjGEBGwKKgYghSFWRP4pVJpiUgJQVb37HAFr3yMOwHqRUxnGBq2TDEHdfwlyIq2id2pITnVf6y1JHAHugCvq9N2687aWmGidfna2cMqmXdvZIZcierDI37o2JAG1yY06iB6q1WANiZIN_4MCUHnSe9486t0UQlv8ikDTEAHARBYoASUZ12_vAQdDTcVrsXTn0WEM3i_IbWqnK3WtGgHNcciv4acZ8uXoP855QfuaMT4rkmJICvpoZ13Pq2SyCgAB5YAJPSQEBvZoSzE85AZpvVuhyN8-1TztL0c8A3rxmggBmsyU2cPnvd9moyPYK_VFGbuPL1vdSP7OtFqL3gqnoDmWoQZCEbUrw00mWHh1ByTo1VKunOj65UksfRSp5m51Fw=="
当产块者赢得了一个slot来产块时,他会从transaction pool中选择交易并从snark pool中选择任意snark work;他会创建the proposed next state of the blockchain,其中包括创建a diff of the staged ledger。a diff中包括:
可将staged ledger看成是a pending accounts database that has transactions(payments, coinbase, and proof fee payments) applied for which there are no SNARKs available yet。
staged ledger中包含了:
其中nonce值会逐笔交易递增。
"staged_ledger_diff":{
"diff": [
{
"completed_works":[
],
"commands":[
{
"data":[
"Signed_command",
{
"payload":{
"common":{
"fee":"0.1",
"fee_payer_pk":"B62qiy32p8kAKnny8ZFwoMhYpBppM1DWVCqAPBYNcXnsAHhnfAAuXgg",
"nonce":"0",
"valid_until":"4294967295",
"memo":"E4YM2vTHhWEg66xpj52JErHUBU4pZ1yageL4TVDDpTTSsv8mK6YaH"
},
"body":[
"Payment",
{
"source_pk":"B62qiy32p8kAKnny8ZFwoMhYpBppM1DWVCqAPBYNcXnsAHhnfAAuXgg",
"receiver_pk":"B62qiy32p8kAKnny8ZFwoMhYpBppM1DWVCqAPBYNcXnsAHhnfAAuXgg",
"amount":"0"
}
]
},
"signer":"B62qiy32p8kAKnny8ZFwoMhYpBppM1DWVCqAPBYNcXnsAHhnfAAuXgg",
"signature":"7mX9wRyDEq5SXYSWLCaCAVza4wQy2JBsZXL2SjQiG6mYbZmTj6rvTp77GDQadrHGYHDtaRTWSWLAQ8d7jKnPERAWQxVUg5AM"
}
],
"status":[
"Applied",
{
"fee_payer_account_creation_fee_paid":null,
"receiver_account_creation_fee_paid":null
},
{
"fee_payer_balance":"65999900000000",
"source_balance":"65999900000000",
"receiver_balance":"65999900000000"
}
]
},
............
]
},
null
]
}
在网络周围广播或gossip新生成的区块以应对不利的网络条件时,存在允许的网络延迟。delta transition chain proof 证明了该区块是在分配的 slot time 内生成的。
[1] Mina官网
[2] 【链向测评】Coda:看起来很美的轻量级公链
[3] Consensus on the Mina Blockchain
[4] Mina常问问题列表
[5] Mina Protocol Architecture
[6] Ouroboros Samasika Consensus
[7] Block structure
[8] What’s in a Block
[9] Mina rfc 0041-infra-testnet-persistence.md