乐趣区

关于区块链:从区块链到-NFT-到元宇宙

以比特币白皮书来说,区块链的实质是一个 P2P(点对点)的分布式账本,节点收回交易时须要向四周节点播送,全节点(还有轻节点等,轻节点个别只保留和本人无关的数据)将收到的交易信息写入区块体中,在共识机制(PoW 即挖矿,还有其余如 PoS、DPoS 机制)作用下获取到记账的权限(即认证某些交易数据,向区块链中写入区块的权限),将新区块播送至四周节点,其它节点校验数据有效性和记账权限后依据区块数据同步本地状态,从而达成整个区块网络的状态统一,同时因为新区块头中有前一区块的关联信息,从而使区块之间达成连贯,造成区块链。

简略来说,就是网络中所有结点做完全相同的操作在本地保护一个状态一致性的分布式系统。

  • 区块链构造:区块 + 哈希链接

    • 链:新的区块通过区块间哈希(哈希算法是一种固定输出产生固定输入的算法,能够了解为对输出产生了一个身份 ID)关联,区块间通过这种关联成链
    • 区块:

      • 区块体:

        • 区块体的构造往往是一颗树
        • 树的叶子结点存储理论数据,即账本信息(如交易信息)等
        • 两两向上逐层求得哈希值造成哈希树(即 Merkle Tree 或应用其变种构造)
      • 区块头:负责基本功能,个别蕴含以下局部

        • 对前一个区块的哈希求值(仅对前一区块的区块头的内容进行哈希运算)
        • 哈希树的根哈希
        • 工夫戳

  • 防篡改:

    • 单个块:当单个块中的交易信息被某个结点批改后,势必会逐层向上影响至存储在区块头中的哈希树的根哈希,那么就须要批改根哈希能力达成单个区块数据篡改有效性
    • 链:如果某个区块中的根哈希被批改,那么对这个区块的区块头进行哈希运算必然会产生新值,和它的下一个区块中的对它的哈希援用的数值对不上,则必然会影响到后续整个链上的所有区块,所以须要批改后续的所有区块能力达成篡改的有效性
    • 这种对整个区块链篡改的可行性须要毁坏已造成的共识,须要有压制性的劣势,实践上在参与者泛滥的零碎中很难达成,从而保障了区块链的防篡改特色

比特币

状态

比特币的节点在本地保护了一个账本叫做 UTXO(Unspent Transaction Output)的状态,即未应用的交易输入,能够简略的了解为某笔未应用的转账输出,用于进行后续转账的转出应用。

运行机制

比特币区块的区块体中以哈希树的构造存储了新产生的每笔交易。

单笔交易的一种协定信息的示例如下:

In: 
// 示意这次交易应用的资金的起源
    Previous tx: f5d8...430901c91
    // 资金来源所在交易的哈希
    Index: 0
    // 资金来源交易哈希中的哪个转出
    scriptSig: 3045...798a4 618c...41501
    // 对申明的资金来源的解锁脚本,含有签名和公钥
    // 能够简略了解为银行卡号和明码

