Hello World - 2022年1月
type: channel
link: https://wlwl.host/index.php/2022/01/
description: Just So So ...
items: 集成Swagger到Gin项目
items: solidity 指令修改
items: Go语言实现solidity部分接口

集成Swagger到Gin项目
type: item
date: 2022-01-17T14:30:00+00:00
description: 简介Swagger本质上是一种用于描述使用JSON表示的RESTful API的接口描述语言。Swagger与一组开源软件工具一起使用，以设计、构建、记录和使用RESTful Web服务。Swagger包括自动文档，代码生成和测试用例生成。在前后端分离的项目开发过程中，如果后端能够提供一份清晰明了的接口文档，那么就能极大地提高大家的沟通效率和开发效率。可是编写接口文档历来都是令人头痛的，而且后续接口文档的维护也十分耗费精力。最好是有一种方案能够既满足我们输出文档的需要又能随代码的变更自动更新，而Swagger正是那种能帮我们解决接口文档问题的工具。集成想要使用gin-swagger为代码自动生成接口文档，一般需要下面三个步骤：按照swagger要求给接口代码添加声明式注释，具体参照声明式注释格式。使用swag工具扫描代码自动生成API接口文档数据使用gin-swagger渲染在线接口文档页面第一步：添加注释在程序入口main函数上以注释的方式写下项目相关介绍信息。package main // @title 这里写标题 // @version 1.0 // @description 这里写描述信息 func main() { r := gin.New() r.Run() }在你代码中处理请求的接口函数（通常位于controller层）按如下方式写上注释：// GetPostListHandler2 升级版帖子列表接口 // @Summary 升级版帖子列表接口 // @Description 可按社区按时间或分数排序查询帖子列表接口 // @Tags 帖子相关接口 // @Accept application/json // @Produce application/json // @Param Authorization header string false "Bearer 用户令牌" // @Param object query models.ParamPostList false "查询参数" // @Security ApiKeyAuth // @Success 200 {object} _ResponsePostList // @Router /posts2 [get] func GetPostListHandler2(c *gin.Context) { p := &models.ParamPostList{ Page: 1, Size: 10, Order: models.OrderTime, } ... }上面注释中参数类型使用了object，models.ParamPostList具体定义如下：// bluebell/models/params.go // ParamPostList 获取帖子列表query string参数 type ParamPostList struct { CommunityID int64 `json:"community_id" form:"community_id"` // 可以为空 Page int64 `json:"page" form:"page" example:"1"` // 页码 Size int64 `json:"size" form:"size" example:"10"` // 每页数据量 Order string `json:"order" form:"order" example:"score"` // 排序依据 }响应数据类型也使用的object，在controller层专门定义一个docs_models.go文件来存储文档中使用的响应数据model。// bluebell/controller/docs_models.go // _ResponsePostList 帖子列表接口响应数据 type _ResponsePostList struct { Code ResCode `json:"code"` // 业务响应状态码 Message string `json:"message"` // 提示信息 Data []*models.ApiPostDetail `json:"data"` // 数据 }第二步：生成接口文档数据编写完注释后，使用以下命令安装swag工具：go get -u github.com/swaggo/swag/cmd/swag # 1.16 及以上版本 go install github.com/swaggo/swag/cmd/swag@latest在项目根目录执行以下命令，使用swag工具生成接口文档数据。swag init执行完上述命令后，如果你写的注释格式没问题，此时你的项目根目录下会多出一个docs文件夹。./docs ├─…

