(三) 区块链数据结构 – 交易

2023-11-17

区块由交易组成。区块体中包含若干项交易数据。


交易

交易主要包含两类数据:交易输入和交易输出。
- 交易输入用来指明钱的来源
- 交易输出用来指明钱的去向

除了交易输入和交易输出外,交易中还包含版本号和锁定时间。交易数据的存储结构如下:

交易数据存储格式

交易对象中的各个字段含义如下:

字段 大小 描述
version 4个字节 明确该笔交易参考的版本规则
numInputs 1-9个字节 交易中包含的输入数量
inputs 不定长 交易中包含的输入数据
numOutputs 1-9个字节 交易中包含的输出数量
outputs 不定长 交易中包含的输出数据
lockTime 4个字节 交易锁定时间

注:如果锁定时间为0,代表立即执行,无需锁定。如果该值小于5亿,则代表区块链到达该高度前,交易不会被执行,如果该值大于5亿,则该值代表Unix纪元时间戳,交易在该时间之后执行。

核心代码 - 变量定义
    // These are bitcoin serialized.
    private long version;                           //交易遵循的版本号
    private ArrayList<TransactionInput> inputs;     //交易的金钱来源
    private ArrayList<TransactionOutput> outputs;   //交易的金钱去向

    private long lockTime;                          //交易的锁定时间
核心代码 - 数据解析
    //解析区块原始字节数据,构造交易对象
    @Override
    protected void parse() throws ProtocolException {
        cursor = offset;

        version = readUint32();         //读取版本号
        optimalEncodingMessageSize = 4;

        // First come the inputs.
        long numInputs = readVarInt();  //读取输入交易量
        optimalEncodingMessageSize += VarInt.sizeOf(numInputs);

        inputs = new ArrayList<>((int) numInputs);

        //逐一解析输入交易对象
        for (long i = 0; i < numInputs; i++) {
            //构造输入交易对象
            TransactionInput input = new TransactionInput(params, this, payload, cursor, serializer);
            inputs.add(input);
            long scriptLen = readVarInt(TransactionOutPoint.MESSAGE_LENGTH);
            optimalEncodingMessageSize += TransactionOutPoint.MESSAGE_LENGTH + VarInt.sizeOf(scriptLen) + scriptLen + 4;
            cursor += scriptLen + 4;
        }

        // Now the outputs
        long numOutputs = readVarInt(); //读取输出交易量
        optimalEncodingMessageSize += VarInt.sizeOf(numOutputs);
        outputs = new ArrayList<>((int) numOutputs);

        //逐一解析输出交易对象
        for (long i = 0; i < numOutputs; i++) {
            //构造输出交易对象
            TransactionOutput output = new TransactionOutput(params, this, payload, cursor, serializer);
            outputs.add(output);
            long scriptLen = readVarInt(8);
            optimalEncodingMessageSize += 8 + VarInt.sizeOf(scriptLen) + scriptLen;
            cursor += scriptLen;
        }
        lockTime = readUint32();
        optimalEncodingMessageSize += 4;
        length = cursor - offset;
    }

交易输入

交易输入指明了交易的金钱来源。在比特币系统中,交易的金钱来源,并不来自于某一特定账户,而来自于其他人的输出。
比如A和B分别转给C一笔金钱,则当C向D支付时,需要用A和B的输出作为输入。

交易输入中,存储了其关联的交易输出指针,同时还存储了该输出的解锁脚本。

交易输入结构如下:

交易输入存储格式

交易输入中,各个字段的含义如下:

字段 大小 描述
hash 32个字节 关联输出所在的交易Hash地址
index 4个字节 关联输出在其交易输出集合中的索引
scriptLen 1-9个字节 解锁脚本长度
scriptBytes 不定长 解锁脚本数据
sequence 4个字节 序列号,暂未使用

注:只有解锁脚本正确,才能对输出进行消费。解锁脚本需要使用当前用户的秘钥进行签名,因此只有当前用户,能使用别人来的输出。

核心代码 - 变量定义
    // Allows for altering transactions after they were broadcast. Values below NO_SEQUENCE-1 mean it can be altered.
    private long sequence;
    // Data needed to connect to the output of the transaction we're gathering coins from.
    //关联的交易输出
    private TransactionOutPoint outpoint;
    // The "script bytes" might not actually be a script. In coinbase transactions where new coins are minted there
    // is no input transaction, so instead the scriptBytes contains some extra stuff (like a rollover nonce) that we
    // don't care about much. The bytes are turned into a Script object (cached below) on demand via a getter.
    // 脚本字节数组可能并不是实际的脚本,在创世区块中,没有输入交易,该字段可能存储其他数据。正常情况下,该数据会转换成脚本对象
    private byte[] scriptBytes;
