如何使用库共享公共数据

2020-09-14 10:28 栏目:经验之谈 来源:网络整理 查看()

本文讨论了Solidity智能契约使用库来共享公共数据。

简介

在我们的文章“使用智能合同共享公共数据”中,我们描述了为什么以及如何使用智能合同可靠地共享公共数据。

然而,在实度智能契约之间共享公共数据的技术也适用于实度库。本文介绍了如何实现这一点,并比较了智能合同和图书馆解决方案的气体消耗。

Solidity v0.6.4和更高版本支持该方法。

示例模型

对于本文,我们假设我们正在构建一个与“共享公共数据的智能契约”相匹配的解决方案,也就是说,路由应该包含一个生产者,生产者会产生一些排队供消费者使用的对象。在本文中,我们并不真正关心附属图书馆的实际功能和使用。本文重点介绍了数据共享的常用方法。

下图说明了智能合同或库的代码和数据的位置:

如何使用库共享公共数据

智能合同/库的代码和数据位置

在这种情况下,路由必须是实智能契约,因为它为来自自身及其下属库的所有数据提供存储空间管理。

在这个例子中,生产者和消费者是实体库。它们的功能将始终在路由环境中执行。

特定于生产者和消费者的数据也必须保留在路由器环境中,因为不可能在生产者库或消费者库中分配存储的数据。

建议使用本文介绍的“存储私有契约数据的存储方法”来分配路由数据,以减少路由中添加任何从属智能契约时覆盖存储的风险。此方法适用于库和智能合同。

智能合同和库

智能合同和库:

生产者图书馆

消费者图书馆

路由器合同

排队数据库

排队数据位置协定

私人合同数据是:

生产者数据-在路由器合同中

消费者数据-在路由器合同中

路由器数据-在路由器合同中

共享公共数据是:

队列数据——在路由器契约中

生产者图书馆(生产者图书馆)

将他们的私有数据附加到路由环境,并将它们附加到他们自己的数据库。

