建议和反馈

请填写你的反馈内容

通过ORACLE使用J***A和WEB3J API构建以太坊金融应用程序的教程

2020-02-26 ·428次阅读 ·读完需要32分钟

以太坊是通用区块链,更适合通过高级脚本(也称为智能合约)来描述业务逻辑。以太坊的设计具有更广阔的视野,它是一台试图将区块链的功能与一台图灵完备的合约引擎相结合的分散式或世界计算机,作为一种信任机器。尽管以太坊借用了比特币最初提出的许多想法,但两者之间还是有很多分歧。
以太坊虚拟机和智能合约是以太坊的关键要素,并构成其主要吸引力。在以太坊中,智能合约代表一段用高级语言(Solidity,LLL,Viper)编写的代码,并作为字节码存储在区块链中,以便在基于堆栈的虚拟机(以太坊虚拟机)中可靠地运行,在每个节点中,一旦被调用。与智能合约功能的交互通过区块链网络上的交易发生,其有效负载在以太坊虚拟机中执行,并且共享的区块链状态也相应地更新。

如果您已遵循并完成了先前的教程,那么现在您应该彻底了解如何使用Solidity编写智能合约,以及如何使用web3.js和Drizzle构建完整的DApp。我们专注于使用诸如Remix或Truffle之类的工具在以太坊上构建去中心化的Web应用程序。在本演练中,我们将学习如何利用强大的语言(例如Java)来构建以太坊桌面或移动应用程序。在此过程中,我们将发现Solidity中的新概念,例如在智能合约或库中调用第三方API。

我们将涉足金融领域,并建立一个使用Java(SE)管理期货智能合约的金融项目。在整个有趣的用例中,我们将介绍以下几点:

  • 建立期货合约

  • oracle介绍

  • 引入web3j API

 

此教程的另一个好处是,建立期货智能合约将帮助您了解区块链的破坏力,以及智能合约如何通过自动付款和简化业务流程来改变金融行业(例如,期货交易市场)。

项目介绍

我知道您是开发人员,而不是金融书呆子。因此,我将尝试以最简单的方式介绍期货概念。期货合约(通称期货)是在未来的指定时间以预定价格买卖指定数量的商品或资产(每桶石油,黄金和白银)的法律协议,因此称为期货。

为了方便和清楚起见,让我们考虑来自金融行业的真实期货合约的简化版。让我们假设一家航空公司希望锁定燃油价格,以管理其承受的风险并避免任何不愉快的意外。
他们没有购买石油并在需要之前储存石油,而是购买了具有特定交货日期和每加仑价格的石油期货合约。例如,一家航空公司可以达成一项期货合同,以每加仑3美元的价格购买1,000,000加仑燃料,并在未来60天交货。

在此示例中,航空公司被视为套期保值者,而卖方则被视为投机者。由于如果价格上涨,期货合约可能会变得更有价值,因此该合约的所有者可以将该合约卖给更多人。也就是说,我们将构建一个智能合约,该合约执行此处描述的逻辑,并定义期货合约的详细信息(资产,数量,统一价格和交割日期)以及持有资金。我们还将构建一个Java应用程序,使第三方(交易所市场主管机构)能够定义其他两个方面之间的期货合约。

智能合约还将使投机者能够将期货合约出售给另一位投机者,并通过将市场价格与期货合约价格进行比较来计算其投资抵消额。

这将是一个简单的合同,只有几个主要功能和简约的设计。

 

期货智能合约

和往常一样,我们通过编写智能合约代码来启动配方。首先,在您的主文件夹中创建一个名为FuturesWeb3j的目录,并
使用truffle init 初始化一个空的Truffle项目。


