国产麻豆精品福利在线观看,亚洲人亚洲精品成人网站,亚洲熟妇无码AV另类VR影视,欧美A级毛欧美1级A大片免费播放

您的位置:首頁 > 互聯(lián)網(wǎng) >

UTXO可被用來竊取金錢 execute函數(shù)是UTXO邏輯的關(guān)鍵

2019-11-12 17:52:19 來源: 區(qū)塊網(wǎng)

前段時間,Gavin Wood要求我研究基于Substrate實施UTXO鏈的可能性,Substrate是目前最有前景的區(qū)塊鏈技術(shù)底層架構(gòu),而且目前Polkadot是基于

前段時間,Gavin Wood要求我研究基于Substrate實施UTXO鏈的可能性,Substrate是目前最有前景的區(qū)塊鏈技術(shù)底層架構(gòu),而且目前Polkadot是基于substrate進行開發(fā)的。

我們想知道Substrate的靈活性,而UTXO鏈似乎是進行測試的一個不錯的選擇,因為它與我們過去在實施Substrate時所考慮的完全不同。如果可行,則表明Substrate確實非常靈活且通用。我們可以更有信心,把Substrate應(yīng)該到不同領(lǐng)域的區(qū)塊鏈項目中。

與以太坊類似,Substrate保留一定數(shù)量的可用資金。從某種意義上講,它類似于普通的銀行系統(tǒng),其中帳戶余額用數(shù)字表示,并存儲在數(shù)據(jù)庫或計算機內(nèi)存中的某個位置。

從歷史上看,第一個成功的加密貨幣是比特幣,它使用完全不同的方法。在比特幣中,本身沒有賬戶,余額也不是作為一個數(shù)字存儲的。取而代之的是,可用資金是根據(jù)一組所謂的未用交易輸出來定義的,簡稱為UTXO,這是一個非常簡單的主意。

簡而言之是UTXO

簡而言之,UTXO非常類似于現(xiàn)金,或者更確切地說,是旅行支票。

當你用現(xiàn)金支付某人時,你通常會想到要支付的總價值,但是你用一組獨特的、不可分割的單位(代幣或鈔票)來表示這個價值。例如如果Alice希望付給Bob$250美元,她可以給Bob2張價值$100美元的鈔票和1張價值50美元的鈔票,或五張面值$50的鈔票,或總計為所需值的任何其他組合。

每一張鈔票都是獨一無二的。盡管有數(shù)百萬張鈔票具有相同的價值,但是每張鈔票在物理上都是唯一的,并在其表面印有序列號。通常情況下,我們不太注意它,只是在支付東西的時候,把兩張100美元的鈔票視為相等,但這個數(shù)字對于銀行控制資金流動和真?zhèn)螜z查是必不可少的。

因此每張鈔票代表著具有預定和固定價值的獨特且不可分割的資產(chǎn),這些資產(chǎn)只能整體使用,即您不能將100美元的鈔票撕成兩張50美元的鈔票。當然你可以要求某人找零,將價值分成較小的單位,但是您仍然需要花100美元的原始鈔票。同樣,購買咖啡時,您會花掉10美元的鈔票,作為回報,您會得到咖啡和一些零錢。

UTXO的工作方式與此類似。要使用比特幣付款,您的錢包中應(yīng)該已經(jīng)有一些未使用的資產(chǎn)。與法定貨幣一樣,您可以結(jié)合使用多個UTXO以獲得更大的價值。

與現(xiàn)金不同,每個UTXO都有自己的所有者。從這個意義上說,它類似于旅行支票,因為只有支票所有人才可以使用它。這是通過所有者簽名增加單位來完成的。不同之處在于,旅行支票由所有者的手簽名,而UTXO使用非對稱加密,并且包含收件人而非發(fā)件人的公鑰。而是鈔票由政府印刷,UTXO由發(fā)起人創(chuàng)建。

目標

在我們的研究中,我們將嘗試建立一個區(qū)塊鏈模型,使用與比特幣相同的原理將資金從一個所有者轉(zhuǎn)移到另一個所有者。

當閱讀文章時,請記住我們的主要目標是評估Substrate的靈活性,而不是比特幣移植時使用端口的詳細解釋。在某些情況下,其實現(xiàn)幾乎與Parity比特幣的實現(xiàn)相同,而在其他情況下則不是。例如當前的實現(xiàn)不支持挖掘和coinbase事務(wù);它只是重新分配在genesis塊中初始化的“預先定義”UTXO集的值。

