您好,登錄后才能下訂單哦!
這篇文章主要介紹“Libra的Move交易腳本怎么編寫”,在日常操作中,相信很多人在Libra的Move交易腳本怎么編寫問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Libra的Move交易腳本怎么編寫”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
Move是一種新的編程語言,旨在為Libra區塊鏈提供安全且可編程的基礎。 Libra區塊鏈中的帳戶就是由任意數量的Move resources和Move modules組成的。 提交給Libra區塊鏈的每個交易都使用Move編寫的交易腳本來對其邏輯進行編碼。
交易腳本通過調用module聲明的procedures來更新區塊鏈的全局狀態。
每個Libra交易都包含一個Move交易腳本,該腳本對驗證程序代表客戶執行的邏輯進行編碼(例如,將Libra從A的帳戶轉移到B的帳戶)。
通過調用一個或多個Move模塊的procedures,事務腳本與發布在Libra區塊鏈的全局存儲中的Move resources進行交互。
事務腳本并不會在全局狀態中存儲,并且其他事務腳本也無法調用它。 它是一個一次性程序。
Move modules定義了用來更新Libra區塊鏈的全局狀態的規則。 modules相當于其他區塊鏈中的智能合約。 它聲明了可以在用戶帳戶下發布的resources類型。 Libra區塊鏈中的每個帳戶都是一個容器,用于容納任意數量的resources和modules。
module主要用來聲明結構類型(包括資源,這是一種特殊的結構)和procedures。
Move module的procedures定義了用于創建,訪問和銷毀其聲明的類型的規則。
modules是可重用的。 在一個module中聲明的結構類型可以使用在另一個module中聲明的結構類型,并且在一個module中聲明的可以procedure調用在另一個module中聲明的public procedures。 一個module可以調用在其他Move module中聲明的procedures。 事務腳本可以調用已發布module的任何public procedures。
最后,Libra用戶將能夠使用自己的帳戶發布modules。
Move的主要功能是能夠定義自定義資源類型。 資源類型主要對數字資產進行編碼。
資源在Libra中隨處可見。 它們可以存儲為數據結構,可以作為參數傳遞給過程,可以從過程中返回,等等。
Move type system為資源提供了特殊的安全保證。 Move resources永遠不能被復制,重用或丟棄。 資源類型只能由定義該類型的模塊創建或銷毀。這是由Move虛擬機通過字節碼驗證來強制進行保證的。 Move虛擬機將拒絕運行尚未通過字節碼驗證程序的代碼。
Libra貨幣是通過LibraCoin.T的資源類型來實現的。 和其他的資源一樣,LibraCoin.T也是一種資源。
本節我會介紹怎么使用Move IR來編寫事務腳本和模塊。IR是即將推出的Move源語言的預覽版本(不穩定)。 Move IR是Move字節碼上的一個薄語法層,用于測試字節碼驗證程序和虛擬機,它對開發人員并不特別友好。 它足夠高,可以編寫人類可讀的代碼,但是也足夠低,可以直接編譯為Move字節碼。
用戶通過交易腳本來請求對Libra區塊鏈的全局存儲進行更新。幾乎所有事務腳本中都會出現兩個重要資源:LibraAccount.T和LibraCoin.T資源類型。 LibraAccount是module的名稱,而T是該module聲明的資源的名稱。這是Move中的通用命名約定。module聲明的“主要”類型通常稱為T。
當我們說用戶“在Libra區塊鏈上的地址0xff擁有一個帳戶”時,我們的意思是地址0xff擁有LibraAccount.T資源的實例。每個非空地址都有一個LibraAccount.T資源。此資源存儲帳戶數據,例如序列號,身份驗證密鑰和余額。要與帳戶進行交互的Libra系統的任何部分都必須通過從LibraAccount.T資源中讀取數據或調用LibraAccount module的procedures來進行此操作。
帳戶余額是LibraCoin.T類型的資源。這是Libra貨幣的類型。與任何其他Move資源一樣,此類型在語言上是一等公民。
LibraCoin.T類型的資源可以存儲在程序變量中,在過程之間傳遞,等等。
現在讓我們看看程序員如何在事務腳本中與這些模塊和資源進行交互。
// Simple peer-peer payment example.// Use LibraAccount module published on the blockchain at account address// 0x0...0 (with 64 zeroes). 0x0 is shorthand that the IR pads out to// 256 bits (64 digits) by adding leading zeroes.import 0x0.LibraAccount;import 0x0.LibraCoin;main(payee: address, amount: u64) { // The bytecode (and consequently, the IR) has typed locals. The scope of // each local is the entire procedure. All local variable declarations must // be at the beginning of the procedure. Declaration and initialization of // variables are separate operations, but the bytecode verifier will prevent // any attempt to use an uninitialized variable. let coin: LibraCoin.T; // Acquire a LibraCoin.T resource with value `amount` from the sender's // account. This will fail if the sender's balance is less than `amount`. coin = LibraAccount.withdraw_from_sender(move(amount)); // Move the LibraCoin.T resource into the account of `payee`. If there is no // account at the address `payee`, this step will fail LibraAccount.deposit(move(payee), move(coin)); // Every procedure must end in a `return`. The IR compiler is very literal: // it directly translates the source it is given. It will not do fancy // things like inserting missing `return`s. return;}
此交易腳本有一個不幸的問題-如果收款人下沒有帳戶,它將失敗。 我們將通過修改腳本為收款人創建帳戶(如果尚不存在)來解決此問題。
// A small variant of the peer-peer payment example that creates a fresh// account if one does not already exist.import 0x0.LibraAccount;import 0x0.LibraCoin;main(payee: address, amount: u64) { let coin: LibraCoin.T; let account_exists: bool; // Acquire a LibraCoin.T resource with value `amount` from the sender's // account. This will fail if the sender's balance is less than `amount`. coin = LibraAccount.withdraw_from_sender(move(amount)); account_exists = LibraAccount.exists(copy(payee)); if (!move(account_exists)) {// Creates a fresh account at the address `payee` by publishing a// LibraAccount.T resource under this address. If theres is already a// LibraAccount.T resource under the address, this will fail.create_account(copy(payee)); } LibraAccount.deposit(move(payee), move(coin)); return;}
讓我們看一個更復雜的例子。 在此示例中,我們將使用交易腳本向多個收件人付款,而不僅僅是一個。
// Multiple payee example. This is written in a slightly verbose way to// emphasize the ability to split a `LibraCoin.T` resource. The more concise// way would be to use multiple calls to `LibraAccount.withdraw_from_sender`.import 0x0.LibraAccount;import 0x0.LibraCoin;main(payee1: address, amount1: u64, payee2: address, amount2: u64) { let coin1: LibraCoin.T; let coin2: LibraCoin.T; let total: u64; total = move(amount1) + copy(amount2); coin1 = LibraAccount.withdraw_from_sender(move(total)); // This mutates `coin1`, which now has value `amount1`. // `coin2` has value `amount2`. coin2 = LibraCoin.withdraw(&mut coin1, move(amount2)); // Perform the payments LibraAccount.deposit(move(payee1), move(coin1)); LibraAccount.deposit(move(payee2), move(coin2)); return;}
好了,這就是簡單的交易腳本,雖然我們不了解Move IR的語法,但是直接看內容應該就很容易明白這個腳本到底在做什么了。
上面的交易腳本使用了現有的LibraAccount和LibraCoin modules,那么我們怎么編寫自己的Move modules呢?
考慮這種情況:B將來會在地址a創建一個帳戶。 A想為B“專款”一些資金,以便他一旦創建就可以將其存入他的帳戶。 但是,如果B從未創建該帳戶,她還希望能夠自己收回資金。
為了解決A的這個問題,我們將編寫一個模塊EarmarkedLibraCoin:
聲明一個新的資源類型EarmarkedLibraCoin.T,該資源類型包裝了Libra coin和收件人地址。
允許A創建此類類型并將其發布到她的帳戶下(創建過程)。
允許B聲明資源(claim_for_recipient過程)。
允許擁有EarmarkedLibraCoin.T的任何人銷毀它并獲得相應的coin(拆包程序)。
// A module for earmarking a coin for a specific recipientmodule EarmarkedLibraCoin { import 0x0.LibraCoin; // A wrapper containing a Libra coin and the address of the recipient the // coin is earmarked for. resource T {coin: LibraCoin.T,recipient: address } // Create a new earmarked coin with the given `recipient`. // Publish the coin under the transaction sender's account address. public create(coin: LibraCoin.T, recipient: address) {let t: Self.T;// Construct or "pack" a new resource of type T. Only procedures of the// `EarmarkedLibraCoin` module can create an `EarmarkedLibraCoin.T`.t = T { coin: move(coin), recipient: move(recipient),};// Publish the earmarked coin under the transaction sender's account// address. Each account can contain at most one resource of a given type;// this call will fail if the sender already has a resource of this type.move_to_sender<T>(move(t));return; } // Allow the transaction sender to claim a coin that was earmarked for her. public claim_for_recipient(earmarked_coin_address: address): Self.T acquires T {let t: Self.T;let t_ref: &Self.T;let sender: address;// Remove the earmarked coin resource published under `earmarked_coin_address`.// If there is no resource of type T published under the address, this will fail.t = move_from<T>(move(earmarked_coin_address));t_ref = &t;// This is a builtin that returns the address of the transaction sender.sender = get_txn_sender();// Ensure that the transaction sender is the recipient. If this assertion// fails, the transaction will fail and none of its effects (e.g.,// removing the earmarked coin) will be committed. 99 is an error code// that will be emitted in the transaction output if the assertion fails.assert(*(&move(t_ref).recipient) == move(sender), 99);return move(t); } // Allow the creator of the earmarked coin to reclaim it. public claim_for_creator(): Self.T acquires T {let t: Self.T;let sender: address;sender = get_txn_sender();// This will fail if no resource of type T under the sender's address.t = move_from<T>(move(sender));return move(t); } // Extract the Libra coin from its wrapper and return it to the caller. public unwrap(t: Self.T): LibraCoin.T {let coin: LibraCoin.T;let recipient: address;// This "unpacks" a resource type by destroying the outer resource, but// returning its contents. Only the module that declares a resource type// can unpack it.T { coin, recipient } = move(t);return move(coin); }}
A可以通過創建交易腳本來為B創建專用coin,該交易腳本調用B地址a上的create和她擁有的LibraCoin.T。 創建a之后,B可以通過發送來自a的交易來claim coin。 這將調用claim_for_recipient,將結果傳遞給unwrap,并在他希望的任何地方存儲返回的LibraCoin。
如果B花費太長時間在a帳戶下創建帳戶,而A想要收回其資金,則可以通過使用Claim_for_creator然后取消unwrap來做到這一點。
到此,關于“Libra的Move交易腳本怎么編寫”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。