Out: // 表明这次交易的输入
    Value: 5000000000
    // 金额
    scriptPubKey: OP_DUP OP_HASH160 4043...549d OP_EQUALVERIFY OP_CHECKSIG
    // 锁定脚本,含有对公钥的哈希和一些运算符,应用这笔转出的交易须要在它的 scriptSig 提供能够通过脚本的信息能力解锁
    // 能够了解为银行卡号的哈希和一些操作指令 
  • 非对称加密概念科普:

    • 公钥、私钥是是成对生成的
    • 公钥公开给零碎中的其余节点应用,私钥集体保留
    • 钱包地址个别是应用公钥进行一系列运算得来的
    • 咱们不明确辨别钱包地址和公钥,可不精确的了解为

      • 公钥、钱包:账户账号
      • 私钥:账户明码
    • 公钥私钥还有一密码学特色:繁多钥匙进行加密的数据必然且只能用另一钥匙进行解密

      • 加密:发送者应用接受者的公钥对内容加密,只有接受者能力用本人的私钥对内容解密,防止了发送门路上的数据泄露
      • 签名验证:更进一步,收回者应用本人的私钥对内容进行签名,将签名和内容发给接受者,接受者应用发送者的公钥对签名解密,发现签名和内容统一,阐明发送门路上,内容未被篡改
  • 交易信息:每笔交易以之前的交易记录为根底,须要满足输出等于输入(其实是存在差额的,差额会作为节点的工作费)

    • 示例:A 账号要领取 6 比特币给 D 账号,则交易数据写为:

      • 输出:

        • 之前某笔交易的输入(B 账号领取 2 比特币给 A 账号)
        • 之前某笔交易的输入(C 账号领取 3 比特币给 A 账号)
        • 之前某笔交易的输入(D 账号领取 2 比特币给 A 账号)
      • 输入:

        • 领取 6 比特币给 D 账号
        • 领取 1 比特币给 A 账号
    • 特点:

      • 须要阐明收入的起源
      • 阐明的资金来源中的金额不能拆分,多出的局部能够通过找零的形式转给本人
  • 交易信息进链:

    • 分布式:

      • 网络上很多节点进行存储和数据认证
      • 发送节点向四周节点播送交易信息
      • 每个节点都保留了区块链的残缺或局部数据
    • 有效性:如某账号同时发送了多条矛盾的交易信息

      • 全节点将收到的交易信息进行验证并写入区块
      • 验证过程会应用到交易信息中的脚本

        • 节点收回的交易信息蕴含

          • 对资金来源的阐明
          • 对每笔资金来源的解锁信息
        • 接管到信息的节点:

          • 确认 UTXO:验证资金来源是否存在 UTXO 中,即是否未应用
          • 执行脚本:

            • 将解锁签名和对应交易输入蕴含的锁定脚本拼接后以栈构造执行
            • 以示例信息为例子,拼接为 [私钥签名, 公钥](解锁脚本提供)[OP_DUP, OP_HASH160, 公钥哈希, OP_EQUALVERIFY, OP_CHECKSIG](锁定脚本提供)
            • 执行大抵为:

              • 将公钥取出(OP_DUP)
              • 进行哈希 160 运算(OP_HASH160)
              • 将后果与公钥哈希比照是否相等(OP_EQUALVERIFY)
              • 验证签名(OP_CHECKSIG)
          • 确权:如何确认 UTXO 的所有权

            • 脚本执行过程中的将解锁脚本中公钥哈希后与锁定脚本中公钥哈希比照的过程即是确定所有所有权的操作
            • 确认了提供的银行卡账号的确是有这笔余额的账号
          • 交易信息防伪:

            • 发送节点:

              • 对交易信息哈希取得一个摘要
              • 用发送节点的私钥对摘要加密生成签名
              • 将内容和签名进行播送
            • 接管节点:执行 OP_CHECKSIG 的过程

              • 应用发送节点的公钥对签名解密失去摘要 1
              • 对内容进行哈希,失去摘要 2
              • 摘要 1 等于摘要 2 则公钥、私钥匹配,内容可信
              • 即交易信息是解锁这个交易输入的公钥的对应私钥拥有者写的
    • 一致性:网络传输问题,每个节点收到的交易信息可能不同,那么他们验证并写入区块的交易可能不同,如果都要上链则会造成最终生成的区块信息不统一

      • PoW:应用共识规定让单位工夫内(约 10 分钟)只有一个节点有非法公布区块的势力,即取得了记账权
      • 规定:

        1. 将新区块的内容(前一个区块头哈希、这个区块的根本信息、新区块的交易信息根哈希)组合成字符串
        2. 在新区块字符串的开端加上一个随机数,进行 SHA-256,如果后果的二进制前 72 位全是 0 则工作实现,这是一个工作量微小的碰运气工作
        3. 随着整体算力的进步会晋升难度(减少 0 的数量等)将出块工夫稳固在 10 分钟
      • 这个过程又因而被称为挖矿,须要大量的算力,进行 PoW 的节点又称为矿工
      • 节点支出:

        • 比特币网络处分:节点在出块的时候会写入对本人地址进行 6.25 个比特币输入的处分交易(Coinbase Newly Generated Coins)信息,此处分每过 21 万个区块减半,也是比特币的发币形式
        • 区块中的交易手续费:区块中所有输出和输入金额的差值,由矿工写给本人
    • 分叉:凑巧同时生成了两个区块,则两个块都会并列入链,造成长期分叉,在后续计算中采纳最长链准则,废除追加区块数量少的分叉
    • 交易确认:正是因为分叉和废块的存在,所以交易个别须要在持续追加多个区块后才会被确认,比特币个别须要通过 6 个区块的追加才算是绝对平安
    • 篡改:须要有超高的算力,篡改者的算力须要超过整个网络的算力能力实现篡改,才会使得本人的篡改分叉变成最长链,实现篡改