另外,請注意,所提供的實現(xiàn)還不能完全投入生產(chǎn)。它尚未經(jīng)過正式驗證,并且可能存在一些安全性或穩(wěn)定性問題,因此,我不建議您在沒有適當研究的情況下,將其用于任何關(guān)鍵基礎(chǔ)架構(gòu)。但是如果有人將這個原型制作成可行的解決方案,我會非常高興。

話雖如此,讓我們繼續(xù)進行代碼。

首先讓我們談?wù)凷ubstrate如何允許您對其進行自定義。作為應(yīng)用程序員,您應(yīng)該提供一個runtime的運行邏輯,這些邏輯告訴Substrate如何處理鏈以及應(yīng)采用的業(yè)務(wù)邏輯。所有這些都圍繞著狀態(tài)轉(zhuǎn)換函數(shù)(簡稱STF)的概念。但現(xiàn)在我們只需說,每個區(qū)塊鏈都可以表示為一個函數(shù),接受當前狀態(tài)和一個掛起的事務(wù),然后生成另一個狀態(tài),反映在應(yīng)用事務(wù)后所做的更改。

假設(shè)Alice和Bob都有10個代幣,然后Alice向Bob發(fā)送了5個代幣。應(yīng)用此交易后,我們預計Alice現(xiàn)在將有5個代幣,而Bob將有15個代幣。如果Bob隨后嘗試向Claire支付20個代幣,則該交易必須視為無效,因為根據(jù)最新的鏈條狀態(tài),Bob只有15個代幣。

這正是runtime的意圖-它定義了所有實體及其關(guān)系,驗證了傳入的事務(wù)并相應(yīng)地更改了狀態(tài)。

讓我們從指定將用于定義UTXO鏈的業(yè)務(wù)邏輯的數(shù)據(jù)類型開始。首先是Transaction 類型。它表示要調(diào)度的單個UTXO事務(wù):

/// Single transaction to be dispatched

#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]

#[derive(PartialEq, Eq, PartialOrd, Ord, Default, Clone, Encode, Decode, Hash)]

pub struct Transaction {

/// UTXOs to be used as inputs for current transaction

pub inputs: Vec,

/// UTXOs to be created as a result of current transaction dispatch

pub outputs: Vec,

}

這里沒有什么特別的,只是一個簡單的定義,即Transaction只是一堆輸入和輸出。如果您好奇,可以將其與Parity Bitcoin的版本進行比較,以了解相似之處。上面所有#[...]怪異都稱為屬性,它告訴Rust編譯器為我們實現(xiàn)各種操作,例如比較運算符,哈希函數(shù)和序列化例程。您現(xiàn)在可以放心地忽略它們。

我留下了所有注釋和屬性,以表明即使將它們包括在內(nèi),代碼仍會保持緊湊。我認為,即使與在成千上萬行中做“同一件事”的Parity Bitcoin相比,這也是Substrate的可觀成就。就像在用JavaScript為網(wǎng)絡(luò)編寫代碼時一樣,您并沒有考慮過瀏覽器引擎或任何底層操作系統(tǒng)(包括操作系統(tǒng))的復雜性。相反,您只是以高級形式制定業(yè)務(wù)邏輯,然后讓系統(tǒng)完成其余工作。

好的,但是TransactionInput呢?

/// Single transaction input that refers to one UTXO

#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]

#[derive(PartialEq, Eq, PartialOrd, Ord, Default, Clone, Encode, Decode, Hash)]

pub struct TransactionInput {

/// Reference to an UTXO to be spent

pub parent_output: H256,

/// Proof that transaction owner is authorized to spend referred UTXO

pub signature: Signature,

}

TransactionInput匯總花費一個UTXO所需的所有數(shù)據(jù)。首先我們需要一種方法來引用一些現(xiàn)有的UTXO。最簡單的方法是使用其哈希作為標識符。這是分布式系統(tǒng)世界中的一種普遍做法,并且只要哈希沖突的可能性可以忽略不計,它就可以很好地工作。為此我們使用256位Blake2。parent_output字段包含此類哈希。

如前所述,要使用UTXO,所有者必須使用與存儲在該特定UTXO中的公鑰匹配的秘密密鑰對其進行簽名。只要知道密鑰的唯一人是所有者,這就是安全的。這種證明存儲在簽名字段中。

