利用golang在python中对一个EthereumStorage的MerkleProof进行verify

这篇博客介绍了如何利用Golang编译成C共享库并与Python对接,实现对EthereumStorage的MerkleProof进行验证。重点在于解决不同语言间参数传递的问题,特别是内存管理的差异。文章提供了RLP编码的背景信息,并展示了C-GO导出函数的注释方法,以及Python端的简单实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

rlp仍然是上次写的rlp代码
我们利用下面的命令行创建c-shared dll与python对接.

go build -buildmode=c-shared -o verifyproof.dll .\verifyproof.go

注意cgo采用了magic comment的方法.所有需要export的函数需要在前面注释上:

//export yourfunctionname
func yourfunctionname ...

本次任务的难点是如何传[]string参数
显然如果在C语言中这是一个**char变量.
转化逻辑如下:

func stringPtrToStringSlice(stringPtr **C.char, slicelen C.size_t) []string {
   
   
    strslice := make([]string, 0, slicelen)
    var unblock unsafe.Pointer
    
    for idx := C.size_t(0); idx < slicelen; idx++ {
   
   
        unblock = unsafe.Pointer(uintptr(unsafe.Pointer(stringPtr)) + uintptr(idx * CHAR_P_SIZE))
        strslice = append(strslice, C.GoString(*((**C.char)(unblock))))
    }
    return strslice;
}

因为go的内存管理和C-DLL的内存管理独立,所以设计下面的方法控制eth-db.

var dbPacket = make([]*leveldb.DB, 0, 64)
var dbpi = 0

//export openDB
func openDB(dbpath *C.char) C.int {
   
   
    db, err := leveldb.OpenFile(C.GoString(dbpath), nil)
    if err != nil {
   
   
		fmt.Println("link error")
        fmt.Println(err)
        return C.int(0)
	}else {
   
   
        dbPacket = append(dbPacket, db)
        dbpi++
		return C.int(dbpi - 1);
	}
    
}


//export closeDB
func closeDB(dbpi C.int) {
   
   
    db := dbPacket[dbpi]
    db.Close();
}

剩下的逻辑与之前没有差异
简单地写出python内的实现代码:

from ctypes import *
from hexbytes import HexBytes

PROVER_PATH = "./scripts/verifyproof.dll"
EDB_PATH = "D:/Go Ethereum/data/geth/chaindata"
ENC = "utf-8"

StorageHash = b"0x11e91152ab237ceff29728c03999ef2debadd7db0fc45b280657c6f7cc4c1ffa"
StoragePath = ["f8918080a06d032ff808e3a2b585df339916901d7b7d04c5bd18a088607093d3178172b7ee8080808080a0071b011fdbd4ad7d1e6f9762be4d1a88dffde614a6bd399bf3b5bad8f41249b5808080a01b56cc0a5b9b1ce34e9a14e896ea000c830bd64387573d238cbe3fa24ddfa2c3a0f5c2efa606e3a5be341f22bf1d5c8f4bce679719870c097a24abb38aec0a4855808080", "f8518080808080a06f643b8fd2176a403e2ccfae43808c4543289e1082078e91d821d1c7886d6f51808080a03822ab26403807d175522401e184b20b5aa8c7fcd802f4793970a70e810f4ce980808080808080", "e2a0200decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56333"]

key = b"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563"
val = b"0x33"

GoInt8 = c_int8
GoInt16 = c_int16
GoInt32 = c_int32
GoInt64 = c_int64

GoUint8 = c_uint8
GoUint16 = c_uint16
GoUint32 = c_uint32
GoUint64 = c_uint64

GoInt = GoUint64
GoUInt = GoUint64

GoBytes = c_char_p
GoString = POINTER(c_char)
GoStringSlice = POINTER(GoString)

dbptr = GoInt32

funcs = CDLL(PROVER_PATH)

funcs.openDB.restype = dbptr
funcs.openDB.argtype = GoString

funcs.closeDB.argtype = dbptr

funcs.VerifyProof.restype = GoInt32
funcs.VerifyProof.argtypes = (dbptr, GoString, GoString, GoString, GoStringSlice, GoInt32)


class Prover:
    def __init__(self, path):
        self.ethdb = funcs
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值