美文网首页
用Substrate区块链实现UTXO功能

用Substrate区块链实现UTXO功能

作者: SeanC52111 | 来源:发表于2019-11-19 20:46 被阅读0次

首先我们定义实现UTXO所需要的结构体:

/// 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<TransactionInput>,

    /// UTXOs to be created as a result of current transaction dispatch
    pub outputs: Vec<TransactionOutput>,
}

结构体里声明了inputs, ouptuts,为UTXO结构中的输入和输出。#[...]表示一系列属性,它们可以告知Rust编译器来实现不同的功能,比如比较函数,哈希函数,序列化函数等。

这里的inputsoutputs的类型均为存有TransactionInputTransactionOutput的Vec(向量)。下面我们来定义对应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所需要的全部信息。首先我们需要指明我们要使用哪个当前存在的UTXO,以便于之后将其花掉。最好的方法就是用哈希来充当它的标识。parent_output就存有这样的哈希。

要花掉UTXO,所有者必须用私钥签名,之后即可用公钥进行验证。这样的证明proof被存在signature域中。

接下来我们看TransactionOutput结构:

/// 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,
}

其中,盐值salt是用来对相同的value, pubkey每次产生不同的Hash值。

状态

前面我们已经定义了相关的数据结构,比如如何在区块链中表示UTXO对应的交易结构。下面我们来看看如何存储这些transactions到Substrate的state db中。

在之前的博客中 https://www.jianshu.com/p/f9a41a2fc90a
我们知道在Substrate中进行自定义存储需要在decl_storage! macro当中定义。

decl_storage! {
    trait Store for Module<T: Trait> 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<T>| {
            config.initial_utxo
                .iter()
                .cloned()
                .map(|u| (BlakeTwo256::hash_of(&u), u))
                .collect::<Vec<_>>()
        }): map H256 => Option<TransactionOutput>;

        /// 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<LockStatus<T>>;
    }

    add_extra_genesis {
        config(initial_utxo): Vec<TransactionOutput>;
    }
}

上述代码定义了:

  • 未花掉的output
  • 当前剩余的金额
  • 被锁定的outputs

同时,上述代码还定义了在区块链启动得时候初始化UTXO。
需要注意的是,区块的存储和状态的存储有很大的区别。区块的存储对于区块链节点来说是十分重要的组成部分,它被用来储存区块链中的区块。而对于状态存储来说,它是和逻辑息息相关的。它包含了所有反应当前状态的数据和关系。为了验证新接收的transactions,我们只需要关心各个参与的party的状态和资金。这也解释了为何情节点也可以验证transactions。

逻辑

当我们说Alice收到来自Bob的转账,实际上发生的是一些列Bob付给Alice的UTXO会被标记为已经花掉。紧接着,一些列新的UTXO(由Bob产生给Alice的)会变成有效的UTXO(可在之后被使用)。

这就是给予UTXO转账的基本逻辑,我们在验证和分发transactions的时候需要考虑这样的逻辑。下面我们看看具体UTXO module(模块)的代码:

decl_module! {
    pub struct Module<T: Trait> 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);
        }
    }
}

相关文章

  • 用Substrate区块链实现UTXO功能

    首先我们定义实现UTXO所需要的结构体: 结构体里声明了inputs, ouptuts,为UTXO结构中的输入和输...

  • Chainx 简介

    Chainx 是使用 Polkadot 技术 Substrate 开发的一个项目,Substrate 简化了区块链...

  • 区块链面试问题整理(以太坊相关,持续更新)

    区块链相关 1. 什么是UTXO, 以太坊转账流程 UTXO 模式(Unspent Transaction Out...

  • Cumulus

    Cumulus Cumulus用来连接Substrate生态区块链到Polkadot。 Polkadot提供中继链...

  • TransactionInput

    简单地说,交易输入是指向UTXO的指针。它们指向特定的UTXO,并被交易哈希和在区块链中记录UTXO的序列号作为参...

  • 创造我们的NFT,使用Substrate 创建KItties 一

    本次研讨会将教您有关构建区块链的所有知识,该区块链处理称为Substrate Kitties的不可替代令牌(NFT...

  • 打造公链-造轮子(4)

    交易 在区块链中,交易一旦被创建,就没有任何人能够再去修改或者删除它。 UTXO模型 Bitcoin采用UTXO(...

  • 以太坊,区块链之光

    1、开创先河的比特币 上篇我们讲了货币的价值,讲了比特币。比特币,用区块链的结构保证了记录不被篡改,用UTXO来做...

  • Substrate 区块链上手

    Note首先需要安装nodejs,npm,因为之后的操作需要和网页界面进行交互。然后需要安装substrate,选...

  • 2021-10-28 起步 Substrate

    Getting Started Overview 本资源的目的是帮助读者了解使用Substrate进行区块链开发的...

网友评论

      本文标题:用Substrate区块链实现UTXO功能

      本文链接:https://www.haomeiwen.com/subject/kokgictx.html