我們的實現(xiàn)與比特幣之間的區(qū)別在于,我們直接通過其哈希值引用parent_output,而比特幣則使用產(chǎn)生了UTXO的交易的哈希值以及一個索引來從交易輸出列表中選擇特定條目。原因是比特幣是根據(jù)交易和區(qū)塊定義的,而我們是根據(jù)業(yè)務(wù)邏輯和狀態(tài)轉(zhuǎn)換來定義的。在我們的例子中,Substrate事務(wù)只是輔助實體,它們促進了流程,并且大部分都超出了業(yè)務(wù)邏輯的范圍。稍后再談。

接下來是定義UTXO的TransactionOutput結(jié)構(gòu):

/// Single transaction output to create upon transaction dispatch

#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]

#[derive(Default, PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Hash)]

pub struct TransactionOutput {

/// Value associated with this output

pub value: Value,

/// Public key associated with this output. In order to spend this output

/// owner must provide a proof by hashing whole `TransactionOutput` and

/// signing it with a corresponding private key.

pub pubkey: H256,

/// Unique (potentially random) value used to distinguish this

/// particular output from others addressed to the same public

/// key with the same value. Prevents potential replay attacks.

pub salt: u32,

}

value和pubkey字段的用途應(yīng)該已經(jīng)清楚。唯一值得解釋的是salt。此字段提供了額外的熵,以使每個UTXO及其哈希真正唯一。想象一下這樣的情況,我們有一個機器人每天向同一個收件人發(fā)送10個代幣。為了簡單起見,它可以使用相同的目的地地址,即接收者的公鑰。因為value和pubkey字段都包含相同的數(shù)據(jù),所以bot創(chuàng)建的所有UTXO看起來都完全相同,因此具有相同的散列。

沒有salt,攻擊者將能夠記住所有者所用的第一個UTXO的簽名,然后在所有者甚至沒有注意到之前就花費所有后續(xù)的UTXO來竊取金錢,這稱為重放攻擊。同樣還有另一種在源代碼中尚未解決的重放攻擊的可能性。

請注意,由于比特幣實現(xiàn)依賴于交易哈希來精確定位UTXO,因此它不會遭受此問題的困擾,因此不需要salt。然而,這并不意味著比特幣不可能進行重放攻擊。這就是為什么為每一筆交易生成一個新的比特幣地址是至關(guān)重要的。

狀態(tài)

到目前為止,我們已經(jīng)定義了表示內(nèi)存中單個事務(wù)所需的所有數(shù)據(jù)結(jié)構(gòu)。但是我們還需要告訴Substrate通過在一段時間內(nèi)保留此信息,在狀態(tài)數(shù)據(jù)庫中存儲什么以支持鏈的業(yè)務(wù)邏輯。

這是通過使用decl_storage定義模塊存儲來完成的!marco:

decl_storage! {

trait Store for Module as Utxo {

/// All valid unspent transaction outputs are stored in this map.

/// Initial set of UTXO is populated from the list stored in genesis.

UnspentOutputs build(|config: &GenesisConfig| {

config.initial_utxo

.iter()

.cloned()

.map(|u| (BlakeTwo256::hash_of(&u), u))

.collect::>()

}): map H256 => Option;

/// Total leftover value to be redistributed among authorities.

/// It is accumulated during block execution and then drained

/// on block finalization.

LeftoverTotal: Value;

/// Outputs that are locked

LockedOutputs: map H256 => Option>;

}

add_extra_genesis {

config(initial_utxo): Vec;

}

}

上面的代碼實際上它僅定義了三件事:未使用的輸出列表,當前剩余值量以及已鎖定且除非解鎖就無法使用的輸出列表。除此之外,它還定義了在引導過程中如何使用一組初始的UTXO填充鏈。

需要要注意的是,狀態(tài)存儲與區(qū)塊存儲有很大不同。

區(qū)塊存儲是每個區(qū)塊鏈節(jié)點的重要組成部分,用于存儲該鏈中的區(qū)塊。如今只有專用的存檔節(jié)點將整個鏈存儲在本地,而普通節(jié)點僅管理最近區(qū)塊的臨時子集。

另一方面,狀態(tài)存儲與業(yè)務(wù)邏輯有關(guān)。它包含反映業(yè)務(wù)實體及其關(guān)系的當前狀態(tài)所需的所有數(shù)據(jù)。為了驗證傳入交易,您唯一需要知道的是所有受影響方的狀態(tài)及其資金額。這就是為什么即使是輕度客戶也能夠驗證交易的原因。