总结

  1. 应用 SHA-256 哈希算法和非对称加密制作数字签名进行防伪
  2. 执行交易信息中的脚本验证验证签名
  3. 应用区块链的区块存储比特币交易信息,应用哈希树存储并避免交易数据篡改
  4. 利用额定的工作规定达成网络一致性(拼算力)
  5. 将网络处分和交易手续费领取给矿工节点

以太坊

以太坊黄皮书

https://ethereum.github.io/ye…

以太坊同样是一个交易驱动的状态机,它反对智能合约,是可编程的区块链,一种去中心化利用的平台。

咱们看到比特币有肯定的脚本执行能力,然而其脚本比较简单,只反对几种固定的交易协定和脚本命令。以太坊则不同,其是图灵齐备的,区块链开发者可在反对范畴内自在编程。

构造

区块头

  • parentHash:前一区块区块头计算哈希
  • ommersHash:叔块哈希
  • beneficiary:出块处分的账户地址
  • stateRoot:状态树根哈希
  • transactionsRoot:交易树根哈希
  • receiptsRoot:收据树根哈希
  • logsBloom:数据布隆过滤器
  • gasLimit:区块汽油费下限,由矿工们独特保护

ommersHash

因为以太坊的出块速度较快,它呈现长期分叉的可能性也就越高,ommersHash 正是出于克制分叉的目标设计的,思路如下,被失效区块写入 ommersHash(最多写入两个)的废块也能够取得出块处分,第一级是 7/8,第二级是 6/8,失效区块写入一个废块也会有 1/32 的处分。

布隆过滤器

布隆过滤器是一种比拟高效然而不太准的查找算法,大抵机制如下:

  1. 提供一批哈希函数
  2. 将输出映射到阵列的几个点上
  3. 查问时查问阵列对应的点是否都有值即可

如:

  • 存:

    • apple 映射到点 1、7、9
    • banana 映射到点 1、3、7
  • 查:

    • orange 映射值为 1、3、9,都有值,则 orange 可能存在
    • peach 映射值为 2、3、7,2 无值,则 peach 肯定不存在

能够看到布隆过滤器对存在的判断是会误报的,然而不存在的肯定不会误报,所以适宜大数据量的过滤。

区块体

与比特币不同的是,以太坊的区块体中有三棵树:状态树、交易树、收据树,树的数据会被全节点保护在本地数据库中。

  • 状态树:

    • 一种变种压缩前缀哈希树(Merkle Patricia Tree,MPT)
    • 存储了所有已知(即产生过交易的)的账户的状态

      • 内部账户:即钱包地址,无代码,能转账或执行智能合约
      • 合约账户:创立合约时生成,存有代码,能被触发执行智能合约
      • 账户状态:

        • nonce:地址的交易数量或合约数量
        • balance:余额
        • codeHash:合约账户的代码的哈希,内部账户没有
        • storageRoot:账户内容(也是一棵 MPT 树)的根哈希
    • 新区块只会理论存储发生变化的账户的新状态,未发生变化的会指向之前的区块状态树的对应地位
  • 交易树:驱动状态树产生变更,也是 MPT,只保留区块中产生的交易信息

    • 音讯调用的信息
    • 合约账户创立的信息
  • 收据树:也是 MPT

    • 交易执行过程中的特定信息编码为交易数据,保留在一个索引为键的树中
    • 交易过程中创立的日志会形成区块头的 Bloom 过滤器

