LibraAccount模块分析
//这个模块主要是很对账户资源的,用于管理每个Libra账户 //可以看到他引用了 module LibraAccount { import 0x0.LibraCoin; import 0x00.Hash; //每个Libra账户都有一个LibraAccount.T资源 // Every Libra account has a LibraLibraAccount.T resource resource T { // The coins stored in this account balance: R#LibraCoin.T, //当前的身份认证key //这个key可以与创建账户的key不同 authentication_key: bytearray, //账户nonce sequence_number: u64, //临时的发送交易事件计数器,等到后面事件系统被完善后,这个值应该会被代替 sent_events_count: u64, //临时的交易接收事件计数器,等到后面事件系统被完善后,这个值应该会被代替 received_events_count: u64 } // Message for sent events struct SentPaymentEvent { // The address that was paid payee: address, // The amount of LibraCoin.T sent amount: u64, } // Message for received events struct ReceivedPaymentEvent { // The address that sent the coin payer: address, // The amount of LibraCoin.T received amount: u64, } //创建一个新的LibraAccount.T类型的资源 //这个过程被内置模块create_account调用 make(auth_key: bytearray): R#Self.T { let zero_balance: R#LibraCoin.T; zero_balance = LibraCoin.zero(); return T { balance: move(zero_balance), authentication_key: move(auth_key), sequence_number: 0, sent_events_count: 0, received_events_count: 0, }; } // 向payee账户存入to_deposit资源 public deposit(payee: address, to_deposit: R#LibraCoin.T) { let deposit_value: u64; let payee_account_ref: &mut R#Self.T; let sender: address; let sender_account_ref: &mut R#Self.T; let sent_event: V#Self.SentPaymentEvent; let received_event: V#Self.ReceivedPaymentEvent; // Check that the `to_deposit` coin is non-zero deposit_value = LibraCoin.value(&to_deposit); assert(copy(deposit_value) > 0, 7); // Load the sender's account sender = get_txn_sender(); sender_account_ref = borrow_global<T>(copy(sender)); // Log a send event sent_event = SentPaymentEvent { payee: copy(payee), amount: copy(deposit_value) }; // 目前的打印事件只是临时之举,未来应该会变得更加有条理 emit_event(&mut move(sender_account_ref).sent_events_count, b"73656E745F6576656E74735F636F756E74", move(sent_event)); // Load the payee's account payee_account_ref = borrow_global<T>(move(payee)); // Deposit the `to_deposit` coin LibraCoin.deposit(&mut copy(payee_account_ref).balance, move(to_deposit)); // Log a received event received_event = ReceivedPaymentEvent { payer: move(sender), amount: move(deposit_value) }; // TEMPORARY The events system is being overhauled and this will be replaced by something // more principled in the future emit_event(&mut move(payee_account_ref).received_events_count, b"72656365697665645F6576656E74735F636F756E74", move(received_event)); return; } //mint_to-address 只能被又有mint能力的的账户使用(参照LibraCoin模块) //这些帐户将被收取gas费用。如果这些帐户没有足够的gas支付,则mint失败 // 那些账户也可以mint给自己coin public mint_to_address(payee: address, amount: u64) { let mint_capability_ref: &R#LibraCoin.MintCapability; let coin: R#LibraCoin.T; let payee_account_ref: &mut R#Self.T; let payee_exists: bool; let sender: address; // Mint the coin mint_capability_ref = LibraCoin.borrow_sender_mint_capability(); coin = LibraCoin.mint(copy(amount), move(mint_capability_ref)); // Create an account if it does not exist payee_exists = exists<T>(copy(payee)); if (!move(payee_exists)) { //这一行感觉没必要 sender = get_txn_sender(); Self.create_new_account(copy(payee), 0); } // Deposit the minted `coin` Self.deposit(move(payee), move(coin)); return; } // Helper to withdraw `amount` from the given `account` and return the resulting LibraCoin.T withdraw_from_account(account: &mut R#Self.T, amount: u64): R#LibraCoin.T { let to_withdraw: R#LibraCoin.T; to_withdraw = LibraCoin.withdraw(&mut move(account).balance, copy(amount)); return move(to_withdraw); } // Withdraw `amount` LibraCoin.T from the transaction sender's account public withdraw_from_sender(amount: u64): R#LibraCoin.T { let sender: address; let sender_account: &mut R#Self.T; let to_withdraw: R#LibraCoin.T; // Load the sender sender = get_txn_sender(); sender_account = borrow_global<T>(move(sender)); // Withdraw the coin to_withdraw = Self.withdraw_from_account(move(sender_account), move(amount)); return move(to_withdraw); } //从发送者账户转移资金到接受者,如果发送者账户不存在,先创建账户,然后再调用此过程 public pay_from_sender(payee: address, amount: u64) { let to_pay: R#LibraCoin.T; let payee_exists: bool; payee_exists = exists<T>(copy(payee)); if (move(payee_exists)) { to_pay = Self.withdraw_from_sender(move(amount)); Self.deposit(move(payee), move(to_pay)); } else { Self.create_new_account(move(payee), move(amount)); } return; } //更新交易发送者身份认证key //新的key将会被用于交易签名 public rotate_authentication_key(new_authentication_key: bytearray) { let sender: address; let sender_account: &mut R#Self.T; sender = get_txn_sender(); sender_account = borrow_global<T>(move(sender)); *(&mut move(sender_account).authentication_key) = move(new_authentication_key); return; } //创建一个新的账户,如果初始资金>0,则从交易发送者账户转移资金到新账户 public create_new_account(fresh_address: address, initial_balance: u64) { create_account(copy(fresh_address)); if (copy(initial_balance) > 0) { Self.pay_from_sender(move(fresh_address), move(initial_balance)); } return; } // Helper to return u64 value of the `balance` field for given `account` balance_for_account(account: &R#Self.T): u64 { let balance_value: u64; balance_value = LibraCoin.value(&move(account).balance); return move(balance_value); } // Return the current balance of the LibraCoin.T in LibraLibraAccount.T at `addr` public balance(addr: address): u64 { let payee_account: &mut R#Self.T; let imm_payee_account: &R#Self.T; let balance_amount: u64; //从账户地址,拿到LibraAccount类型的资源,此时拿到的资源是可变的 payee_account = borrow_global<T>(move(addr)); //将资源转为不可变资源,防止误操作 imm_payee_account = freeze(move(payee_account)); balance_amount = Self.balance_for_account(move(imm_payee_account)); return move(balance_amount); } // Helper to return the sequence number field for given `account` sequence_number_for_account(account: &R#Self.T): u64 { return *(&move(account).sequence_number); } // Return the current sequence number at `addr` public sequence_number(addr: address): u64 { let account_ref: &mut R#Self.T; let imm_ref: &R#Self.T; let sequence_number_value: u64; account_ref = borrow_global<T>(move(addr)); imm_ref = freeze(move(account_ref)); sequence_number_value = Self.sequence_number_for_account(move(imm_ref)); return move(sequence_number_value); } // Checks if an account exists at `check_addr` public exists(check_addr: address): bool { let is_present: bool; is_present = exists<T>(move(check_addr)); return move(is_present); } // 序言过程在每笔交易开始的时候被调用,它要做以下验证: //账户的身份key是否匹配交易的公钥 //账户是否有足够的金额支付所有的gas //sequence number是否匹配当前账户sequence key prologue() { let transaction_sender: address; let transaction_sender_exists: bool; let sender_account: &mut R#Self.T; let imm_sender_account: &R#Self.T; let sender_public_key: bytearray; let public_key_hash: bytearray; let gas_price: u64; let gas_units: u64; let gas_fee: u64; let balance_amount: u64; let sequence_number_value: u64; let transaction_sequence_number_value: u64; transaction_sender = get_txn_sender(); // 现在这些error code还是很不友好的,后续应该会变得更好 transaction_sender_exists = exists<T>(copy(transaction_sender)); assert(move(transaction_sender_exists), 5); // Load the transaction sender's account sender_account = borrow_global<T>(copy(transaction_sender)); //检查交易的公钥是否与当前账户的身份key相匹配 sender_public_key = get_txn_public_key(); public_key_hash = Hash.sha3_256(move(sender_public_key)); assert(move(public_key_hash) == *(©(sender_account).authentication_key), 2); // 检查是否有足够的余额支付交易手续费 gas_price = get_txn_gas_unit_price(); gas_units = get_txn_max_gas_units(); //先计算最大所需的手续费,在交易结束后进行扣除真实消耗的gas手续费 gas_fee = move(gas_price) * move(gas_units); imm_sender_account = freeze(copy(sender_account)); balance_amount = Self.balance_for_account(move(imm_sender_account)); assert(move(balance_amount) >= move(gas_fee), 6); // 检查交易的sequence number是否与账户保存的sequence number匹配 sequence_number_value = *(&mut move(sender_account).sequence_number); transaction_sequence_number_value = get_txn_sequence_number(); //这里多判断一次可能是未来防止并行交易的时候较大sequence number可以被接受 assert(copy(transaction_sequence_number_value) >= copy(sequence_number_value), 3); assert(move(transaction_sequence_number_value) == move(sequence_number_value), 4); return; } // 收尾主要是被用于在交易结束后进行一些处理 //主要是计算交易真实消耗gas的手续费和调整账户sequence number // The epilogue is invoked at the end of transactions. // It collects gas and bumps the sequence number epilogue() { let transaction_sender: address; let sender_account: &mut R#Self.T; let imm_sender_account: &R#Self.T; let gas_price: u64; let gas_units_remaining: u64; let starting_gas_units: u64; let gas_fee_amount: u64; let balance_amount: u64; let gas_fee: R#LibraCoin.T; let transaction_sequence_number_value: u64; transaction_sender = get_txn_sender(); // Load the transaction sender's account sender_account = borrow_global<T>(copy(transaction_sender)); //收取真实消耗的gas的手续费 gas_price = get_txn_gas_unit_price(); starting_gas_units = get_txn_max_gas_units(); gas_units_remaining = get_gas_remaining(); gas_fee_amount = move(gas_price) * (move(starting_gas_units) - move(gas_units_remaining)); imm_sender_account = freeze(copy(sender_account)); balance_amount = Self.balance_for_account(move(imm_sender_account)); assert(move(balance_amount) >= copy(gas_fee_amount), 6); gas_fee = Self.withdraw_from_account(copy(sender_account), move(gas_fee_amount)); //销毁掉相应的手续费资源 LibraCoin.TODO_REMOVE_burn_gas_fee(move(gas_fee)); // 账户sequence number + 1 transaction_sequence_number_value = get_txn_sequence_number(); *(&mut move(sender_account).sequence_number) = move(transaction_sequence_number_value) + 1; return; } }
到这里整个move语言官方给出的实例代码就解读完毕了,读者也可以查看libra仓库看看最新更新的代码