設(shè)計邏輯

當我們說Alice從Bob那里得到一些資金時,我們的意思是根據(jù)規(guī)則,Bob用來支付Alice的一組UTXO必須標記為已用(以防止Bob以后重復使用)。然后Bob為Alice創(chuàng)建的一組新UTXO現(xiàn)在必須被記住是有效的,這樣Alice就可以在之后使用它們了。

這些規(guī)則是業(yè)務(wù)邏輯的本質(zhì),在驗證和調(diào)度傳入事務(wù)時需要考慮這些規(guī)則。

讓我們看一下整個UTXO模塊的入口點:

decl_module! {

pub struct Module for enum Call where origin: T::Origin {

/// Dispatch a single transaction and update UTXO set accordingly

pub fn execute(origin, transaction: Transaction) -> Result {

ensure_inherent(origin)?;

let leftover = match Self::check_transaction(&transaction)? {

CheckInfo::MissingInputs(_) => return Err("all parent outputs must exist and be unspent"),

CheckInfo::Totals { input, output } => input - output

};

Self::update_storage(&transaction, leftover)?;

Self::deposit_event(Event::TransactionExecuted(transaction));

Ok(())

}

/// Handler called by the system on block finalization

fn on_finalise() {

let authorities: Vec<_> = Consensus::authorities().iter().map(|&a| a.into()).collect();

Self::spend_leftover(&authorities);

}

}

}

我們定義了兩個函數(shù):execute和on_finalize

execute函數(shù)是整個UTXO邏輯的關(guān)鍵。它接受單個事務(wù),對其進行檢查,如果有效,則通過更新存儲應(yīng)用該事務(wù)。最后它存儲一個事件,表示一個事務(wù)剛剛被處理。

當剛剛形成一個充滿交易的單個塊時,將調(diào)用on_finalize事件處理程序。通過觸發(fā)該事件處理程序,Substrate允許運行時根據(jù)需要采取一些措施。我們使用此處理程序從參與創(chuàng)建此塊的驗證程序之間的所有事務(wù)中重新分配合并的剩余價值,作為對其工作的獎勵。

交易檢查

為了驗證傳入事務(wù),我們需要確保以下內(nèi)容:

1. 輸入和輸出不為空。

2. 所有輸入與現(xiàn)有的、未使用的和未鎖定的輸出匹配。

3. 每個輸入只使用一次。

4. 每個輸出只定義一次,并且有一個非零值。

5. 總產(chǎn)值不得超過總產(chǎn)值。

6. 新的輸出不能與現(xiàn)有的沖突。

7. 輸入和輸出值之和不能溢出。

8. 提供的簽名有效。

違反任何一項檢查都可能導致連鎖安全性問題,因此正確實施它們至關(guān)重要。幸運的是,邏輯非常簡單明了:

pub fn check_transaction(transaction: &Transaction) -> CheckResult<'_> {

ensure!(!transaction.inputs.is_empty(), "no inputs");

ensure!(!transaction.outputs.is_empty(), "no outputs");

{

// Collecting inputs into a set where every element is unique.

// If two equal elements are inserted, only one will remain.

let input_set: BTreeMap<_, ()> = transaction

.inputs

.iter()

.map(|input| (input, ()))

.collect();

// Ensuring that the size of original collection and the set are equal.

// If they are not, then due to pigeonhole principle, some entries must

// have been maliciously mentioned several times.

ensure!(

input_set.len() == transaction.inputs.len(),

"each input must be used only once"

);

}

{

let output_set: BTreeMap<_, ()> = transaction

.outputs

.iter()

.map(|output| (output, ()))

.collect();

ensure!(

output_set.len() == transaction.outputs.len(),

"each output must be defined only once"

);

}

let mut total_input: Value = 0;

let mut missing_utxo = Vec::new();

for input in transaction.inputs.iter() {

// Fetch UTXO from the storage

if let Some(output) = >::get(&input.parent_output) {

ensure!(!>::exists(&input.parent_output), "utxo is locked");

// Check that we're authorized to spend this UTXO

ensure!(

ed25519_verify(

input.signature.as_fixed_bytes(),

input.parent_output.as_fixed_bytes(),

&output.pubkey

),

"signature must be valid"

);

// Add the value to the input total

total_input = total_input.checked_add(output.value).ok_or("input value overflow")?;

} else {

missing_utxo.push(&input.parent_output);

}

}