然后,在Contracts /文件夹中,使用以下代码创建Futures.sol文件:
contract CFutures {地址user; 地址套期保值者;地址投机者;结构资产{ 
uint id; 
单位数量; 单价 地址卖家;地址买家;日期 

资产TradedAsset;
事件DepositEv(单位数量,地址发送者); 功能CFutures(单位
资产ID,单位数量,单位价格,地址买方,地址卖方,单位
日期)public {TradedAsset.id = assetID; TradedAsset.Quantity =数量;TradedAsset.price =价格;TradedAsset.seller =卖方;投机者=卖方; 
套期保值者=买方; TradedAsset.buyer =买方;TradedAsset.date =日期;
}

函数deposit()公共应付款收益率(布尔){ 
require(msg.value == TradedAsset.Quantity * TradedAsset.price); DepositEv(msg.value,msg.sender); 
返回true;
}

修饰符onlyhedger(){require(msg.sender ==树篱); 
_; 
}

功能sellcontract(地址为newhedger)public onlyhedger返回(布尔){

树篱= newhedger; 返回true;
}

函数getpaid()公共收益(布尔){ 
require(现在> = TradedAsset.date &&地址(this).balance> 0); speculator.transfer(address(this).balance); 
返回true;

}

这是期货智能合约代码的简化版本。我假设您现在已经熟悉Solidity语言,并且可以开发用于添加高级功能的代码。

如您所见,起点是定义一个构造器,该构造器将确定合同的详细信息,即:资产ID,同意购买的数量,单价,买方地址,卖方地址和交货日期。

我们还将定义一些函数:

  • deposit():套期保值者(航空公司)将调用此函数来存放商定的资金。

  • sellcontract():投机者可以将合同出售给另一位投资者。getpaid():合同将在交货日期将资金释放给石油供应商。

  • onlyhedger():这是一个修饰符,用于将操作限制为初始购买者(套期保值者)。

 

区块链神谕

在此级别上,先前的合同使基本操作可以锁定和解锁资金以防止商品交付。但是,一旦合同到期,我们希望合同计算期货交易产生的抵消收益(储蓄)或损失,换句话说,对冲者节省或损失了多少。
在这种情况下,在结算时,智能合约需要坚实可靠的信息源来确定基础商品(石油)价格以计算抵消额。但是,这里出现一个问题:合同本身是否能够知道石油市场价格是多少?

正如我们在先前的教程中所介绍的那样,智能合约是在独立的VM中执行的确定性代码,无需直接连接到外部信息源!

但是,对于这种情况,有一种解决方法:oracles。

Oracle是受信任的代理或数据供应商,它们从可靠的外部数据源读取请求的信息并将其发送到智能合约。在区块链领域,我们有一些此类服务的提供商,例如Chainlink,Link,Blocksense和Oraclize。在我们的示例中,我们将使用Oraclize(http://www.oraclize.it/),因为它是Oracle服务的行业领导者。

让我们看看如何将合同连接到Oracle合同。在前面的代码中,我们必须进行以下更改:

语用强度^ 0.4.24; 
导入“ ./oraclizeAPI_0.5.sol”;合同CFutures正在使用Oraclize { 
uint public fuelPriceUSD;

事件NewOraclizeQuery(字符串描述); 事件NewDieselPrice(string price);

函数CFutures(uint资产ID,uint数量,uint价格,地址购买者,地址卖方,
uint日期)public { 
…//使其保持先前的定义

function callback(bytes32 myid,string result)public {require(msg.sender == oraclize_cbAddress()); NewDieselPrice(结果); 
fuelPriceUSD = parseInt(result,2); 
}

函数updateprice()public payable { 
NewOraclizeQuery(“已发送Oraclize查询,等待答案..”); oraclize_query(“ URL”,“ xml(https://www.fueleconomy.gov/ws/rest/fuelprices).fuelPrices.diesel”); 


在结果,我们使用的Oraclize服务请求Fuelprice一个简单的合同结束了
(让我们考虑用燃料,相当于油)。

如您所见,我们首先导入Oraclize API:import“ ./oraclizeAPI_0.5.sol” ;;。
然后,我们继承usingOraclize契约来访问库方法。
接下来,为了帮助编译器解决导入问题,我们需要通过运行wget https://raw.githubusercontent.com/oraclize/ethereum-api/master/oraclize API_0.5将Oraclize API合约和库下载到Truffle的Contracts /文件夹中.sol。
在Oracle代码部分中,我们与fuelPriceUSD一起定义了两个新函数:updateprice()和                              callback。
第一个使用oraclize_query通过两个参数将查询发送到Oraclize的智能合约:请求的类型(URL,WolframAlpha,IPFS multihash)和请求的信息(XML响应中的特定属性)。由于Oraclize服务不是免费的,因此updateprice函数被声明为可付费的,并且该函数应接受以太币才能为Oraclize服务付费。但是,合同进行的第一个查询是免费的,因此我们包含了对updateprice()函数的调用,而无需在构造函数中发送以太币。

另一方面,第二个函数                 回调是由API定义的,顾名思义,这是一个一旦Oracle发回响应就执行的回调函数。它的第一个参数是请求的ID,而第二个参数是请求的结果。在此示例中,我们使用由Oraclize API文件定义的parseInt函数来设置数字精度。在前面的示例中,$ 3.20将作为320美分返回。

下图显示了使用Oraclize的初始合同和数据源之间的交互:


 

使用Java的以太坊区块链开发

最后,让我们实现offset()方法,该方法将通过基于价格变化获取此期货合约来计算套期保值者获得的抵消利润:

函数offset()公共视图返回(uint){ 
return TradedAsset.Quantity *(fuelPriceUSD-TradedAsset.price); 
}

现在,合同已完成,请使用松露编译来编译合同,并检查是否存在任何错误。

 

Web3j

对于想要在新的区块链环境中迈出第一步的Java爱好者来说,Web3j是一种真正的享受。它代表了用于与以太坊客户端集成的轻量级Java和Android API。它使您可以轻松地基于以太坊构建去中心化的Java应用程序。您可以在其官方网站上找到有关该项目的所有详细信息:https:// web3j.io/。


先决条件

要充分利用以下各节,您需要具有Java的基本知识。您还应该安装以下元素来构建应用程序:

  • Java 8 JDK

  • Eclipse和Maven –用于编码和开发

 

设置Web3J Maven项目

如果您已经从GitHub下载了代码,则可以将其导入Eclipse。否则,如果要从头开始构建项目,则必须创建一个新的Maven项目,如下所示:

  • 在Eclipse IDE中,导航到File File 新品其他显示项目创建向导。

  • 滚动到Maven文件夹,打开它,然后选择Maven Project。然后选择下一步

  • 继续通过按下一步传递对话表格,直到获得以下表格:

使用Java的以太坊区块链开发


在这里,您将需要输入有关正在创建的Maven项目的信息。选择所需的名称,然后按完成。以下是示例项目结构在Maven项目创建过程结束时的外观:
使用Java的以太坊区块链开发

然后,在Maven POM文件(pom.xml)中,我们需要在相应的POM标记中添加以下几行:

 
UTF-8  
1.8  
1.8  
 
 
 
org.apache.maven.plugins  
maven-compiler-plugin  
3.7.0  
<配置> 
1.8  
1.8  
 
 
 

org.slf4j  
slf4j-simple
1.7.21  

编辑Maven POM文件后,我们必须更新项目以下载必要的依赖项。右键单击Project,单击Maven,然后选择Update Project ...
使用Java的以太坊区块链开发

 

安装web3j

Web3j提供了作为便携式.jar分发的命令行工具。在几个步骤中,您可以开始使用web3j命令行,因此不需要安装。在您的主文件夹中。
运行wget 
https://github.com/web3j/web3j/releases/download/v3.4.0/web3j-3.4.0.tar 

解压缩下载的TAR文件:

焦油xvf web3j-3.4.0

然后将结果文件夹添加到系统路径:

导出PATH = $ PATH:〜/ web3j-3.4.0 / bin

你们都准备好了 现在,您可以创建以太坊账户或为智能合约生成包装器类。

 

钱包创作

除了其他功能外,web3j命令行工具还允许我们创建钱包或发送交易。

要创建一个新的以太坊账户,请运行web3j wallet create。系统将要求您提供密码(不要忘记密码),然后提供您要备份帐户的位置(钱包JSON文件)。最后,您将获得一个带有长名称(可以更改此名称)的JSON文件,其中包含很多信息,包括帐户地址和私钥:
使用Java的以太坊区块链开发

另外,您可以导出在MetaMask或Geth中创建的Testnet帐户之一,而不是使用web3j。

在此项目中,我们将在Testnet中运行合同,因此我们需要向新创建的帐户提供测试以太币。为此,我们可以使用MetaMask获取免费的以太坊,并将其发送到新帐户的地址。请注意,您应该添加0x并等待直到确认交易,如下所示:
使用Java的以太坊区块链开发

帐户的地址保存在先前创建的钱包的JSON文件中,该地址是文件名的最后一部分。


Java客户端

如本教程前面所述,我们正在使用web3j构建一个简单的Java应用程序。让我们简要地了解该API背后的机制。

Web3j是以太坊的web3 API的Java端口,用于管理以太坊客户端与网络之间的通信(JSON-RPC)。对于每个智能合约,web3j都会生成包装器类,从而简化了与以太坊的访问以及智能合约的交互。因此,所有复杂性都将被隐藏,并且您不会被迫自行发起RPC调用。下图(来自官方文档)描述了web3j和以太坊之间的交互流程:
使用Java EE进行以太坊区块链编码

 

包装器生成器

在使用web3j之前,我们需要为智能合约构建Java包装器类。web3j命令行工具直接从Truffle的合同模式支持Java智能合同功能包装器的自动生成,如下所示:

web3j松露生成〜/ FuturesWeb3j / build / contracts / CFutures.json -o〜
/ eclipse-workspace / futures / src / main / java / -p org.recipe6.futures


第一个参数是Truffle为CFutures合同编译的构建文件,第二个参数是Java项目目标的路径,将在该路径中生成类包装器。另外,-p参数应该是所生成类的Java打包结构:
以太坊与Java

这将导致创建一个具有与智能合约同名的新类的CFutures.java文件:

公共类CFutures扩展了Contract { 
private static final String BINARY =“ 0x60606040523415600e576 ...”; 
}

如您所见,BINARY字符串表示您的已编译合同(字节码)。删除\和\ n(如果有)。您将在此类中找到所有智能合约方法的Java实现。

请记住,如果进行任何更改,则必须编译智能合约,然后像以前一样生成新的ABI,字节码和web3j包装器。

现在我们有了智能合约类包装器,让我们继续编写期货主类。我们必须编写一个Java类,该类使用Futures类包装器部署并与Cfutures智能合约进行交互。


初始化web3j

现在,让我们集中讨论在Maven项目中创建的App.java文件。
第一步是初始化一个web3j对象。为此,我们将提供程序(例如,第三方或本地以太坊节点的端点)传递给web3j构建函数:

Web3j web3j = Web3j.build(new HttpService(“ https://ropsten.infura.io”));

在此示例中,我们将使用Infura网关(https://infura.io/)访问Testnet网络。如果您还记得,在以太坊中,我们总是需要一个入口点,它是一个RPC / HTTP提供程序(节点),用于承载用户分派给网络的命令或动作。通常,最终用户应具有连接到网络的本地RPC客户端。但是,我们直接使用在线提供程序(也由MetaMask使用)来避免不必要的说明,并保持与oracle的直接通信。

请记住,如果要使用专用网络,则需要使用以太坊桥API(https://github.com/oraclize/ethereum-bridge)才能继续使用Oraclize服务。

 

设置以太坊账户

为了与区块链网络进行交互,我们需要建立交易,因此我们需要一个钱包。我们可以使用现有的,如下所示:

凭据凭据= WalletUtils.loadCredentials(“ PASSWORD”,“ /path/to/walletfile.json”);

或者,我们可以创建一个新的钱包:WalletUtils.generateNewWalletFile(“ PASSWORD”,new File(“ / path / to / destination”),true);。
加载或创建后,您可以使用以下方法检查钱包的当前余额:

EthGetBalance AccountBalance = web3j.ethGetBalance(credentials.getAddress(),
DefaultBlockParameterName.LATEST).sendAsync()。get(); log.info(“帐户余额” + AccountBalance);

部署合同

定义了钱包凭证并初始化了web3后,我们可以使用以下部署方法来构建和部署Cfutures合约:
CFutures CFuture_ = CFutures.deploy(web3j,凭据,CUSTOM_GAS_PRICE,GAS_LIMIT,资产ID,
数量,价格,买方,卖方,日期).send();

前四个参数是构造部署事务所需的,而其余的则是合同的构造函数所需的参数。

在这四个参数中,我们需要定义天然气限额和天然气价格。在此示例中,我将它们定义为全局变量,如下所示:

私有静态最终BigInteger GAS_LIMIT = BigInteger.valueOf(4_700_000); 私有静态最终BigInteger CUSTOM_GAS_PRICE = Convert.toWei(“ 140”,
Convert.Unit.GWEI).toBigInteger();

在这里,我们定义了47,00,000单位天然气的天然气限制和140 GWei的天然气价格。Web3j的默认价格为22 GWei-随时定义您自己的价值。要选择正确的值,您可以在https://ropsten.etherscan.io/chart/gasprice上查看Ropsten的当前汽油价格。
一旦执行deploy()函数,它将使用提供的凭据和构造函数参数值在以太坊区块链上创建CFutures智能合约的新实例。如果由于某种原因在600秒内未验证部署事务,则将引发异常。

您随时可以访问Ropsten资源管理器,以使用此处记录的链接检查合同是否已部署:

字符串CFuturesAddress = CFuture_.getContractAddress(); log.info(“查看合同位于https://ropsten.etherscan.io/address/” + CFuturesAddress);

 

与智能合约互动

如果要使用现有智能合约构造智能合约包装器的实例,只需将其地址传递给预定义的加载函数:

CFutures CFutureInstance = CFutures.load(“ contract_address”,web3j,凭据,
CUSTOM_GAS_PRICE,GAS_LIMIT);

一旦实例化了一个新的CFuture对象(使用部署或加载),Eclipse将帮助您使用自动完成功能来选择要调用的函数或访问合同专有性: 
使用Java EE进行以太坊区块链编码

 

调用合约功能

在我们的示例中,首次加载合同后,我们需要存入双方同意的金额。因此,我们需要执行存款功能,同时以太币发送合约价值。

在web3j中,所有方法的定义均与其等效的Solidity方法相同,并采用相同的参数。要使用Cfutures函数进行交易,我们使用点表示法调用等效对象的方法,如下所示:

BigInteger数量= BigInteger.valueOf(120000); BigInteger价格= BigInteger.valueOf(300);

TransactionReceipt DepositReceipt = CFutureInstance.deposit(Price.multiply(Quantity))。send();

如您所见,传递给deposit函数的参数是BigInteger(价格*数量),而不是整数或整数,因此应在web3j中将所有变量声明为BigInteger。

为了保留我们的测试以太币,我们将在wei中存入资金,并假设wei值得一分钱(我知道这是不现实的)。我们在这里假设,在协议达成时,每加仑油的价格为300美分(300 wei)。数量和价格被声明为单独的变量。

如果查看CFutures.java中的包装器类,则会为智能合约中定义的每个函数找到一个已定义的Java函数。例如,您将找到以下内容:

public RemoteCall deposit(BigInteger weiValue){ 
… 
return executeRemoteCallTransaction(function,weiValue); 
}

您可以看到函数定义已更改,因为原始函数不接受任何参数:

deposit()应付收益(布尔){}

Web3j为应付款功能定义了这个新参数,以便可以传递一定数量的Wei。

值得注意的是,如官方文档(https://web3j.readthedocs.io/en/latest/smart_contracts.html)所述,无论方法上指定了哪种返回类型,事务调用都不会返回任何值。因此,对于所有交易方法,将返回与交易相关联的交易收据(https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionreceipt)。

交易收据之所以有用,有两个原因:

  • 它提供了交易所在的开采区块的详细信息

  • 被调用的实体事件将作为事务的一部分记录下来,然后可以提取该事件


 

例如,我们可以从交易收据中获取交易哈希值,并在Etherscan上检查相应的交易,如下图所示: 
使用Java EE进行以太坊区块链编码

 

调用视图方法

对于视图方法(仅读取智能合约中的值),将使用普通方法调用来调用它们,但它们不会返回TransactionReceipt,因为不会启动任何事务(不关联成本)。在我们的智能合约中,我们有一个view 
方法offset(),可以按以下方式调用:
BigInteger Offset = CFutureInstance.offset()。send(); log.info(“您的偏移量为” + Offset.intValue());


以相同的方式,可以查询智能合约的公共状态,例如读取最后的fuelPriceUSD状态的值:
BigInteger LastfuelPrice = CFutureInstance.fuelPriceUSD()。send(); 整数fuelPriceUSD = LastfuelPrice.intValue(); 
log.info(“ Last fuel Price,根据Oracle的燃料价格为:” + fuelPriceUSD);

但是,要将fuelPriceUSD更新为当前价格,我们需要经历两个步骤。
首先是更新价格,这是我们从oracle请求的。第二种是等待事件通知我们oracle的响应以读取新值:

BigInteger txcost = Convert.toWei(“ 0.01”,Convert.Unit.ETHER).toBigInteger(); TransactionReceipt UpdateReceipt = CFutureInstance.updateprice(txcost).send(); 
对于(CFutures.NewDieselPriceEventResponse事件:CFutureInstance.getNewDieselPriceEvents(UpdateReceipt)){ 
log.info(“油价已更新:” + event.price); 
}

请记住,当您调用oracle时,您正在启动异步交换,这意味着查询和响应(请求和回调事务)之间会有延迟。因此,在我们的Java代码中,我们需要在调用offset()方法为我们提供准确值之前,通过侦听NewDieselPrice事件来更新价格。

请注意,我们在调用updateprice()时使用Convert.toWei(“ 0.01”,Convert.Unit.ETHER)从以太币转换为wei来支付通话费用。

 

Web3j事件

在智能合约中,我们定义了一些事件。每一个将在智能合约包装器中使用相同名称的方法表示,该方法获取交易收据并在
EventValues对象的实例中返回解码结果(事件参数)。鉴于此,以下是获取事件数据并在控制台中显示其内容的方法:

对于(CFutures.DepositEvEventResponse事件:CFutureInstance.getDepositEvEvents(DepositReceipt)){ 
log.info(“检测到Depoist事件:” + event.amount +“ wei已被存放”);

log.info(“资金已通过以下方式发送:” + event.sender); 
}

或者,您可以使用Observables(RxJava的observables),它将监听与智能合约相关的事件。然后使用EthFilter对象过滤您的可观察对象,如下所示:

EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST,DefaultBlockParameterName.LATEST,
CFutureInstance.getContractAddress()); web3j.ethLogObservable(filter).subscribe(
Clog- > { log.info(“合同日志” + Clog.toString()); 
});

对于EthFilter,我们指定希望应用于过滤器的主题,包括合同地址。我们还可以提供特定主题(仅适用于索引的Solidity事件参数)以使用以下方法进行过滤:filter.addSingleTopic(EventEncoder.encode(event)); 
在撰写本文时,Infura仅在主网,Ropsten和Rinkeby上使用websocket端点支持侦听事件(过滤器/订阅)。但是,web3j尚不支持websocket,因此在使用Infura时我们无法在web3j中使用过滤器。
这是我们在本食谱中需要介绍的最后一个web3J功能–是时候通过在Eclipse中导入和运行项目来测试代码了。

 

增强功能

最后要考虑的是在此应用程序中添加文本或图形菜单,以帮助用户做出选择。为了避免使用与我们的目的无关的代码来膨胀项目,我选择了一个简单的基于文本的菜单:

输入=新的Scanner(System.in); CFutures CFutureInstance = null; 
System.out.println(“请做出选择:”); System.out.println(“ 1 –部署新功能合同。”); System.out.println(“ 2 –加载合同”); System.out.println(“ 3 –进行存款”); System.out.println(“ 4 –当前燃油价格”); System.out.println(“ 5 –更新燃油价格”); System.out.println(“ 6 –投资抵销”); System.out.println(“ 0-exit”); 
int选择;
选择:while(input.hasNextInt()){

选择= input.nextInt(); 切换(选择){ 
情况0:
中断选择;
… 

}

太好了,现在运行您的APP.java文件来检查是否一切都按预期工作。您应该看到详细描述执行步骤的消息日志,类似于以下内容:
使用Java EE进行以太坊区块链编码

您可能会以任意顺序获得事件结果,因为它们是并行异步执行的,并且以后会捕获它们的结果。因此,最好使用CompletableFuture类包装web3j方法并处理这些异步调用。

 

结论

在本教程中,我们使用了您喜欢的语言Java来探讨以太坊区块链的工作。确实,它是通过构建基于Oracle的应用程序,为用Java构建复杂的以太坊应用程序的门而对web3j进行的温和介绍。从现在开始,您只需要深入研究web3j文档即可。您将在其主项目存储库(https://github.com/web3j/web3j/tree/master/codegen/src/test/resources/solidity)中找到许多智能合约示例。


评论(0)问答(0)
请先登录或注册

请先登陆或注册

相关推荐

李斌说币:大饼顶部不远了短期注意回调风险

John McAfee再次表示比特币毫无价值 近日,John McAfee回复推特网友评论称,比特币毫无价值。此前1月29日,他也曾于推特表示,比特币是真正的垃圾币。而此前John McAfee却以“......
A-李斌说币 · 2020-04-07
90阅读 · 0赞赏 · 0问答

存储的内容违反当地法律怎么办?揭秘IPFS创始人胡安的“外交辞令”

![](https://www.liankexing.com/Public/Uploads/2020-04-07/5e8c37fd070f3.png) 当你惬意地在抖音、微博刷视频时,有没有遇见自己......
YottaChain · 2020-04-07
72阅读 · 0赞赏 · 0问答

科普| 冷数据在IPFS上可能会丢失?

 首先,我们先对数据进行一个简单的了解,数据分为冷数据、热数据,难道数据也有温度吗?从字面意思来简单的说,热数据就是访问多的数据,门庭若市十分热闹。冷数据就是基本上没什么客人访问,门庭冷落车......
金锄矿业 · 2020-04-07
74阅读 · 0赞赏 · 0问答

玩一分快三彩怎么才能长期盈利-询68183049。

【导師Q:68183049】【邀请码88288889】【网址yf165、c0m】【长久盈利轻松上岸】【顶尖稳定盈利】 希望帮助到大家怎么玩才能赢如何才能回血上岸?如果你是刚刚玩,我来教教你。......
晨小柒 · 2020-04-07
70阅读 · 0赞赏 · 0问答

玩快三彩输了很多,该如何回血上岸-询68183049。

【导師Q:68183049】【邀请码88288889】【网址yf165、c0m】【长久盈利轻松上岸】【顶尖稳定盈利】 希望帮助到大家怎么玩才能赢如何才能回血上岸?如果你是刚刚玩,我来教教你。......
晨小柒 · 2020-04-07
76阅读 · 0赞赏 · 0问答

幸运一分快三有什么快速回血的技巧呢?询68183049

【导師Q:68183049】【邀请码88288889】【网址yf165、c0m】【长久盈利轻松上岸】【顶尖稳定盈利】 希望帮助到大家怎么玩才能赢如何才能回血上岸?如果你是刚刚玩,我来教教你。......
晨小柒 · 2020-04-07
61阅读 · 0赞赏 · 0问答

lqq

676

LK币

0

粉丝

3

笔记

感谢"lqq"

这篇精彩的笔记,目前已经帮助

  • 0
  • 0
  • 4
  • 2
  • 8
喜欢0
链客社群 加入

微博进入

商务合作>

广告投放>

公司名称:北京链客行科技有限公司

联系方式:010-67707199

ICP备案号:京ICP备18032136号

Copyright:链客区块链技术问答社区 版权所有

感谢您的提问,问题被社区永久收入以便新人查看。一定要记得采纳最佳答案哦!加油!

感谢您的善举,每一次解答会成为新人的灯塔,回答被采纳后获得20算力和相应的LK币奖励

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!