作者:VV一笑ヽ
如果有一个p2p的demo,我们要怎么才能应用到区块链当中?
今天就来一起尝试一下吧!
首先,我们需要模拟网络中的多个节点相互通讯,我们假设现在的情况是有AB两个节点整个过程如下图所示:
梳理流程
让我们来梳理一下整个流程,明确在p2p网络中需要做的事情。
启动节点A。A首先创建一个创世区块创建钱包A1。调用节点A提供的API创建一个钱包,此时A1的球球币为0。A1挖矿。调用节点A提供的挖矿API,生成新的区块,同时为A1的钱包有了系统奖励的球球币。启动节点B。节点B要向A同步信息,当前的区块链,当前的交易池,当前的所有钱包的公钥。创建钱包B1、A2,调用节点A和B的API,要广播出去创建的钱包,目前节点只有两个,因此A需要告诉B,A2的钱包。B需要告诉A,B1的钱包。A1转账给B1。调用A提供的API,同时广播交易。A2挖矿记账。调用A提供的API,同时广播新生成的区块。总结一下,就是节点刚开始加入到区块链网络中,需要同步其他节点的
已经处于网络中的某个节点,在下述情况下需要通知网络中的其他节点
P2P的大致流程为下方几点,我们后边的实现会结合这个过程。
client→server发送消息,一般是请求数据server收到消息后,向client发送消息client收到消息处理数据相关代码
在实现的过程中,由于消息类型较多,封装了一个消息对象用来传输消息,对消息类型进行编码,统一处理,消息对象Message,实现了Serializable接口,使其对象可序列化:
开源可编程加密货币平台Spacemesh将于7月14日上线主网:7月8日消息,开源可编程加密货币平台Spacemesh将于7月14日上线主网,任何拥有标准消费级PC的人都将能够开始运行节点并赚取Smesh代币,Smesh用户将在 8 月 11 日开始的两周内获得第一份奖励,且所有 smesh 用户都会在8月15日之前获得他们的第一份奖励。
其中运行节点的最低要求为CPU:Intel或AMD x86-64或64位ARM,包括Apple Silicon(但不包括Raspberry Pi);内存:1GiB+;操作系统:Windows 10/11、MacOS、Ubuntu 22.04+或Fedora 36+;磁盘空间:50GiB的可用磁盘空间;始终开启且无流量限制的互联网连接,下载速度至少为5 mbps,上传速度至少为1 mbps。[2023/7/8 22:25:35]
publicclassMessageimplementsSerializable{/***消息内容,就是我们的区块链、交易池等所需要的信息,使用JSON.toString转化到的json字符串*/privateStringdata;/***消息类型*/privateinttype;}涉及到的消息类型有:
/***查询最新的区块*/privatefinalstaticintQUERY_LATEST_BLOCK=0;/***查询整个区块链*/privatefinalstaticintQUERY_BLOCK_CHAIN=1;/***查询交易集合*/privatefinalstaticintQUERY_TRANSACTION=2;/***查询已打包的交易集合*/privatefinalstaticintQUERY_PACKED_TRANSACTION=3;/***查询钱包集合*/privatefinalstaticintQUERY_WALLET=4;/***返回区块集合*/privatefinalstaticintRESPONSE_BLOCK_CHAIN=5;/***返回交易集合*/privatefinalstaticintRESPONSE_TRANSACTION=6;/***返回已打包交易集合*/privatefinalstaticintRESPONSE_PACKED_TRANSACTION=7;/***返回钱包集合*/privatefinalstaticintRESPONSE_WALLET=8;由于代码太多,就不全部粘在这里了,以client同步其他节点钱包信息为例,结合上面的p2p网络交互的三个步骤,为大家介绍下相关的实现。
Sui Network发布0.28新版本文档,包括引入可编程新型交易等:3月7日消息,公链Sui Network发布下一个版本0.28的文档。具体功能更改将包括推出取代批次处理交易和普通交易的可编程新型交易、从20字节调整到32字节(在十六进制中,从40增加到64)、更改Gas预算以使用SUI而不是Gas单位等。[2023/3/7 12:46:47]
1、client→server发送消息,一般是请求数据
在client节点的启动类首先创建client对象,调用client内部方法,连接server。
启动类main方法中关键代码,:
P2PClientp2PClient=newP2PClient;Stringurl="ws://localhost:"+args+"/test";p2PClient.connectToPeer(url);P2PClient中的connectToPeer方法
publicvoidconnectToPeer(Stringurl)throwsIOException,DeploymentException{WebSocketContainercontainer=ContainerProvider.getWebSocketContainer;URIuri=URI.create(url);this.session=container.connectToServer(P2PClient.class,uri);}P2PClient中,WebSocketContainer.connectToServer的时候会回调onOpen函数,假设我们只查询钱包公钥信息,此时服务端会接收到相应的请求。
@OnOpenpublicvoidonOpen(Sessionsession){this.session=session;p2PService.sendMsg(session,p2PService.queryWalletMsg);}注意:我把解析消息相关的操作封装到了一个service中,方便server和client的统一使用。给出相应的queryWalletMsg方法:
StarkWare的编程语言Cairo探索投票类应用场景:3月1日消息,由零知识证明研究机构StarkWare推出的专用编程语言Cairo宣布正在开发一种简单投票机制的应用,可以支持大规模的用户以安全的方式投票并保存在区块链上,去中心化组织(DAO)也将受益于该功能。该应用会收集用户的选票,验证每次投票的签名,累计在一起后更新至默克尔树,同时将生成一个STARK证明以确保本轮投票的有效性。最后这些数据会被发送到一个链上的STARK验证器智能合约,然后生效,应用的智能合约就可以验证并更新至最新状态。[2021/3/1 18:03:17]
publicStringqueryWalletMsg{returnJSON.toJSONString(newMessage(QUERY_WALLET));}以及之前提到的sendMsg方法:
@OverridepublicvoidsendMsg(Sessionsession,Stringmsg){session.getAsyncRemote.sendText(msg);}2、server收到消息后,向client发送消息
server收到消息,进入P2PServer中OnMessage方法
/***收到客户端发来消息*@parammsg消息对象*/@OnMessagepublicvoidonMessage(Sessionsession,Stringmsg){p2PService.handleMessage(session,msg);}p2PService.handleMessage就是解析接收到的消息,根据类型的不同调用其他的方法,这里我们接收到了client传来的信息码QUERY_WALLET。
@OverridepublicvoidhandleMessage(Sessionsession,Stringmsg){Messagemessage=JSON.parseObject(msg,Message.class);switch(message.getType){caseQUERY_WALLET:sendMsg(session,responseWallets);break;caseRESPONSE_WALLET:handleWalletResponse(message.getData);break;......}根据信息码是QUERY_WALLET,调用responseWallets方法,得到数据。
动态 | Telegram 公布 TON 编程大赛 最高奖励 40 万美元:Telegram 官方今日公布 TON 最新编程大赛,任务是为 TON 区块链平台构建智能合约,最高奖金为 40 万美元,截止日期是北京时间 10 月 16 日 6:00,细则和提交渠道尚未公布。任务分别是:1. 根据官方公布的 TON Contest.txt 文件所述,构建一个或多个智能合约;2. 提交 FunC / TON VM 改进建议(可选);3. 查找并提出 TON 测试网的 BUG (可选),这三项任务的奖金为 20 万至 40 万美元。TON 中文社区表示:“这其实属于 TON 官方上线前的大规模测试,因 Telegram 生态内本身有大量的开发者,故 TON 选择了在 Telegram 生态内进行公布大赛,中文地区的开发者可以与我们联系。距离 TON 主网启动还有 37 天。”[2019/9/25]
privateStringresponseWallets{Stringwallets=blockService.findAllWallets;returnJSON.toJSONString(newMessage(RESPONSE_WALLET,wallets));}这里我把区块链的相关操作也封装到了一个service中,下面给出findAllWallets的具体实现,其实就是遍历钱包集合,统计钱包公钥,没有什么难度。
@OverridepublicStringfindAllWallets{Listwallets=newArrayList<>;myWalletMap.forEach((address,wallet)->{wallets.add(Wallet.builder.publicKey(wallet.getPublicKey).build);});otherWalletMap.forEach((address,wallet)->{wallets.add(wallet);});returnJSON.toJSONString(wallets);}得到数据之后,返回给client:
声音 | 上交所前总工白硕:可编程的法定数字货币将是必争要地:今日在2019全球区块链(杭州)高峰论坛上,Chinaledger技术委员会主任、上交所前总工程师白硕认为,法定数字货币并不会给我们比移动支付更好的体验,法定数字货币也并不意味着用户可以自己做主,另外法定数字货币如果是可编程的,我认为将是唯一机会,必争要地。[2019/5/17]
因此我们的responseWallets方法中,最后一句话新建了一个message对象,并设置了信息码为RESPONSE_WALLET,在handleMessage中调用了sendmsg方法回传给client。
caseQUERY_WALLET:sendMsg(session,responseWallets);break;3、client收到消息处理数据
client收到了请求得到的数据,进入P2PClient中的OnMessage方法
@OnMessagepublicvoidonMessage(Stringmsg){p2PService.handleMessage(this.session,msg);}同样进入我们上面提到的p2PService.handleMessage方法,此时收到的信息码为RESPONSE_WALLET,进入handleWalletResponse方法
caseRESPONSE_WALLET:handleWalletResponse(message.getData);break;handleWalletResponse的实现,解析接收到的钱包公钥信息,并存储到client节点的blockService中。
privatevoidhandleWalletResponse(Stringmsg){Listwallets="\"\"".equals(msg)?newArrayList<>:JSON.parseArray(msg,Wallet.class);wallets.forEach(wallet->{blockService.addOtherWallet(walletService.getWalletAddress(wallet.getPublicKey),wallet);});}在具体实现中,由于使用到了注入服务的方式,在向server和client中使用@Autowired注解注入Bean的时候,由于Springboot单例的特点,而websocket每次都会创建一个新的对象,所以在使用服务的时候会导致出现空指针异常,因此,我们创建了一个工具类Springtil,每次需要服务时,都从Spring容器中获取到我们所需要的bean,下面给出工具类代码。
publicclassSpringUtilimplementsApplicationContextAware{publicstaticApplicationContextapplicationContext;@OverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext)throwsBeansException{if(SpringUtil.applicationContext!=null){SpringUtil.applicationContext=applicationContext;}}/***获取applicationContext*/publicstaticApplicationContextgetApplicationContext{returnapplicationContext;}/***通过name获取Bean.*/publicstaticObjectgetBean(Stringname){returngetApplicationContext.getBean(name);}/***通过class获取Bean.*/publicstaticTgetBean(Classclazz){returngetApplicationContext.getBean(clazz);}
/***通过name,以及Clazz返回指定的Bean*/publicstaticTgetBean(Stringname,Classclazz){returngetApplicationContext.getBean(name,clazz);}}
因此测试之前我们首先需要设定SpringUtil中的applicationContext,下面给出启动类以及相关节点的配置。
publicstaticvoidmain(Stringargs){System.out.println("Helloworld");SpringUtil.applicationContext=SpringApplication.run(Hello.class,args);if(args.length>0){P2PClientp2PClient=newP2PClient;Stringurl="ws://localhost:"+args+"/test";try{p2PClient.connectToPeer(url);}catch(Exceptione){e.printStackTrace;}}使用时,我们需要手动获取bean
//之前是这样//@Autowired//privateP2PServicep2PService;//改正后,去掉Autowired,每次使用都手动获取beanprivateP2PServicep2PService;@OnOpenpublicvoidonOpen(Sessionsession){//如果不使用那些,在这里会报空指针异常,p2PService为nullp2PService=SpringUtil.getBean(P2PService.class);//新增这句话从IVO容器中获取beanp2PService.sendMsg(session,p2PService.queryWalletMsg);}Hello节点,测试时作为server
Test节点,测试时作为Client。
到此,我们就实现了p2p网络中server节点与client节点的交互过程。建议你也可以尝试一下,然后在评论区和我们讨论哦!
在隔离期间,我们无法旅行,但是没有人取消虚拟探险,对吗?因此,我们将带您穿越欧洲最宏伟的城堡,这些城堡在其废墟中拥有数百年令人难以置信的丰富历史.
1900/1/1 0:00:00纸币是否会携带病?将其放入微波炉加热能否起到消作用? 图片来源于网络答案是否定的,不仅不能消,还可能造成人民币毁损、灭失,存在巨大的安全隐患.
1900/1/1 0:00:00空空如也的货架 随着疫情的大范围扩散,全球各国都陷入了恐慌。很多超市出现了“哄抢物资”的局面,货架上的卫生纸被抢购一空.
1900/1/1 0:00:003月30日,吉利汽车控股有限公司发布2019年财报。2019年吉利汽车全年总收益达974亿人民币,净利润82.6亿人民币,股东应占溢利81.9亿人民币.
1900/1/1 0:00:00众所周知,比特币被视为“数字黄金”,同时一些人认为投资者也把这个加密货币视作全球不稳定局势下的一种避险资产.
1900/1/1 0:00:00召唤师峡谷打累了,玩会儿云顶吧!相信不少召唤师都是如此,云顶之奕上线后,新颖休闲的游戏方式,吸引了大批玩家的家的加入,游戏的火热程度,曾一度超越了召唤师峡谷,而固定的玩法和阵容.
1900/1/1 0:00:00