solidity 指令修改
type: item
date: 2022-01-16T08:19:00+00:00
description: solidity编译后的字节码运行在以太坊虚拟机EVM中，指令修改需要同时修改编译器和虚拟机关键文件Solidity编译器项目地址：https://github.com/ethereum/solidity.gitToken的定义：solidity/liblangutil/Token.h；词法定义，比如 token{Add,+}，将+与Add对应起来Instruction的定义：solidity/libevmasm/Instruction.h；虚拟机执行的指令,需要在EVM里实现Type的定义：solidity/libsolidity/ast/Types.h；数据类型定义，包括魔术变量（block，msg...）的定义TypeProvider的定义：solidity/libsolidity/ast/TypeProvider.h；所有数据类型声明Semantic的定义：solidity/libevmasm/SemanticInformation.h;语义信息定义，主要是指令对函数pure,view，payable属性的影响ExpressionCompiler的定义：solidity/libsolidity/codegen/ExpressionCompiler.cpp；将AST语法树翻译成指令以太坊区块链项目地址：https://github.com/ethereum/go-ethereum.gitEVM字节码定义：go-ethereum/core/vm/opcodes.goEVM字节码属性定义：go-ethereum/core/vm/jump_table.go，将字节码和具体的操作绑定起来EVM指令操作定义：go-ethereum/core/vm/instructions.go添加RANDOM指令编译器添加和block.number一样的block.random语法，虚拟机支持和NUMBER一样操作的RANDOM指令编译器修改1.指令定义，代码位置libevmasm/Instruction.h。在enum calss Instruction中找到block的相关属性，并在其后追加RANDOM指令，注意添加的指令不能与其他的冲突。/// Virtual machine bytecode instruction. enum class Instruction: uint8_t { ...... BLOCKHASH = 0x40, ///< get hash of most recent complete block COINBASE, ///< get the block's coinbase address TIMESTAMP, ///< get the block's timestamp NUMBER, ///< get the block's number DIFFICULTY, ///< get the block's difficulty GASLIMIT, ///< get the block's gas limit CHAINID, ///< get the config's chainid param SELFBALANCE, ///< get balance of the current account BASEFEE, ///< get the block's basefee RANDOM, ...... }上述定义为16进制，同时也需要有一个字符串的"RANDOM"与指令对应，代码位置libevmasm/Instruction.cpp中。std::map<std::string, Instruction> const solidity::evmasm::c_instructions = { ...... { "DIFFICULTY", Instruction::DIFFICULTY }, { "GASLIMIT", Instruction::GASLIMIT }, { "CHAINID", Instruction::CHAINID }, { "SELFBALANCE", Instruction::SELFBALANCE }, { "BASEFEE", Instruction::BASEFEE }, { "RANDOM", Instruction::RANDOM }, ...... } static std::map<Instruction, InstructionInfo> const c_instructionInfo = { ...... { Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1, false, Tier::Base } }, { Instructi…

Go语言实现solidity部分接口
type: item
date: 2022-01-02T08:17:00+00:00
description: 打包数据abi.encode打包数据时每个变量都补齐到32字节大小，比如说address类型的变量，需要在前面补12个0字节来凑齐32字节，而abi.encodePacked接口不需要，直接根据变量所占字节大小按顺序拼接成字节数组即可。solidity语言： function abiEncode() public pure returns (bytes memory) { address a = 0x1000000000000000000000000000007000006000; bytes32 b = "hello" ; return abi.encode(a, b); } function abiEncodePacked() public pure returns (bytes memory) { address a = 0x1000000000000000000000000000007000006000; bytes32 b = "hello" ; return abi.encodePacked(a, b); }go语言：import ( "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ) func abiEncode() { addressTy, _ := abi.NewType("address", "", nil) bytes32Ty, _ := abi.NewType("bytes32", "", nil) arguments := abi.Arguments{ { Type: addressTy, }, { Type: bytes32Ty, }, } bytes, _ := arguments.Pack( common.HexToAddress("0x1000000000000000000000000000007000006000"), [32]byte{'h', 'e', 'l', 'l', 'o'}, ) fmt.Println(hexutil.Encode(bytes)) } func abiEncodePacked() { bytes = append( common.HexToAddress("0x1000000000000000000000000000007000006000").Bytes(), common.RightPadBytes([]byte{'h', 'e', 'l', 'l', 'o'}, 32)..., ) fmt.Println(hexutil.Encode(bytes)) }输出：0x000000000000000000000000100000000000000000000000000000700000600068656c6c6f000000000000000000000000000000000000000000000000000000 0x100000000000000000000000000000700000600068656c6c6f000000000000000000000000000000000000000000000000000000哈希数据：solidity使用keccak256接口将字节数组来生成32字节的哈希，部分前端js库在签名或哈希时自动在数据前加特殊的前缀，为了使solidity计算带前缀的哈希方便，将数据编码并哈希成32字节后再加前缀来计算哈希（这时前缀固定为\x19Ethereum Signed Message:\n32）solidity语言： function hash() public pure returns (bytes32) { address a = 0x1000000000000000000000000000007000006000; bytes32 b = "hello" ; return keccak256(abi.encodePacked(a,b)); } function prefixedHash() public pure returns (bytes32) { address a = 0x1000000000000000000000000000007000006000; bytes32 b = 'hello'; return keccak256(abi.encodePacked('\x19Ethereum Signed Message:\n32', keccak256(abi.encodeP…