let mut total_output: Value = 0;

for output in transaction.outputs.iter() {

ensure!(output.value != 0, "output value must be nonzero");

let hash = BlakeTwo256::hash_of(output);

ensure!(!>::exists(hash), "output already exists");

total_output = total_output.checked_add(output.value).ok_or("output value overflow")?;

}

if missing_utxo.is_empty() {

ensure!(total_input >= total_output, "output value must not exceed input value");

Ok(CheckInfo::Totals { input: total_input, output: total_output })

} else {

Ok(CheckInfo::MissingInputs(missing_utxo))

}

}

您可能注意到,除了事務(wù)檢查之外,此函數(shù)還收集一些信息。讓我們看看它的定義:

/// Result of transaction verification

pub type CheckResult<'a> = rstd::result::Result, &'static str>;

/// Information collected during transaction verification

pub enum CheckInfo<'a> {

/// Combined value of all inputs and outputs

Totals { input: Value, output: Value },

/// Some referred UTXOs were missing

MissingInputs(Vec<&'a H256>),

}

/// Representation of UTXO value

pub type Value = u128;

稍后將顯示,我們使用總的 inputs和outputs來計算交易的優(yōu)先級,并將剩余價值的一部分作為塊式獎勵在驗證者之間重新分配。

但是如果交易未通過驗證,談?wù)撨@些價值絕對沒有任何意義。否則攻擊者將能夠通過淹沒交易池并阻止正常交易被派發(fā),從而故意制作具有最高優(yōu)先級的交易并對鏈進行DoS?;蛘?,它可能會“憑空產(chǎn)生”大量剩余價值以利用獎勵系統(tǒng)。

通過將數(shù)據(jù)組織為Rust枚舉,可以防止意外誤用,因為只有在交易有效時值才可用。反之亦然,只有在發(fā)現(xiàn)事務(wù)引用狀態(tài)數(shù)據(jù)庫中不存在的某個UTXO時,才可以使用缺少輸入的列表。這樣一來,就不會濫用API,這有利于提高可讀性和鏈安全性。

狀態(tài)更新

如果交易經(jīng)過驗證并證明是正確的,那么我們要做的就是更改鏈狀態(tài)以反映該交易所做的更改:

/// Update storage to reflect changes made by transaction

fn update_storage(transaction: &Transaction, leftover: Value) -> Result {

// Calculate new leftover total

let new_total = >::get()

.checked_add(leftover)

.ok_or("leftover overflow")?;

// Storing updated leftover value

>::put(new_total);

// Remove all used UTXO since they are now spent

for input in &transaction.inputs {

>::remove(input.parent_output);

}

// Add new UTXO to be used by future transactions

for output in &transaction.outputs {

let hash = BlakeTwo256::hash_of(output);

>::insert(hash, output);

}

Ok(())

}

基本上,我們刪除所有現(xiàn)在認為已用完的輸入,并添加所有新輸出以將其標記為可用。我們還將剩余的值累積在臨時存儲變量LeftoverTotal中,該變量將在區(qū)塊確定期間使用。

阻止獎勵

區(qū)塊完成后,就該獎勵創(chuàng)作該區(qū)塊的節(jié)點了。這是通過重新分配從此區(qū)塊中包括的所有事務(wù)中收集的剩余價值來完成的:

/// Redistribute combined leftover value evenly among authorities

fn spend_leftover(authorities: &[H256]) {

let leftover = >::take();

let share_value = leftover / authorities.len() as Value;

if share_value == 0 { return }

for authority in authorities {

let utxo = TransactionOutput {

pubkey: *authority,

value: share_value,

salt: System::block_number() as u32,

};

let hash = BlakeTwo256::hash_of(&utxo);

if !>::exists(hash) {

>::insert(hash, utxo);

runtime_io::print("leftover share sent to");

runtime_io::print(hash.as_fixed_bytes() as &[u8]);

} else {

runtime_io::print("leftover share wasted due to hash collision");

}

}

}

邏輯非常簡單:我們接受一個權(quán)限列表,然后將剩余的總值除以權(quán)限數(shù)平均得出一個share_value。然后,我們?yōu)槊總€作者創(chuàng)建一個UTXO,并將其插入UnspentOutputs中。我們將當前區(qū)塊號用作salt值,以防止上述潛在的重放攻擊。

