如何使用以太坊和serpen将“复杂”数据结构存储为持久数据结构

2024-09-30 10:31:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我的工作是关于Smart Contract开发,使用(py)ethereum和{a3}

读“A Programmer’s Guide to Ethereum and Serpent”时,我在第5.9点看到:

[...] Persistent data structures can be declared using the data declaration. This allows for the declaration of arrays and tuples. [...]

以及:

[...] For simple storage, self.storage[] is useful, but for larger contracts, we recommend the use of data (unless you need a key- value storage, of course) [...]

代码示例:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import serpent
from ethereum import tester, utils, abi

serpent_code = '''
data mystorage[]


def test_data_storage(key,value):
    if not self.mystorage[key]:
        self.mystorage[key]=value
        return(1)
    else:
        return(0)


def get_value_mystorage(key):
    if not self.mystorage[key]:
        return(0)
    else:
        return(self.mystorage[key])



def test_self_storage(key,value):
    if not self.storage[key]:
        self.storage[key]=value
        return(1)
    else:
        return(0)


def get_value_self_storage(key):
    if not self.storage[key]:
        return(0)
    else:
        return(self.storage[key])

'''


s = tester.state()
c = s.abi_contract(serpent_code)

#example with self storage
c.test_self_storage("keyA",1)
print c.get_value_self_storage("keyA") #store and access data works in self.storage!

#example with mystorage
c.test_data_storage("keyB",2)
print c.get_value_mystorage("keyB") #store and access data works in data as persistant data storage!

#fail example with complex data
my_complex_data={"keyA":1,"keyB":2, "keyC":[1,2,3], "keyD":{"a":1,"b":2}}
c.test_data_storage("keyComplex",my_complex_data) 

#don't store anything because error:
# ethereum.abi.ValueOutOfBounds: {'keyC': [1, 2, 3], 'keyB': 2, 'keyA': 1, 'keyD': {'a': 1, 'b': 2}}

我的问题是:什么是最好的方法,以及如何像字典一样存储复杂数据(代码中的查看My_complex_data变量),将其他dict(或数组作为键值)存储为持久数据结构?在

有人知道这是否可能,以及如何将任何类结构存储为持久数据结构吗?在


Tags: andkeytestselfdatagetreturnif
1条回答
网友
1楼 · 发布于 2024-09-30 10:31:17

重要:请注意,根据this Vitalik TweetSerpent现在是一种“过时的技术”。在

毒蛇README已更新为:

Being a low-level language, Serpent is NOT RECOMMENDED for building applications unless you really really know what you're doing. The creator recommends Solidity as a default choice, LLL if you want close-to-the-metal optimizations, or Vyper if you like its features though it is still experimental.

如果您想从Python编写以太坊契约来发布产品,那么就开始考虑迁移到Solidity或{a4}(这仍然是一种“新的实验性编程语言”)


关于我的问题,我最终找到了一个(棘手的/肮脏的)解决方案,即在将复杂数据推送到持久数据存储之前对其进行编码,然后在从存储中检索数据后进行解码。在

请参阅以下更新代码:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import serpent
import json,math
from ethereum import tester, utils, abi

serpent_code = '''
data mystorage[]


def test_data_storage(key,value):
    if not self.mystorage[key]:
        self.mystorage[key]=value
        return(1)
    else:
        return(0)


def get_value_mystorage(key):
    if not self.mystorage[key]:
        return(0)
    else:
        return(self.mystorage[key])



def test_self_storage(key,value):
    if not self.storage[key]:
        self.storage[key]=value
        return(1)
    else:
        return(0)



def rebuild_complex_data_storage(key):
    if not self.storage[key]:
        return(0)

def get_value_self_storage(key):
    if not self.storage[key]:
        return(0)
    else:
        return(self.storage[key])


def put_complex_data_storage(key,value=""):
    self.storage[key]=value


def get_complex_data_storage(key):
    return(self.storage[key])



'''


s = tester.state()
c = s.abi_contract(serpent_code)

#example with self storage
c.test_self_storage("keyA",1)
print c.get_value_self_storage("keyA") #store and access data works in self.storage!

#example with mystorage
c.test_data_storage("keyB",2)
print c.get_value_mystorage("keyB") #store and access data works in data as persistant data storage!

start_block="99699"

def block_chain_encode(c,key,my_complex_data):

    #ENCODE PART

    global start_block

    print "\n","*","ENCODE","*"

    #fail example with complex data
    my_complex_data_json_format=unicode(json.dumps(my_complex_data))

    int_str=start_block
    for each in my_complex_data_json_format:
        int_str=int_str+ str(ord(each)).zfill(4)
    int_str=int_str+start_block
    print int_str
    #toHex = lambda x:"".join([hex(ord(c))[2:].zfill(2) for c in x])
    print "need to declare 32 bit words", math.ceil(len(int_str)/32.),"times"
    #max 32 char for each key

    max_size=int(math.ceil(len(int_str)/32.))
    for i in range(0,max_size):
        block_content=int_str[i*32:(i+1)*32]
        print "block",i," content",block_content
        if i==0:
            c.test_data_storage("keyComplex_len",max_size)

        key="keyComplex_"+str(i).zfill(3)
        res=c.test_data_storage(key,int(block_content)) #store block part in block chain
        print " - substorage",key,"",

    #print "data storage part is done !"
    return 1

def block_chain_decode(c,key):

    #DECODE PART

    global start_block
    print "\n","*","DECODE","*"


    int_str=""
    lenght= c.get_value_mystorage("keyComplex_len") #get lenght to know how many block we need to get for all data from block chain
    for i in range(0,lenght):
        key="keyComplex_"+str(i).zfill(3)
        print key,c.get_value_mystorage(key)
        int_str=int_str+str(c.get_value_mystorage(key))

    content_=""
    sp_int_str= int_str.split(start_block)
    if len(sp_int_str)==3:
        if sp_int_str[-1]==sp_int_str[0] and sp_int_str[0]=="":
            print "ok"
            content_=sp_int_str[1]

    js_str=""
    if content_!="":
        for i in range(0,int(len(content_)/4.)):
            js_str+=chr(int(content_[i*4:(i+1)*4])) #recover char from asci code
    my_complex_data=json.loads(js_str)

    return my_complex_data

#define complex data
my_complex_data={"keyA":1,"keyB":2, "keyC":[1,2,3], "keyD":{"a":1,"b":2}}
print "Initial complex data",my_complex_data

#encode and push to block chain
block_chain_encode(c,"keyComplex",my_complex_data)

#get complex variable from block chain
my_complex_data_back = block_chain_decode(c,"keyComplex")
#acces data
print my_complex_data_back["keyD"]["a"]+my_complex_data_back["keyD"]["b"]
print "Extracted complex data from blockchain",my_complex_data
print "Integrity test pass:",my_complex_data_back==my_complex_data

哪个返回:

^{pr2}$

相关问题 更多 >

    热门问题