共识机制

目前以太坊也是应用 PoW(工作量证实)即挖矿的形式确定记账权。

由一个 seed 生成一个小数据集(MB 级别),再由小的数据集生成一个大的数据集(GB 级别大小),在应用区块头和一个 nonce 值求取哈希,映射至大数据集,读取大数据集中指标地位和相邻元素,再哈希,循环 64 次,算出一个哈希和挖矿目标值比照。失败则更换区块头中 nonce 从新计算。

同时以太坊也有像 PoS 机制转换的打算,在以太坊的难度调节机制中存在一个难度因子,此难度因子每 10 万个区块会翻一倍,是一个指数级的因子,所以又称为难度炸弹,因为 PoS 机制的上线不顺利,而难度炸弹导致出块速度晋升过快,所以以太坊批改了其代码,使得难度因子计算时减去了 300 万个区块,也是因为代码降级导致了以太坊网络的一次硬分叉,还好这次分叉网络节点都进行了代码降级。

智能合约

后面提到,以太坊网络中存在合约账户,账户内存有一段代码,所以智能合约就是依照既定逻辑执行的代码。

调用

内部账户调用合约账户,内部账户发动的合约账户调用也能够调用另一个合约账户。

内部账户调用时,将指标函数和参数写在 data 域中,向合约账户发动交易。

合约调用合约的一种形式:

contract A {event LogCallFoo (string str);
    function foo (string str) returns (uint) {emit LogCallFoo(str);
        return 123;
    }
}