我們還通過將獎勵UTXO插入UnspentOutputs來進行檢查,以確保我們不會意外覆蓋一些恰好具有相同哈希值的現(xiàn)有UTXO。這種情況在實踐中極為罕見,但是不幸的是,如果有人因為常規(guī)獎勵UTXO覆蓋了他或她的UTXO而損失了數(shù)百萬美元的UTXO,那將是不幸的。

乍一看,我們似乎是憑空創(chuàng)造價值,但仔細想想,人們可能會意識到,全局價值不會增加,因為交易所有者明確放棄了部分資金,以換取優(yōu)先權(quán)。

最后,由于每個區(qū)塊發(fā)起人都知道所有詳細信息,例如區(qū)塊編號,該特定時代使用的會話密鑰,當然還有與該會話密鑰匹配的秘密密鑰,因此區(qū)塊發(fā)起人將始終能夠重構(gòu)UTXO,計算其哈希值,即使沒有將UTXO存儲在任何地方也可以要求其獎勵。

UTXO鎖定

這就是與比特幣不同的地方。

據(jù)我所知,比特幣規(guī)范并沒有規(guī)定哪些信息需要存儲在磁盤上以及如何存儲。唯一重要的是比特幣協(xié)議本身,它是根據(jù)交易和區(qū)塊來制定的。因此,每個節(jié)點必須建立自己的理解,在區(qū)塊鏈歷史的任何給定點上,哪些UTXO是有效的。

相反,根據(jù)定義,我們的UTXO實現(xiàn)具有所有參與節(jié)點都同意的全局狀態(tài)數(shù)據(jù)庫。眾所周知,它用于存儲UTXO狀態(tài)和剩余的臨時值。由于狀態(tài)數(shù)據(jù)庫是共識的一部分,因此我們可以在業(yè)務(wù)邏輯中依賴狀態(tài)數(shù)據(jù)庫的內(nèi)容,并確保所有其他節(jié)點都將這樣做。

但沒有什么能阻止我們儲存額外的東西。例如我們可以將現(xiàn)有UTXO的哈希映射映射到定義該UTXO的鎖定狀態(tài)的結(jié)構(gòu)。如果UTXO被鎖定,則不允許以通常的方式使用它:

#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]

#[derive(Clone, Encode, Decode, Hash)]

pub enum LockStatus {

// Referred UTXO is locked

Locked,

// Referred UTXO is locked until specified block

LockedUntil(T::BlockNumber),

}

decl_storage! {

trait Store for Module as Utxo {

...

/// Outputs that are locked

LockedOutputs: map H256 => Option>;

}

}

很像鎖在保險箱里的現(xiàn)金:你可以最終使用它,但不早于你打開保險箱的時候。它是可用的,只是鎖上了。

你可能在想,為什么一個人會需要這個?您會發(fā)現(xiàn),在加密貨幣的世界中,有一種趨勢是用貪婪程度更低,更有效的方法來代替舊的廢物證明算法(proof-of-waste)。一種可能是將資金本身用作保證同peer行為正常的保證。

基本上,有人會說:“我發(fā)誓要遵守規(guī)則。這是我的錢。請把它鎖在安全的地方。如果有人證明我的行為不當,那么我的錢就必須削減或在誠實的參與者之間分配。”當然,如果這樣的人隨后希望取回他或她的資金,則網(wǎng)絡(luò)將檢查是否沒有惡意行為。在最后期限內(nèi)提取,然后解鎖資金。通常,鎖定的資金越多,您獲得的能力,投票權(quán)重或收入就越多。此類系統(tǒng)通常簡稱為權(quán)益證明或PoS。

只要網(wǎng)絡(luò)中三分之二以上的節(jié)點沒有惡意,并且按照協(xié)議操作,這就可以正常工作。除了執(zhí)行常規(guī)任務(wù)外,這些節(jié)點還將支持PoS。

在類似以太坊的區(qū)塊鏈中,在調(diào)度交易時,對可用資金的推論可能非常復雜:每個節(jié)點必須確保有足夠的可用資金,尤其是因為可能存在與時間相關(guān)的復雜合約。

有趣的是,我們的UTXO實現(xiàn)以幾行代碼來完成。與以太坊式的鏈相反,類比特幣的鏈的資金已經(jīng)以自然的方式分配。我們可以輕松地鎖定單個UTXO,并在滿足某些解鎖條件之前防止其被花費。