核心代码 - 数据解析
    //通过区块的原始字节数据,构造输入交易对象
    @Override
    protected void parse() throws ProtocolException {
        //构造该输入交易对应的输出(接收地址)
        //解析数据时,会解析出对应输出所在交易的Hash地址以及交易输出对应的索引值
        outpoint = new TransactionOutPoint(params, payload, cursor, this, serializer);
        cursor += outpoint.getMessageSize();
        int scriptLen = (int) readVarInt(); //读取脚本长度
        length = cursor - offset + scriptLen + 4;

        scriptBytes = readBytes(scriptLen); //读取解锁脚本数据
        sequence = readUint32();            //序列号,目前未使用
    }

交易输出

交易输出指明了钱的去向,拥有该输出,并用私钥解密后,方可作为其他交易的输入,进行消费。

交易输出中,存储了支付的金额以及锁定脚本。交易输出的存储结构如下:

交易输出存储格式

交易输出中,各个字段含义如下:

字段 大小 描述
value 8个字节 支付金额(单位为聪)
scriptLen 1-9个字节 锁定脚本长度
scriptBytes 1-9个字节 锁定脚本数据

注:只有接收者,通过秘钥加密生成解锁脚本后,方可继续使用该输出作为输入,继续消费。

核心代码 - 变量定义
    // The output's value is kept as a native type in order to save class instances.
    //支付金额
    private long value;

    // A transaction output has a script used for authenticating that the redeemer is allowed to spend
    // this output.
    //锁定脚本
    private byte[] scriptBytes;
核心代码 - 数据解析
    //解析交易输出数据,包含输出金额和锁定脚本(接收者可以解锁该脚本)
    @Override
    protected void parse() throws ProtocolException {
        value = readInt64();                    //获取交易输出的金额
        scriptLen = (int) readVarInt();         //锁定脚本的长度
        length = cursor - offset + scriptLen;
        scriptBytes = readBytes(scriptLen);     //锁定脚本的内容
    }

上一篇:(二) 区块链数据结构-区块

下一篇:(四) 区块链数据结构 – 脚本

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(三) 区块链数据结构 – 交易 的相关文章

  • uniapp 自定义手机顶部状态栏不生效问题

    想要的效果想淘宝一样 底色覆盖到手机顶部 找了两天都没找到原因 过程很艰苦 直接上结果吧 项目是后来接手的 最终原因出在这 immersed false gt 设置为 true 就可以了 沉浸式样式

