Blockchain

自己实现 Etherscan 合约认证功能

2018-12-19  本文已影响0人  __飘__

最近要实现Etherscan的合约认证的功能 类似这个这个页面
大概实现思路是这样

解决的问题
1. bytecode尾部与链上的bytecode不同

bytecode尾部是一个部署合约元数据的Hash称为 AUXDATA ,不同环境下编译会产生不同的hash(即使使用相同版本编译器),在校对时候需要移除尾部的32字节Hash值

2.bytecode首部与链上的bytecode不同

在编译完成后bytecode首部的一段代码称为部署代码,这一部分在部署完成后通过eth_getCode 是无法获取到的,所以在比对时需要将它移除出去,那么怎么确定哪一部分是属于部署代码的呢?
经过观察发现,部署代码的最后一个指令都会以STOP结尾(不一定正确),在编译合约时同时生成opcodes,编译完成后将opcodes读取进入,截取出opcodes第一个STOP指令前所有的指令,计算出这些指令对应的bytecode,然后将其移除出去,由此又衍生出关于opcodes转bytecode的第三个问题

3.opcdoes转bytecode的问题
  • 指令转换问题
    发现通过opcodes计算的bytecode有时候对有时候不对,问题出现在PUSH指令上,PUSH1 到PUSH32 分别表示操作1到32个字节的数据,那么后面的数据如果不满足PUSH指令的数据长度,需要在高位补充0
  • 源代码指令不够问题
    由于部署代码部分需要自己进行计算,所以需要收集所有的opcodes,以太坊源码 中指定的opcodes在实际使用过程中发现并不完整,经过核对有INVALID,KECCAK256 操作码并没有在该源码文件中,手动录入
  • 库合约字节码被替换问题
    库合约部署完成后,bytecode开头(已经去除了部署代码)使用了PUSH20指令后面紧随合约地址,编译器刚编译完成后当然是不知道合约地址的所以PUSH20指令后面跟随的是空值也就是 0000000000000000000000000000000000000000,检测到后需要替换为真实合约地址

参考文档
https://www.jianshu.com/p/1969f3761208

solidity历史版本下载 nightly版本不知道在哪儿下载,有知道还望的告知一下

附所有opcodes
{
    "STOP": "00",
    "ADD": "01",
    "MUL": "02",
    "SUB": "03",
    "DIV": "04",
    "SDIV": "05",
    "MOD": "06",
    "SMOD": "07",
    "ADDMOD": "08",
    "MULMOD": "09",
    "EXP": "0a",
    "SIGNEXTEND": "0b",
    "LT": "10",
    "GT": "11",
    "SLT": "12",
    "SGT": "13",
    "EQ": "14",
    "ISZERO": "15",
    "AND": "16",
    "OR": "17",
    "XOR": "18",
    "NOT": "19",
    "BYTE": "1a",
    "SHA3": "20",
    "ADDRESS": "30",
    "BALANCE": "31",
    "ORIGIN": "32",
    "CALLER": "33",
    "CALLVALUE": "34",
    "CALLDATALOAD": "35",
    "CALLDATASIZE": "36",
    "CALLDATACOPY": "37",
    "CODESIZE": "38",
    "CODECOPY": "39",
    "GASPRICE": "3a",
    "EXTCODESIZE": "3b",
    "EXTCODECOPY": "3c",
    "BLOCKHASH": "40",
    "COINBASE": "41",
    "TIMESTAMP": "42",
    "NUMBER": "43",
    "DIFFICULTY": "44",
    "GASLIMIT": "45",
    "POP": "50",
    "MLOAD": "51",
    "MSTORE": "52",
    "MSTORE8": "53",
    "SLOAD": "54",
    "SSTORE": "55",
    "JUMP": "56",
    "JUMPI": "57",
    "PC": "58",
    "MSIZE": "59",
    "GAS": "5a",
    "JUMPDEST": "5b",
    "PUSH1": "60",
    "PUSH2": "61",
    "PUSH3": "62",
    "PUSH4": "63",
    "PUSH5": "64",
    "PUSH6": "65",
    "PUSH7": "66",
    "PUSH8": "67",
    "PUSH9": "68",
    "PUSH10": "69",
    "PUSH11": "6a",
    "PUSH12": "6b",
    "PUSH13": "6c",
    "PUSH14": "6d",
    "PUSH15": "6e",
    "PUSH16": "6f",
    "PUSH17": "70",
    "PUSH18": "71",
    "PUSH19": "72",
    "PUSH20": "73",
    "PUSH21": "74",
    "PUSH22": "75",
    "PUSH23": "76",
    "PUSH24": "77",
    "PUSH25": "78",
    "PUSH26": "79",
    "PUSH27": "7a",
    "PUSH28": "7b",
    "PUSH29": "7c",
    "PUSH30": "7d",
    "PUSH31": "7e",
    "PUSH32": "7f",
    "DUP1": "80",
    "DUP2": "81",
    "DUP3": "82",
    "DUP4": "83",
    "DUP5": "84",
    "DUP6": "85",
    "DUP7": "86",
    "DUP8": "87",
    "DUP9": "88",
    "DUP10": "89",
    "DUP11": "8a",
    "DUP12": "8b",
    "DUP13": "8c",
    "DUP14": "8d",
    "DUP15": "8e",
    "DUP16": "8f",
    "SWAP1": "90",
    "SWAP2": "91",
    "SWAP3": "92",
    "SWAP4": "93",
    "SWAP5": "94",
    "SWAP6": "95",
    "SWAP7": "96",
    "SWAP8": "97",
    "SWAP9": "98",
    "SWAP10": "99",
    "SWAP11": "9a",
    "SWAP12": "9b",
    "SWAP13": "9c",
    "SWAP14": "9d",
    "SWAP15": "9e",
    "SWAP16": "9f",
    "LOG0": "a0",
    "LOG1": "a1",
    "LOG2": "a2",
    "LOG3": "a3",
    "LOG4": "a4",
    "PUSH": "b0",
    "DUP": "b1",
    "SWAP": "b2",
    "CREATE": "f0",
    "CALL": "f1",
    "CALLCODE": "f2",
    "RETURN": "f3",
    "DELEGATECALL": "f4",
    "SELFDESTRUCT": "ff",
    "REVERT": "fd",
    "INVALID": "fe",
    "KECCAK256": "20",
    "SHL": "1b",
    "SHR": "1c",
    "SAR": "1d",
    "RETURNDATASIZE": "3d",
    "RETURNDATACOPY": "3e",
    "EXTCODEHASH": "3f",
    "CREATE2": "f5",
    "STATICCALL": "fa"
}
上一篇下一篇

猜你喜欢

热点阅读