contract B {
    uint ua; // callAFooDirectly 的执行返回值
    function callAFooDirectly (address addr) public {A a = A(addr);
        ua = a.foo("call foo directly); // 调用 a 地址的 foo 办法
    }
}

创立和运行

  • 智能合约代码编写(solidity 等)完之后,编译成 bytecode
  • 创立:内部账户向 0*0 地址发动交易,将代码放在 data 域中
  • 智能合约运行在 EVM 中
  • 调用智能智能合约的交易将函数和参数写在交易的 data 域中,公布到区块链上后,受到音讯的矿工则会依照参数执行代码
  • 发动调用的账户须要领取汽油费 GasLimit

    • 执行前全额扣除,开始执行,多退少补,不够则状态回滚,汽油费不退
    • 执行出错则整体状态回滚,汽油费不退:一个不谨严的例子,智能合约能发动了向 A、B 的转账,如果向 B 的转账出错了,向 A 转账的状态也会回滚
  • 每个交易执行之后造成一个收据,存有执行后果等信息

一个例子

这是一个拍卖出价的智能合约:

contract SimpleAuctionV1 {
    address public beneficiary; // 受益人
    uint public auctionEnd; // 完结工夫
    address public highestBidder; // 以后最高出价地址
    mapping(address => unit) bids; // 所有出价
    address[] bidders; // 所有出价地址
    bool ended; // 是否完结

    event HighestBidIncreased(address bidder, uint amount);
    event AuctionEnded(address winner, unit amount);

    constructor(uint _biddingTime, address _beneficiary) public {
        beneficiary = _beneficiary;
        auctionEnd = now + _biddingTime
    }
}

// 参加拍卖的地址向此合约地址发动交易并领取货币
function bid() public payable {require(now <= auctionEnd);
    require(bids[msg.sender]+msg.value > bids[highestBidder]);
    // 没出过价则把出价人存起来
    if (!(bids[msg.sender] == unit(0))) {bidders.push(msg.sender);
    }
    // 如果出价最高则批改以后最高出价人
    highestBidder = msg.sender;
    bids[msg.sender] += msg.value;
    emit HighestBidIncreased(msg.sender, bins[msg.sender]);
}
// 拍卖完结
function auctionEnd()public {require(now > auctionEnd);
    require(!ended);
    // 把最高出价转给受益人
    beneficiary.transfer(bids[highestBidder]);
    // 给没竞拍胜利的人退钱
    for (uint i = 0; i< bidders.length; i++) {address bidder = bidders[i];
        if (bidder == highestBidder) continue;
        bidder.transfer(bids[bidder]);
    }

    ended = true;
    emit AuctionEnded(highestBidder, bids[highestBidder]);
}
  • 这里存在一个问题:beneficiary.transfer,如果 beneficiary 是一个无奈承受领取的合约地址(未声明 payable 关键词),那么会导致 auctionEnd 执行失败,导致所有出价锁在智能合约地址中,永远无奈取出
  • 除此之外还有重入攻打,即调用的合约账户可能会反过来调用,引发循环执行

Code Is Law。

智能合约的逻辑由代码决定,已公布的合约代码无奈批改,如果公布新的代码则会生成另一个合约账户地址,所以就算有 Bug 也无奈批改。

The DAO(Decentralized Autonomous Organization):利用了重入攻打,黑客在本人的合约账户得收款函数中写了向 The DAO 发动调用的代码,应用循环调用的形式,转走了 5000 万 /1.5 亿美元的以太币,约 10% 的以太坊零碎总量的以太币,为了补救对以太坊稳定性的重大影响,通过软分叉修复失败,以太币质押投票,以太坊抉择了硬分叉的形式,将 The DAO 中的以太币强行转出,造成了社区决裂,造成以太坊硬分叉为 ETH、ETC。

NFT

从智能合约的例子中也能够看到,智能合约的开发者能够在合约账户的外部保护一个状态树。

其中的一种利用形式就是基于智能合约在区块链的网络内发行 Token,将所有持有人的状态保护在合约账户中。

NFT 正是这样的一种利用,全称为非同质化代币。NFT 的一大特色是,基于区块链的个性公开且防篡改的确定了某地址对某个数字作品的所有权。

一个 ERC721 规范(一种以太坊上发行 NFT 的规范)的 NFT 在区块链的数据示例:

  • 地址:0x40468d172cE354d3fAdAb06D0FA53eDdB2F3AA45
  • id:6
  • tokenURI:https://Opensea-creatures-api…)

因为 https 的内容会被批改,tokenURI 个别会用 IPFS 代替(分布式文件存储系统)。这个示例表明某地址领有编号为 6 的某个物品,其内容为 tokenURI 的内容。

大多数 NFT 的实现上看,在区块链上只是记录了一个作品拥有者的地址、作品的编号、以及这个作品的链接,而作品自身在链下。所以也呈现过事实中艺术家的作品被别人拿走铸造成 NFT 发售的状况,所以 NFT 不能解决线下的问题。 从实践上讲,NFT 会提供数字资产的流通性,然而不能给物品自身赋予价值

通过调用智能合约的函数,能够进行 NFT 的转移、交易。所以能够晓得,NFT 不单指某一个代币,而是一种代币类型,你也能够通过创立本人的智能合约,发行本人的 NFT 或 NFT 平台。

元宇宙

区块链应该会是元宇宙实现的一个技术,作为可任意复制的数字世界的数字资产进行确权的根底,如现有的 Decentraland 的虚构土地、发明品的售卖。

同时,对于在数字世界中诞生的虚构物品,因为不须要解决线下问题,NFT 的应用性应该会更高一些。

其余

  • 空块:在局部区块链中,新区块产生后,会先播送区块头再播送区块体,因为区块体数据较大,下载须要工夫,局部矿工节点会在收到区块头后就开始挖矿,因为向新区块体中写入的交易信息不能与已有区块抵触或反复,所以为保障在未拿到前一区块信息的状况下的新区块的有效性,不向新区块体中写入理论交易信息(处分信息除外),从而产生空块。

总结

  • 区块链存在交易慢、耗能高诟病,但要联合场景观测,在具体的场景下是比现有的解决方案快的。
  • 从实践上讲,基于区块链的 NFT 数字资产交易会提供数字资产的流通性,然而不能给物品自身赋予价值。
  • 投资有危险,追赶热点要审慎。

参考资料

  • 绝大部分的信息起源:https://www.bilibili.com/vide…
  • https://blog.csdn.net/vigor23…
退出移动版