-

如安在区块链上完成去中间化数据仓库同享

来源: 数字货币 时间:2020-07-30 16:09:33
导读: 如何在区块链上实现去中心化数据仓库共享来源于陀螺财经专栏作家区块链研究实验室,内容简述:背景Alice和Bob已经在他们选择的数据仓库中共享数据,而


新手学习要有系统性

新手学习要有系统性来源于陀螺财经专栏作家X平行线,内容简述:近期有很多朋友反映,想要深入学习区块链,但又不知道从哪里入手

背景

Alice和Bob已在他们挑选的数据仓库中同享数据,而智能接见掌握着用户接见,这些接见都经由过程互联网链接在一起。

我们前面的例子形貌了一种解决方案,经由过程该解决方案,智能合约运用户能够将包含国际象棋棋子的文件附加到文件夹中。

在那个例子中,Alice是第一个出棋的人,在本例中,能够改成Bob是第一个出棋的人。而且他们大概会玩不止一种游戏。要完成这一点,须要修正智能合约,即建立一个新合约。

然则由于数据仓库的合约不能变动,因而建立新的智能合约也须要新的数据仓库。

这也大概意味着将旧的数据仓库挪动(复制和删除)到新的数据仓库,并变动对掌握智能合约的任何援用。

Alice和Bob愿望能够升级掌握其数据仓库的智能合约,而没必要挪动数据仓库并更新对新智能合约的任何其他援用。

这意味着坚持雷同的数据仓库,也要坚持雷同的智能合约。

可升级数据同享示例

在这个例子中,我们引见了一个可升级的智能合约和一个路由器智能合约。

关于我们的特定示例,由于智能合约中的功用将由数据仓库挪用,因而,智能合约必需相符datona-lib形貌并指定为假造函数的智能数据接见合约(SDAC)接口范例,这一点很主要。在SDACinterface基础智能合约中。

因而,我们不须要通用的可升级智能合约,而是须要一个路由器智能合约和一个可升级的SDAC。

经由过程路由器接见的可升级智能合约(掌握)

而且,我们挑选仅大概的可升级SDAC:那些具有合约一切者和两个帐户用户的sdac。明显另有很多其他的大概性,比方一个合约一切者和一个其他帐户用户,或很多个帐户用户等等。

末了由于上述参考文献中的正告,我们还挑选防止在新的智能合约中重复运用之前的智能合约的数据。在大概的情况下,我们将数据存储定位在链外,由于在链上存储数据的本钱很高。

路由器“升级”到一个全新的智能合约,包含代码和数据

这意味着我们必需运用完成SDAC接口的路由器智能合约和可升级智能合约的要领,该要领挪用支撑两个用户的可升级SDAC。

建立可升级智能合约

下面是一个笼统的DuoSDAC,它将用于我们的示例可升级智能合约,它支撑一个合约一切者和两个用户:

DuoSDACimport"SDACinterface.sol";abstractcontractDuoSDACisSDACinterface{addresspublicowner=msg.sender;addresspublicaccount1;addresspublicaccount2;constructor(address_account1,address_account2)public{account1=_account1;account2=_account2;}}

必需将其声明为笼统智能合约,由于它不供应SDACinterface中指定的假造函数的完成。

我们能够重写之前的数据同享智能合约,然后跳入时间机器并紧缩几周,如许我们就能够布置这些智能合约,而不是原本的智能合约。

以下是同享去中间化数据的示例解决方案,它简化了变量和组织函数(如今在DuoSDAC中),但在其他方面没有变化:

DataShareSDACimport"DuoSDAC.sol";contractDataShareSDACisDuoSDAC{boolterminated;constructor(address_account1,address_account2)publicDuoSDAC(_account1,_account2){}...

在上一篇文章中,我们已已对其举行了变动,以方便运用多个游戏文件夹,但在其他方面坚持稳定:

ChessDataShareSDACimport"DataShareSDAC.sol";contractChessDataShareSDACisDataShareSDAC{uintgameFolder=3;...functiongetPermissions(addressaccount,uintobject)publicviewoverridevirtualreturns(uint){if(!terminated){if(object==gameFolder){...

这是本文的示例解决方案,它能够指定第一回合的用户,并由回合的用户入手下手新的游戏,从而有效地妥协了当前游戏:

StartChessDataShareSDACimport"ChessDataShareSDAC.sol";contractStartChessDataShareSDACisChessDataShareSDAC{constructor(address_account1,address_account2,bool_turn2)publicChessDataShareSDAC(_account1,_account2){turn2=_turn2;}functionnewGame(uint_gameFolder)public{require(msg.sender==(turn2?account2:account1));require(gameFolder<_gameFolder);gameFolder=_gameFolder;}}

建立路由器智能合约

我们如今已编写了几个相符DuoSDAC接口的可升级智能合约(上面的DataShareSDAC、ChessDataShareSDAC、StartChessDataShareSDAC)。

我们将布置一个可升级智能合约,然后升级到另一个可升级智能合约。

我们将运用路由器智能合约挪用可升级的智能合约。由于路由器智能合约中的功用将由数据仓库挪用,因而它必需相符datona-lib形貌的智能数据接见合约(SDAC)接口范例。这些功用鄙人面的智能合约中被标识为数据仓库接口。

升级战略取决于智能合约作者决议升级权限的位置。在很多可升级的智能合约中,它由智能合约一切者负担(比方,请参阅开放Zeppelin升级)。

在我们的案例中,由于升级后的智能合约会影响两个用户同享的数据(趁便说一句,合约一切者实际上并不可见),因而我们决议,智能合约一切者和两个用户必需赞同升级后的智能合约,然后才强制执行。

我们将鄙人面的acceptUpgrade函数中强制执行该操纵。如前所述,将经由过程将一个可升级的智能合约替换为另一个可升级的智能合约来升级完全的合约(代码和数据)。

下面是一个路由器智能合约的示例,它相符我们想要的数据仓库存储接口和升级战略:

DuoSDACrouterimport"DuoSDAC.sol";contractDuoSDACrouterisSDAC{DuoSDACduoSDAC;constructor(DuoSDAC_duoSDAC)public{duoSDAC=_duoSDAC;}//----------datavaultinterface----------functionhasExpired()publicoverrideviewvirtualreturns(bool){returnduoSDAC.hasExpired();}functionterminate()publicoverridevirtual{duoSDAC.terminate();}functiongetPermissions(addressaccount,uintobject)publicoverrideviewvirtualreturns(uint){returnduoSDAC.getPermissions(account,object);}//----------upgradepolicy----------eventnewContract(addressindexed_from,addressindexed_to,bytes32_value);eventupdated(addressindexed_from,addressindexed_to,bytes32_value);DuoSDACnewDuoSDAC;uint8votes;functionagreeUpgrade(DuoSDAC_duoSDAC)publicreturns(bool){uint8vote;//(1)if(msg.sender==duoSDAC.owner())vote|=1;if(msg.sender==duoSDAC.account1())vote|=2;if(msg.sender==duoSDAC.account2())vote|=4;require(vote!=0,"Unknownaccount");//(2)if(newDuoSDAC!=_duoSDAC){newDuoSDAC=_duoSDAC;votes=vote;emitnewContract(msg.sender,address(newDuoSDAC),"newcontract");}else{votes|=vote;//(3)if(votes==(1+2+4)){terminate();duoSDAC=newDuoSDAC;votes=0;emitupdated(msg.sender,address(newDuoSDAC),"contractagreedandupdated");returntrue;}}}}

在我们之前的文章中已形貌过数据仓库接口函数。这里,我们集合议论路由器的函数。

我们引入了一个必需由智能合约一切者和两个用户以任何顺序挪用的函数acceptUpgrade。必需供应新的智能合约作为参数。

(1)以后的行确保为每一个参与者的投票设置唯一的位。

(2)以后的搜检可确保每当有人尝试升级到潜伏的新合约时,将消灭表决集并发出事宜。

(3)以后的搜检确保了一切3个参与者都赞同统一个新的智能合约时,旧的智能合约停止,设置了新的智能合约,发出了一个事宜而且函数返回true。

合约测试

为了测试解决方案合约,我们能够将其布置在区块链上-一个测试网就能够了。然则任何DuoSDAC智能合约组织函数都须要2个参数,即两个用户帐户。

为了辅佐自动化测试,我们能够建立代办用户智能合约来代表两个用户的帐户。这是ProxyUser智能合约的定义:

ProxyUserimport"DuoSDACrouter.sol";contractProxyUser{functionagreeUpdate(DuoSDACrouterduoSDACrouter,DuoSDACduoSDAC)publicreturns(bool){returnduoSDACrouter.agreeUpgrade(duoSDAC);}}

测试合约自身会建立代办用户智能合约,然后建立路由器智能合约,并供应一些测试功用:

TestSDACrouterimport"DuoSDACrouter.sol";contractTestSDACrouter{ProxyUseruser1=newProxyUser();ProxyUseruser2=newProxyUser();DuoSDACrouterduoSDACrouter=newDuoSDACrouter();functiont1createRouter()public{DataShareSDACdsSDAC=newDataShareSDAC(address(user1),address(user2));duoSDACrouter=newDuoSDACrouter(dataShareSDAC);}functiont2changeToDataShare()public{DataShareSDACdsSDAC=newDataShareSDAC(address(user1),address(user2));require(!duoSDACrouter.agreeUpgrade(dsSDAC));require(!user1.agreeUpdate(duoSDACrouter,dsSDAC));require(user2.agreeUpdate(duoSDACrouter,dsSDAC));}functiont3changeToChess()public{ChessDataShareSDACcdsSDAC=newChessDataShareSDAC(address(user1),address(user2));require(!duoSDACrouter.agreeUpgrade(cdsSDAC));require(!user1.agreeUpdate(duoSDACrouter,cdsSDAC));require(user2.agreeUpdate(duoSDACrouter,cdsSDAC));}functiont4changeToStartChess()public{StartChessDataShareSDACscdsSDAC=newStartChessDataShareSDAC(address(user1),address(user2),true);require(!user2.agreeUpdate(duoSDACrouter,scdsSDAC));require(!user1.agreeUpdate(duoSDACrouter,scdsSDAC));require(duoSDACrouter.agreeUpgrade(scdsSDAC));}functiont5changeBack()public{DataShareSDACdsSDAC=newDataShareSDAC(address(user1),address(user2));require(!user2.agreeUpdate(duoSDACrouter,dsSDAC));//resetvotesChessDataShareSDACcdsSDAC=newChessDataShareSDAC(address(user1),address(user2));require(!user1.agreeUpdate(duoSDACrouter,cdsSDAC));//startvotingagainrequire(!duoSDACrouter.agreeUpgrade(dsSDAC));require(!user2.agreeUpdate(duoSDACrouter,dsSDAC));require(user1.agreeUpdate(duoSDACrouter,dsSDAC));}}

上面的示例供应了一个大众函数t1createRouter,它运用初始的DuoSDAC可升级智能合约建立路由器智能合约。

公用功用t2changeToDataShare运用统一DuoSDAC可升级智能合约的差别版原本升级路由器智能合约。搜检赞同更新的返回效果。

公用函数t3changeToChess和t4changeToStartChess运用差别的DuoSDAC可升级智能合约来升级路由器智能合约。搜检赞同更新的返回效果。

大众函数t5changeBack运用初始DuoSDAC可升级智能合约的新实例化升级路由器智能合约,并测试投票。搜检agreeUpdate的返回效果。

发起举行其他测试,以确保DuoSDAC可升级智能合约的行动相符预期。

气体斲丧量

天下没有免费的午饭。

布置合约

直接挪用gas保险库函数,而不是直接挪用gas接口来斲丧更多的数据。

布置可升级智能合约的总耗气体量是布置智能合约的一般耗气体量,再加上升级智能合约的耗气体量,再加上以下数目的一部分(取决于升级合约的次数):布置路由器。

升级到DataShare(实际上是从初始DataShare)的耗气体量比后续升级要高一些,由于这是第一次升级,因而触及新的存储位置。

运用合约

布置合同不仅斲丧更多的气体量,而且数据仓库运用的大众函数也越发高贵。

此图说清楚明了DataShare getPermissions函数的耗气体量已从略高于5000的气体增加到快要7500气体。在更庞杂的智能合约中,雷同函数的气体斲丧量也涌现了相似的增进。

运用智能合约

如t1createRouter所示,您必需先布置可升级的智能合约,然后再布置路由器。您还须要建立一个数据仓库并运用示例智能合约。这些手艺都在我们之前的文章中举行了议论。

布置智能合约

建立数据仓库

运用入手下手棋盘数据同享

结论

Alice和Bob以及其他很多人都愿望能够以疏散的体式格局同享数据。这大概会使数据更平安、更私密、更可控。

但他们也愿望能够升级智能合约而没必要变动其数据保险库。

我们已展现了一个有用的解决方案,它运用智能合约和数据仓库的组合来完成这一点,这些都相符datona-lib中形貌的接口范例。

--------------------------------------------

原文作者:Julian Goddard

译者:链三丰

译文出处:http://bitoken.world

---------------------------------------------