由于狀態(tài)數(shù)據(jù)庫不是其原始規(guī)范的一部分,因此在比特幣中很難做到這一點。因此,很難在任何給定的時間點推斷哪個UTXO被鎖定,更不用說客戶端兼容性問題了。

交易排序

在談到鏈的業(yè)務(wù)邏輯時,我們提到Substrate為我們完成了所有骯臟的工作,例如處理塊存儲,執(zhí)行網(wǎng)絡(luò)交互和進行共識投票。但這并非總是如此。我們已經(jīng)說過,我們的runtime原子性一次調(diào)度一個事務(wù)。因此如果該交易有效,則狀態(tài)將相應(yīng)更改。

但是如果兩個從屬事務(wù)在短時間內(nèi)到達同一節(jié)點會發(fā)生什么呢?真實的網(wǎng)絡(luò)是復雜且不可預測的。連接性問題和突然的拓撲更改可能會對傳輸?shù)臄?shù)據(jù)造成各種影響。值得注意的是,消息可能會丟失,延遲或重新排序。后一個事實對我們尤為重要。

想象一個情況,我們有兩個事務(wù),A和B,B依賴于A。在UTXO的情況下,這意味著B消耗了A創(chuàng)建的UTXO。如果B在A之前到達,我們可能會遇到這樣的情況節(jié)點運行時將無法檢查事務(wù)的有效性,因為它引用了看似不存在的UTXO。當然,我們確實知道它存在,但尚未交付,但是節(jié)點不知道。本質(zhì)上,它有兩個選擇:

1. 只需將交易B視為無效即可。如果原始發(fā)送人重新廣播該交易,它仍將有機會被應(yīng)用,但不會早于A被調(diào)度。此解決方案可能有效,但它是骯臟且無效的。此外,一些嚴重的網(wǎng)絡(luò)問題可能導致無法分配B的情況,從而使整個系統(tǒng)無用。我們可以做得更好。

2. 將事務(wù)B的分派推遲到有意義的時候。在我們的情況下,我們需要以某種方式等待A的發(fā)送。

第二種選擇似乎更有趣,但是在實踐中我們該如何做呢?通過其本身的設(shè)計,Substrate對運行時內(nèi)部或鏈的業(yè)務(wù)邏輯一無所知。實際上,從其角度來看,Substrate就像不透明的字節(jié)數(shù)組一樣“看到”我們的交易。

這里的解決方案是“解釋” Substrate如何處理我們的交易以及如何正確排序它們。這是通過使用事務(wù)池向運行時公開的專用TaggedTransactionQueue API完成的。

在Substrate中,每個事務(wù)都與兩組標簽相關(guān)聯(lián):require和Provides。標簽只是代表某個唯一值的任意字節(jié)向量。第一組描述此事務(wù)需要哪些標簽,而第二組定義此事務(wù)提供的標簽。

在上述情況下,我們需要通過聲明A提供一些標簽而B消耗與其要求相同的標簽來將事務(wù)A和B鏈接在一起。為了簡單起見,我們可以使用UTXO哈希作為標簽。

通過遍歷事務(wù)并查詢其標記,事務(wù)池以一種順序組織它們,以使每個事務(wù)都可以滿足其要求。那些熟悉計算機科學的人可能會意識到這類似于拓撲順序。

有時兩個事務(wù)不相互依賴,但又依賴于第三次事務(wù)。例如我們可能有交易A產(chǎn)生兩個輸出,交易B和C分別花費這兩個輸出。這將導致B和C都依賴于A。拓撲排序狀態(tài)規(guī)定必須在B和C之前調(diào)度A,但是未定義分發(fā)B和C的順序。在這種情況下,事務(wù)池使用其他條件來確定事務(wù)的優(yōu)先級。

經(jīng)典解決方案是將剩余值的數(shù)量用作優(yōu)先級。交易所有者有意留給當局的資金越多,交易優(yōu)先級就越高,雙贏。(鏈三豐)

讓我們看看它如何在我們的鏈中實現(xiàn):