随机推荐

  • Linux 内核开发学习

    Linux 内核 Linux 内核官网 传送门 Linux 内核源码下载 传送门 1 内核空间 现在来说一下内核空间以及用户空间 这是学习linux内核最基本的两个概念了 如果连这都不懂 那就好好学吧 我们先从这张图入手 32位操作系统的最
  • 华为OD机试 - 增强的strstr(Python)

    题目描述 C 语言有一个库函数 char strstr const char haystack const char needle 实现在字符串 haystack 中查找第一次出现字符串 needle 的位置 如果未找到则返回 null 现
  • 锐星服务器怎么上传文件,协议转换器仪表远程配置方法专利_专利申请于2019-06-06_专利查询 - 天眼查...

    1 一种协议转换器仪表远程配置方法 其特征在于 包括以下步骤 步骤1 在平台端开发一个基于页面配置的配置程序 为指定的CAN仪表协议提供配置工具 输出配置文件 该配置文件是由版本信息 报文CAN ID配置语句 车载机使用数据项ID配置语句
  • 【干货】--手把手教你完成文本情感分类

    作者 刘顺祥 个人微信公众号 每天进步一点点2015 前言 2017年12月9日 参加了天善组织的线下沙龙活动 在沙龙中自己分享了如何借助于R语言完成情感分析的案例 考虑的其他网友没能够参与到活动现场 这里通过微信公众号作一个简单的分享 在
  • 【Angular中的HTTP请求】- JSONP 详解

    JSONP JSON with Padding 是JSON的一种 使用模式 可用于解决主流浏览器的跨域数据访问的问题 基于XMLHttpRequest的数据请求会受到同源策略限制 而 JSONP 以
  • 为什么离不开 Stackoverflow

    作为一名程序员 如果没有听过 Stackoverflow 那么你最好去面壁思过一下 程序员最需要阅读的一本编程书籍 其实编程书留下这本就够了 那些还没有读过这本书的程序员 是时候买一本了 如果还在犹豫 那么先看下这篇文章 看看为什么离不开
  • linux创建链接命令

    1 软链接 符号链接 1 软链接文件有类似于Windows的快捷方式 2 在符号连接中 文件实际上是一个文本文件 其中包含的有另一文件的位置信息 3 它只会在你选定的位置上生成一个文件的镜像 不会占用磁盘空间 linux创建链接软命令 具体
  • C语言调用C++函数

    前阵子被问及一个在C中如何调用C 函数的问题 当时简单回答是将函数用extern C 声明 当被问及如何将类内成员函数声明时 一时语塞 后来网上查了下 网上有一翻译C 之父的文章可以作为解答 遂拿来Mark一下 将 C 函数声明为 exte
  • JS 5种遍历对象的方式

    From https blog csdn net qq 53225741 article details 127073295 我根据阮老师的 ES6标准入门 学习并总结了七种遍历对象的方法 我会将分别介绍这七种方法并进行详细的区分 并将从属
  • Linux Ubuntu 能PING IP但不能PING主机域名的解决方法

    vi etc nsswitch conf hosts files dns networks files 改成 hosts files dns wins networks files 如果不一样的话 就在hosts 原来那行后面加个wins
  • Vue2转Vue3快速上手第一篇(共两篇)

    Vue3 v2 v3的学习成本不高 只要有v2基础 基本可以上手vue3 一 setup语法 setup中不能访问v2的配置比如data methods等 二 ref响应数据 使用ref可以创建一个对象 可以是基本类型 也可以是对象 例如
  • SpringBoot获取resources 目录下的文件的方式

    SpringBoot获取resources 目录下的文件的方式在Spring Boot项目中 读取resources目录下文件的方式是非常常见的操作 为了确保项目的稳定性和可靠性 我们需要采取一种高效的方法来获取这些文件 因此 在本文中 我
  • overloading与overriding的区别

    1 overloading 重载 1 方法重载是让类以一种统一的方式处理不同类型数据的手段 多个同名函数同时存在 具有不同参数个数 类型 重载是一个类中多态性的表现 2 java方法重载就是在同一个类中创建多个具有相同的方法名 但是参数类型
  • MAC M1安装VMware 安装windows11

    目录 前言 一 安装包列表 二 VMware安装Windows11过程 总结 前言 最近想着给自己的mac安装windows虚拟机 因为mac是m1芯片的 所以也是从网上找了很多资料 用PD安装了Windows11 在找资料的时候发现VM也
  • Hbuild X 下载以及插件安装

    1 下载 下载地址 https www dcloud io 2 进入Hbuilder 官方网站 3 下载HBuilder 点击下载按钮 Download for Windows 点击后会直接下载 也可以鼠标移动到 more 选择对应的版本点
  • VC使用ActiveX控件常见问题

    转自 http lingchuangsong blog 163 com blog static 126932322008631104133309 一方面 它表示将你联系到Microsoft Internet和业界的新技术的小型快速的可重用组
  • 大数据应用——Hadoop运行模式(本地运行)

    Hadoop运行模式包括 本地模式 伪分布式模式以及完全分布式模式 Hadoop官方网站 http hadoop apache org 4 1本地运行模式 4 1 1 官方Grep案例 1 创建在hadoop 2 7 1文件下面创建一个in
  • pycharm注释、查看函数用法快捷键

    单行或多行注释 选中代码 ctrl 查询函数用法 ctrl 鼠标左击函数名 便可以直接进入原文件查看此函数的定义 自动填充空格 ctrl alt L 将光标置于需要调整的代码行 或者选择一个区域 按下快捷键后 代码会自动填充空格 自动对齐代
  • matlab figure函数的用法

    https blog csdn net qq 30387863 article details 80301996
  • (三) 区块链数据结构 – 交易

    区块由交易组成 区块体中包含若干项交易数据 交易 交易主要包含两类数据 交易输入和交易输出 交易输入用来指明钱的来源 交易输出用来指明钱的去向 除了交易输入和交易输出外 交易中还包含版本号和锁定时间 交易数据的存储结构如下 交易对象中的各个