IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 区块链 -> 比特币源码分析 脚本(二) -> 正文阅读

[区块链]比特币源码分析 脚本(二)

代码分析

script.h中,存放着类CScript的成员函数,其中最关键的是函数GetOp

bool GetOp(const_iterator& pc, opcodetype& opcodeRet, vector<unsigned char>& vchRet) const

GetOp的参数包括程序计数器PC、操作码OPCode及立即数返回值。该函数的作用是从脚本PC处读出操作码,调整PC指向下一个操作码;若当前读取的操作码为立即数操作码,则也一并读出立即数。

script.cpp中,存放着与脚本密切相关的函数,其中最基础、最关键的是函数EvalScript

bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType,
                vector<vector<unsigned char> >* pvStackRet)

EvalScript的参数包括待执行的程序(待执行的脚本),运行的环境(待填充的交易交易输入的索引等)以及运行的结果

EvalScript主要局部变量及解析如下:

CScript::const_iterator pc = script.begin();				//程序计数器,用于指向下一个执行的指令
CScript::const_iterator pend = script.end();				//用于判断程序结束
CScript::const_iterator pbegincodehash = script.begin();	//与操作码OP_CODESEPARATOR一起用于辅助定位待签名脚本
vector<bool> vfExec;										//条件判断结果
vector<valtype> stack;										//主运行栈,用于运行时存放中间数值
vector<valtype> altstack;									//次栈,未找到具体用法

EvalScript主要逻辑是从待执行脚本中取出操作码并执行,直至取完、执行过程中遇到OP_RETURN、执行过程中VERIFY类验证失败、执行过程中遇到错误(例如操作数不足等)才会结束执行。
各类操作码大致行为如下表:

类型操作
立即数往主栈压入立即数
流程控制对操作数进行条件判断;根据条件判断结果控制指令解析执行;对条件判断结果进行操作
栈操作对栈顶某些元素进行复制、反转、交换等操作
切片运算对栈顶某些元素进行拼接、位移等操作
位运算对栈顶某些元素进行位运算
数值运算对栈顶某些元素进行数值运算
加密运算对栈顶某些元素进行计算哈希值、验签等密码学运算
边界符
模板
非法字节码

其中,边界符、模板、非法字节码三类操作码并无实际的执行代码(即这三类操作码在输入到脚本执行前已被预处理)。

所有指令中,较难理解的是OP_CHECKSIGVERIFYOP_CHECKMULTISIGVERIFY可看作升级版OP_CHECKSIGVERIFY

case OP_CHECKSIGVERIFY:
{
    // (sig pubkey -- bool)
    // OP_CHECKSIGVERIFY输入参数为sig及pubkey,输出结果bool
    if (stack.size() < 2)
        return false;

    valtype& vchSig    = stacktop(-2);
    valtype& vchPubKey = stacktop(-1);

    // debug print
    //PrintHex(vchSig.begin(), vchSig.end(), "sig: %s\n");
    //PrintHex(vchPubKey.begin(), vchPubKey.end(), "pubkey: %s\n");

    // Subset of script starting at the most recent codeseparator
    // 从最近的分隔符OP_CODESEPARATOR一直到结束的脚本需要进行验签
    CScript scriptCode(pbegincodehash, pend);

    // Drop the signature, since there's no way for a signature to sign itself
    // 去掉签名
    scriptCode.FindAndDelete(CScript(vchSig));

	// 跟进 CheckSig -> SignatureHash,最终在SignatureHash中,将scriptCode填充到txTo的vin[nIn]中的scriptSig,
	// 序列化后在进行计算哈希值,并对该哈希值进行验签
    bool fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType);

    stack.pop_back();
    stack.pop_back();
    stack.push_back(fSuccess ? vchTrue : vchFalse);
    if (opcode == OP_CHECKSIGVERIFY)
    {
        if (fSuccess)
            stack.pop_back();
        else
        	// 验签失败直接返回
            pc = pend;
    }
}
break;
  区块链 最新文章
盘点具备盈利潜力的几大加密板块,以及潜在
阅读笔记|让区块空间成为商品,打造Web3云
区块链1.0-比特币的数据结构
Team Finance被黑分析|黑客自建Token“瞒天
区块链≠绿色?波卡或成 Web3“生态环保”标
期货从入门到高深之手动交易系列D1课
以太坊基础---区块验证
进入以太坊合并的五个数字
经典同态加密算法Paillier解读 - 原理、实现
IPFS/Filecoin学习知识科普(四)
上一篇文章      下一篇文章      查看所有文章
加:2021-10-09 16:20:06  更:2021-10-09 16:20:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:22:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码