图书馆制作人{

struct ProducerData {

uint计数;

{}

function product()public {

Producer data storage PDS=Producer data();

pds.count

QueueData storage QDs=QueueData();

QueueDataLib.append(qds,PDS . count);

{}

函数producerData()内部纯返回

(ProducerData存储pds) {

uint location=uint(keccak 256(' product . data . location '));

组件{ pds.slot :=location }

{}

函数queueData()内部纯返回

(队列数据存储qds) {

uint location=uint(keccak 256(' queue . data . location '));

组件{ qds.slot :=location }

{}

{}

producerData()函数提供了对生产者数据的引用,生产者数据只由库使用。

queueData()函数提供了对队列数据的引用,它将与路由协定和使用者库一起使用。

这些功能也可以根据开发人员的需要进行扩展或内联。不幸的是,这个库中必须提供queueData()函数,并且必须将相同的代码复制到消费者库中,因为Solidity库不能从公共基础协定或库继承。

消费者图书馆(消费者图书馆)

消费者契约非常类似于生产者库,生产者库包含从公共队列数据中删除项目的代码,并在路由契约的上下文中操作它们自己的私有数据。

图书馆消费者{

struct ConsumerData {

uint总计;

{}

function consume()public returns(uint count){

QueueData storage QDs=QueueData();

(bool success,uint item)=queuedatalib . remove(QDs);

if(成功){

consumer data storage CDs=consumer data();

cds.total=item

return cds.total

{}

{}

函数queueData()内部纯返回

(队列数据存储qds) {

uint location=uint(keccak 256(' queue . data . location '));

组件{ qds.slot :=location }

{}

函数consumerData()内部纯返回

(消费者数据存储光盘){

uint location=uint(keccak 256(' consumer . data . location '));

组件{ cds.slot :=location }

{}

{}

类似地,queueData()函数提供了对队列数据的引用,该引用将与路由协定和使用者库一起使用。确定数据位置的算法[在本例中为keccak 256(" queue . data . location ")]必须与生产者库中使用的算法相同,以便定位相同的数据。

ConsumerData()函数提供了对消费者数据的引用,该引用只由库使用。

路由合同(路由器合同)

路由协定包含将调用路由到生产者和消费者库的代码,它还可以操纵自己的私有协定数据。

合同路由器是CallLib {

构造函数(uint32 qSize) {

queuedatalib . create(Producer . queuedata(),qSize);

{}

function product()public {

callLib(地址(生产者));

{}

function consume()public returns(uint total){

(bool ok,字节内存bm)=callLib(地址(Consumer));

if (ok) {

return abi.decode(bm,(uint 256));

{}

{}

{}

生产者使用的queueData()函数可以在生产者和消费者库中使用。

提供公共函数produce()和consume()来执行此解决方案的实际操作。目标函数必须与路由器协定中的公共函数具有相同的函数签名(名称和参数),因为库是使用消息中提供的函数签名调用的。

调用存储库

callLib契约中提供的CallLib()函数类似于OpenZeppelin的文章“编码可伸缩智能契约”和“代理转发”中提供的备份函数。这是代码:

合同CallLib {

函数callLib(地址adrs)内部返回

(bool,字节内存){

程序集{

calldatacopy(0,0,calldatasize())

让结果:=delegatecall(gas(),adrs,0,

calldatasize(),0,0)

returndatacopy(0,0,returndatasize())

切换结果

案例0 {revert(0,returndatasize())}

默认{return (0,returndatasize())}

{}

{}

{}

队列数据和库

该库将被导入所有使用它的合同和库。从队列中移除项目,从队列中移除实例。编译器将确保在最终的字节码中只提供那些函数。

试验

这个简单、交互式、智能的合同部署者可以调用生产和消费者。

合同测试路由器是DcReporter {

路由器路由器;

constructor() {

uint queue SiZe=2;

Router=new Router(queueSize);

{}

function product()public {

router . product();

{}

function consume()public returns(uint total){

return router . consume();

{}

{}

燃气流量

构建了另一个智能合同,它包括继承的生产者和消费者合同,以方便天然气消费的比较。从属合同使用相同的分配存储方法。

合同组合是消费者,生产者{

构造函数(uint32 queueSize) {

queuedatalib . create(Producer . queuedata(),queueSize);

{}

function product()public {

producer . product();

{}

function consume()public returns(uint total){

return consumer . consume();

{}

{}

在最后一篇文章中,我们将这种智能合同与图书馆的用气量进行了比较。

智能合同部署

创建单个智能合同也会产生开销,因此我们可以预计部署所需的天然气量将大于智能合同和基于库的解决方案的总和。

如何使用库共享公共数据

结果是这样的。请注意,路线的库版本消耗的汽油要少得多。这是因为不需要创建单独的契约,部分原因是这些单独契约的数据引用不需要存储在Ethereum虚拟机的高空气消耗存储空间中。

典型的智能合同用法

智能合同和图书馆的公共功能Produce()和consume()的用气量是多少?

如何使用库共享公共数据

不出所料,这些项目的成本大体相似。

进一步的可能性

如“共享公共数据的智能契约”中所述,路由契约的生产()和消费()的公共函数使用callLib()来调用生产方和消费方的从属库函数:

如何使用库共享公共数据

如果只有一个下级合同或库,可以根据文章“编码可伸缩智能合同”使用路由合同的回退功能。但是,在本例中,因为目标函数位于不同的从属库中,所以不能使用路由协定的回退函数。

《EIP-2535:钻石标准》描述了路由如何存储类似于契约或库所支持的函数,因此通过回滚函数来调用代码的方法类似于以下内容:

如何使用库共享公共数据

结论

智能合同可以分为多个组件,出于多种原因,这些组件需要共享公共数据,并将私有数据定位在安全的地方。

我们已经展示了用简单的路线做到这一点是多么容易,但是有一些考虑。

这些组件中的每一个都可以是一个智能契约或库。智能合同在可靠性方面比图书馆更灵活,但在建造时会消耗更多的天然气。

微信二维码
售前客服二维码

文章均源于网络收集编辑侵删

提示:仅接受技术开发咨询!

郑重申明:资讯文章为网络收集整理,官方公告以外的资讯内容与本站无关!
NFT开发,NFT交易所开发,DAPP开发 Keywords: NFT开发 NFT交易所开发 DAPP开发