impl runtime_api::TaggedTransactionQueue for Runtime {

fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity {

// A bunch of imports

use srml_support::IsSubType;

use runtime_primitives::{

traits::Hash,

transaction_validity::{TransactionLongevity, TransactionPriority, TransactionValidity},

};

// Extrinsics representing UTXO transaction need some special handling

if let Some(&utxo::Call::execute(ref transaction)) = IsSubType::>::is_aux_sub_type(&tx.function) {

// List of tags to require

let requires;

// Transaction priority to assign

let priority;

match >::check_transaction(&transaction) {

// Verification failed

Err(e) => {

runtime_io::print(e);

return TransactionValidity::Invalid(1);

}

// Transaction was fully verified and is valid

Ok(utxo::CheckInfo::Totals { input, output }) => {

關(guān)鍵詞: UTXO 竊取金錢 execute函數(shù)

精選 導讀

募資55億港元萬物云啟動招股 預計9月29日登陸港交所主板

萬科9月19日早間公告,萬物云當日啟動招股,預計發(fā)行價介乎每股47 1港元至52 7港元,預計9月29日登陸港交所主板。按發(fā)行1 167億股計算,萬

發(fā)布時間: 2022-09-20 10:39
管理   2022-09-20

公募基金二季度持股情況曝光 隱形重倉股多為高端制造業(yè)

隨著半年報披露收官,公募基金二季度持股情況曝光。截至今年二季度末,公募基金全市場基金總數(shù)為9794只,資產(chǎn)凈值為269454 75億元,同比上

發(fā)布時間: 2022-09-02 10:45
資訊   2022-09-02

又有上市公司宣布變賣房產(chǎn) 上市公司粉飾財報動作不斷

再有上市公司宣布變賣房產(chǎn)。四川長虹25日稱,擬以1 66億元的轉(zhuǎn)讓底價掛牌出售31套房產(chǎn)。今年以來,A股公司出售房產(chǎn)不斷。根據(jù)記者不完全統(tǒng)

發(fā)布時間: 2022-08-26 09:44
資訊   2022-08-26

16天12連板大港股份回復深交所關(guān)注函 股份繼續(xù)沖高

回復交易所關(guān)注函后,大港股份繼續(xù)沖高。8月11日大港股份高開,隨后震蕩走高,接近收盤時觸及漲停,報20 2元 股。值得一提的是,在7月21日

發(fā)布時間: 2022-08-12 09:56
資訊   2022-08-12

萬家基金再添第二大股東 中泰證券擬受讓11%基金股權(quán)

7月13日,中泰證券發(fā)布公告,擬受讓齊河眾鑫投資有限公司(以下簡稱齊河眾鑫)所持有的萬家基金11%的股權(quán),交易雙方共同確定本次交易的標的資

發(fā)布時間: 2022-07-14 09:39
管理   2022-07-14

央行連續(xù)7日每天30億元逆回購 對債市影響如何?

央行12日再次開展了30億元逆回購操作,中標利率2 10%。這已是央行連續(xù)7日每天僅進行30億元的逆回購縮量投放,創(chuàng)下去年1月以來的最低操作規(guī)

發(fā)布時間: 2022-07-13 09:38
資訊   2022-07-13

美元指數(shù)創(chuàng)近20年新高 黃金期貨創(chuàng)出逾9個月新低

由于對美聯(lián)儲激進加息的擔憂,美元指數(shù)11日大漲近1%創(chuàng)出近20年新高。受此影響,歐美股市、大宗商品均走弱,而黃金期貨創(chuàng)出逾9個月新低。美

發(fā)布時間: 2022-07-13 09:36
資訊   2022-07-13

美股三大股指全線下跌 納斯達克跌幅創(chuàng)下記錄以來最大跌幅

今年上半年,美股持續(xù)回落。數(shù)據(jù)顯示,道瓊斯指數(shù)上半年下跌15 3%,納斯達克綜合指數(shù)下跌29 5%,標普500指數(shù)下跌20 6%。其中,納斯達克連續(xù)

發(fā)布時間: 2022-07-04 09:51
推薦   2022-07-04

融資客熱情回升 兩市融資余額月內(nèi)增加超344億元

近期A股走強,滬指6月以來上漲4%,融資客熱情明顯回升。數(shù)據(jù)顯示,截至6月16日,兩市融資余額1 479萬億元,月內(nèi)增加344 67億元,最近一個半

發(fā)布時間: 2022-06-20 09:41
資訊   2022-06-20

4個交易日凈買入超百億元 北向資金持續(xù)流入A股市場

北向資金凈流入態(tài)勢延續(xù)。繼6月15日凈買入133 59億元后,北向資金6月16日凈買入44 52億元。自5月27日至今,除6月13日以外,北向資金累計凈

發(fā)布時間: 2022-06-17 09:37
推薦   2022-06-17