如何通过构建智能合约来销售商品

如何通过构建以太坊智能合约来销售商品?这是个问题。

毫无疑问,比特币已经改变了我们看待和理解什么是金钱,价值以及最近由智能合约产生的所有权的方式。这很有趣,因为几乎每个人都听说过它或加密货币。来自许多业务领域的人,不仅仅是我们,IT工作者。

在本文中,我将展示我关于以太坊的第一份智能合约,这是我对区块链的个人研究的一部分。

以太坊智能合约

区块链适合初学者

有许多涉及区块链技术的概念,但在本节中我将尝试解释这种惊人的颠覆性技术。

顾名思义,区块链是使用它的哈希数据连接在一起的数据链的块,由用户的私钥签名。通常,这些块的大小限制为1MB,并且由于此限制而存储尽可能多的交易。

  • 概念1区块:它们是存储交易的块。认为这些块是具有一些元组的表,每个块都存储交易。

区块

  • 概念2不对称加密,公钥和私钥对:每个人都可以访问我们的公钥,只需我们访问我们的私钥即可。并且,非对称加密意味着:我们使用其中一个密钥编码,它只能与另一个密钥进行解码。没有例外。

真实性:如果我们想签署数据,我们使用私钥进行编码,因为每个人都可以使用我们的公钥解码并安全地认证我们。但是没有人可以改变数据并再次签名,因为它会被命运所拒绝。当真实性成为问题时使用。这是区块链的情况 。

签署数据以保证真实性

  • 使用私钥,所有者对数据进行编码,或者更好地对数据进行签名 。 通过此操作,所有者保证没有人伪造他或她的身份。
  • 使用公钥,每个人都可以解码数据,或者更好地检查 签名 。 通过这种操作,起源就是我们所期待的。
  • 概念3区块链的不可侵犯性质在于链接块的机制:当生成新块时,从当前块的数据生成哈希,包括它的签名。然后,生成新块,将来自前一块的hash与当前块的数据组合,并生成新的hash并使用用户的私钥进行签名,依此类推。如果有人试图更改块的数据以伪造事务,则他或她必须在整个网络开始使所有这些重新生成的块无效之前快速生成所有后续块。

如同暗夜里一开始没有灯……

一切都从创世块开始,这个块负责启动区块链网络并设置许多参数值,例如挖掘代币的难度。

如何创建链?

基于来自当前块的所有数据(包括签名),生成hash并将其包括在新生成的块的头中。此时此新块将成为当前块并开始注册交易。

很惊人!是不是?

案例分析

我选择了一个非常常见的用例,为使其易于理解,只留下了智能合约逻辑和技术细节的实现。

企业对企业——B2B

  • 零售商(retailer)从制造商(manufacturer)处订购货物。制造商检查库存数量,收集产品,包装,准备和运输。零售商和制造商有可信赖的商业关系。
  • 货物(shipment)由制造商要求的快递公司(courier)发货,他们也有可信赖的商业关系。
  • 零售商(retailer)和快递(courier)之间可信赖的商业关系(relationship)是可传递的(transitive),因为为制造商提供了共同的关系。
  • 值得信赖(trusted)的商业关系(relationship)非常重要,因为传统市场需要这种关系。从零售商到制造商的付款是在收到货物后几天发生的。并且,从发货人到快递员的付款在交货确认后几天发生。如果没有信任,他们就不会互相信任,也不会做出交易。这并不会促进最佳价格,服务和产品的竞争。

概括

最精细的商业交易由三部分组成:买方(buyer),货物(goods)和卖方(seller)。最基本的过程是转移货物的所有权以换取现金,从卖方到买方。你怎么看待这件事?

我们可以将此模型称为:从卖家购买商品所有权(buy-goods-ownership-from-seller)或简写为bogos

购买-所有权-商品-卖方图表模型

让我展示一些例子,然后翻译成bogos模型。

  • B2C——商品:John想要一部新的智能手机,他去了当地的市场并挑选了最好的智能手机并用他的信用卡付款。在这个例子中,“John”是买方buyer,“smartphone”是商品goods ,“local mart”是卖方seller。在John支付之前,本地市场拥有智能手机,付款后所有权转移给他。
  • B2C——服务:Maria很饿,她去了妈妈的意大利面并订购了很多意大利面条。厨师接受她的订单细节,准备菜肴,服务员为此服务。当Maria满意时,她付账并回家。在这个例子中,“Maria”是买家buyer,“dish”是商品goods,“Mama’s Pasta”是卖家seller。支付后,“菜”的所有权从“Mama’s Pasta”转移到“Maria”。
  • C2C——货物:Joseph在卖他的车。几周后,Berta想要从他那里买车。他们完成交易,Berta支付了有价值的价值,而Joseph将所有权转让给了她。 在这种情况下,“Berta”是买方buyer,“car”是货物goods而“Joseph”是卖方seller。支付后,所有权转移到“Berta”。
  • B2B——商品:Jong,买家buyer,是一家电子产品经销商,有一家商店,他从卖家北京公司seller订购商品goods。当货物准备好运输时,它们被打包,一名叫海外的快递员将包裹运给Jong。当他收到货物和发票时,将执行付款。

智能合约解决方案

正如我们在案例研究部分所看到的,参与者之间的信任是传统业务的主要关注点。这个概念证明的目标是使用以太坊区块链网络上的智能合约建立一种无信任的方式在参与者之间进行交易。

带智能解决方案的序列图

为了定义一系列交易,外部交互和支付,我提出了案例研究的新流程。

  • 制造商(Manufacturer)专门为零售商(Retailer)的帐户部署智能合约。
  • 零售商(Retailer)在(Manufacturer)的智能合约中订购产品X,其数量等于N.通过所谓的订单发送活动,制造商(Manufacturer)可以接收订单数据并对其进行处理。
  • 制造商(Manufacturer)寻找Courier智能合约的最佳运费。
  • 制造商(Manufacturer)发送订单价格,零售商(Retailer)通过发送的称为价格的事件收到订单价格。
  • 制造商(Manufacturer)发送装运价格,零售商(Retailer)通过发送的称为价格的事件接收此价格。
  • 零售商(Retailer)执行总额的安全支付:订单价格+装运价格。这些代币进入智能合约账户并等到那里直到交货。
  • 制造商(Manufacturer)发送包含交货日期和一些其他数据的发票。零售商(Retailer)通过发送的称为发票的事件接收发票数据。
  • Courier在将订单交付给零售商(Retailer)后 ,标记了智能合约上的订单。快递员可以是机器人,也可以是无人机。想想我!今天我们有很多可能性。
  • 智能合约为订单支付制造商的费用。
  • 智能合约向快递公司(Courier)支付为了发货。

好的,足够的理论,让我们看看如何写代码!

开发工具

为了加速我们的发展,有一个很好的选择叫做Truffle Framework。这个框架有很多东西可以帮助我们在以太坊编程语言Solidity中开发智能合约。

要快速查看Solidity,我建议你访问以下网站:http://solidity.readthedocs.io/en/develop/solidity-by-example.html

Truffle

Truffle是一个用于编译,测试和部署用Solidity编写的智能合约到以太坊区块链的工具。要使用它,我们需要nodejs。然后,检查已安装node tools的版本。

如果你的计算机中没有nodejs,请按照这些说明操作 。

1
2
3
4
5
$ node -v 
v6.11.5

$ npm -v
3.10.10

使用以下命令全局安装Truffle。

1
$ sudo npm install -g truffle

检查Truffle的版本输入truffle version

1
2
3
$ truffle version
Truffle v4.0.5 (core: 4.0.5)
Solidity v0.4.18 (solc-js)

ganache

全局安装ganache CLI以在localhost上运行私有以太坊区块链网络。

1
$ sudo npm install -g ganache-cli

然后,尝试在终端中输入ganache-cli。你必须在localhost上看到类似于以下内容的8545端口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ ganache-cli
Ganache CLI v6.0.3 (ganache-core: 2.0.2)
Available Accounts
==================
(0) 0x8baae15bf75ffdb6fcde77ecc4e2aa8063ad820c
(1) 0x1f6c6fa7aceb8124e9db0bd283dbe99489cd7b80
(2) 0x85e1e869e57004618481539c1ee8b2a55195892b
(3) 0x05dd0af1306a4537ca25e651f97df23c68d9b2d7
(4) 0x84a9964a2a9d8136498b26f27311c1ecd244733a
(5) 0x79e21b3f20eca854fa6ca822a8550b1fbdda3c30
...
HD Wallet
==================
Mnemonic: stereo pistol pulp advance same transfer eight deal unhappy charge attitude lock
Base HD Path: m/44'/60'/0'/0/{account_index}
Listening on localhost:8545

开始之后,我们有十个账户(或钱包或地址),每个账户余额为100.00ETH,还有一个完整的工作和私人区块链,可以玩,试错,用不完的以太币,做我们想做的一切,直到获得稳定的代码。

你想要一个更直观的方式来看看发生的事情,然后安装Ganache而不是ganache-cli。这个工具可以完成ganache-cli所做的工作,加上一个非常酷的GUI可以使用鼠标点击。

这些工具,ganache-cli和Ganache GUI在关机后不能维护状态,它们需要我们在每次重启时重新部署智能合约。

MyEtherWallet是一个对初学者来说很有趣的GUI,它比Ganache GUI更直观,因为我们可以在下拉列表中选择要调用的函数。它对于演示和截屏也非常有用。

MyEtherWallet只是与以太坊区块链交互的附加工具。我们必须先运行ganache-cli或Ganache GUI。在此处下载包,解压缩并在你喜欢的浏览器中打开index.html文件,并添加指向正在运行的区块链的自定义节点。

设置

通过本文,我不会假装展示如何成为Solidity程序员,但如果你想要启动免费的项目,请按以下步骤操作。

1
2
3
4
5
6
7
8
9
10
11
$ mkdir my-contract
$ cd my-contract
$ truffle init
Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet!
Commands:
Compile: truffle compile
Migrate: truffle migrate
Test contracts: truffle test

要有效地部署合约,我们必须在migrations目录中创建迁移文件。下面我向你展示负责部署Deal.sol合同的2_deploy_contract.js文件的内容。通过这种方法,我们可以将参数传递给合约构造函数以及许多其他可能性。

1
2
3
4
5
“use strict”;
var Deal = artifacts.require(“./Deal.sol”);
module.exports = function(deployer, network, accounts){
deployer.deploy(Deal, accounts[1]);
};

创建一个工作目录。以下命令将在你的主目录中创建区块链目录。

1
2
$ mkdir -p ~/blockchain
$ cd ~/blockchain

来吧看看代码。将源代码从https://github.com/fabiojose/ethereum-ex克隆到~/blockchain目录中。

1
2
$ git clone https://github.com/fabiojose/ethereum-ex.git
$ cd ethereum-ex

安装依赖项。

1
$ npm install

一个vanilla Truffle项目不需要npm安装,但如果我们想要更多的库,只需创建一个package.json文件并将依赖项放在那里。

构建和部署

要执行Truffle命令,我们需要访问我们的私有区块链。为此,编辑truffle.js文件,添加以下行。

1
2
3
4
5
6
7
8
9
module.exports = {
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*"
}
}
};

默认情况下,Ganache GUI在端口号7545上绑定。如果你选择它而不是ganache-cli,请更改为此端口。在Solidity中,我们需要编译.sol文件。为此,我们只需在项目目录中键入以下命令即可:

1
2
3
$ truffle compile
Compiling ./contracts/Deal.sol...
Writing artifacts to ./build/contracts

要部署我们编译的.sol文件,我们必须使用migrate命令。此命令将在truffle.js文件中配置的网络中部署智能合约。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ truffle migrate
Using network 'development'.
Running migration: 1_initial_migration.js
Deploying Migrations...
... 0xa74ff1912d2a53a3d77d2678e9fc617f9baa838a46e57a4182d1da6ff4a0cc4f
Migrations: 0xd86037f19f3adac9bdf3331298b3e9709baabb2e
Saving successful migration to network...
... 0x221758e993424fa81581100e2cdd278ed45f9c84820f3ced69362813e409a098
Saving artifacts...
Running migration: 2_deploy_contracts.js
Deploying Deal...
... 0x16f5149e71dd77f8891278e824c9d6e477f7408253fbc2f36560da4aa2a7c6f0
Deal: 0x3c7396d30e70b4deec5b33582b59766249b6ea83
Saving successful migration to network...
... 0x0631419bcf68146a50f524b1d6735f62fca5a825858e57458d4f8cf45e0e70aa
Saving artifacts...

要更好地了解migration,请阅读:http://truffleframework.com/docs/getting_started/migrations

测试

单元测试?:是的!我们可以通过智能合约进行单元测试。毕竟,一个简单的错误可能导致我们丢失所有代币。

在幕后我们有Mocha和Chai,主要区别在于使用关键字contract代替describe创建测试场景。

要执行测试,只需在项目目录中输入以下命令即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ truffle test
Using network 'development'.
Contract: Deal
✓ should the seller account owns the contract (72ms)
✓ should the second account was the buyer (72ms)
✓ should first order was number 1 (154ms)
✓ should the shipment price was set (189ms)
✓ should the order's price was set (169ms)
✓ should the safe pay was correct (218ms)
✓ should the contract's balance was correct after the safepay (186ms)
✓ should the first invoice was number 1 (177ms)
✓ should the invoice 1 it is for order 1 (190ms)
✓ should the courier was correct (186ms)
✓ should the contract's balance was correct after the delivery (268ms)
11 passing (2s)

可以像在本文中那样在JavaScript中实现测试,并在Solidity中进行测试。你可以在此处获得有关测试的更多详细信息:http://truffleframework.com/docs/getting_started/testing

编码

为了实施解决方案,我应用了泛化并使用这些实体:买方(buyer),卖方(seller),货物(goods),订单(order),发票(invoice)和称为Deal的智能合约。你可以通过克隆源代码来查看具体实现。

卖方为每个想要与之进行交易的买方部署一个智能合约,即交易实例。为此,我们需要一个带有一个参数的构造函数constructor:Buyer帐户地址。

1
2
3
4
5
6
7
/// The smart contract’s constructor 智能合约的构造函数 
function Deal(address _buyerAddr) public payable {

/// The seller is the contract’s owner 卖方是合约的所有者
owner = msg.sender;
buyerAddr = _buyerAddr;
}

请注意,与许多语言一样,Solidity的构造函数具有相同的类名,或同名的合约。

1
2
3
contract Deal {
/// ...
}

要将参数传递给构造函数,我们使用位于migrations/2_deploy_contracts.js的部署文件来执行此操作,这是我们调用truffle compiletruffle test时由migrations/2_deploy_contracts.js使用的.js文件。

下面我们有migration/2_deploy_contract.js的内容。在第3行,我们需要为智能合约加载我们的Solidity实现。在第6行,我们使用由Truffle注入的部署实例来执行Deal的部署。而deploy()函数的第二个参数将传递给第一个构造函数参数。在这种情况下,我们从ganache提供的帐户数组中传递第二个帐户。

1
2
3
4
5
6
7
1. “use strict”;
2.
3. var Deal = artifacts.require(“./Deal.sol”);
4.
5. module.exports = function(deployer, network, accounts){
6. deployer.deploy(Deal, accounts[1]);
7. };

要发送商品订单,我们有sendOrder功能。它是改变合约状态的函数中无用的返回数据,因为它们启动将异步处理(或挖掘)的交易。只是查询合同状态的函数可以返回数据。

1
2
3
4
5
6
7
/// The function to send purchase orders 发送采购订单的功能
/// requires fee 需要费用
/// Payable functions returns just the transaction object, with no custom field. 应付款函数只返回交易对象,没有自定义字段。
/// To get field values listen to OrderSent event. 要获取字段值,请监听OrderSent事件。
function sendOrder(string goods, uint quantity) payable public {
/// ...
}

要获取订单号,在执行sendOrder之后我们必须监听事件。在这种方法的情况下,我们必须使用以下签名来监听OrderSent

1
2
/// Event triggered for every new order 为每个新订单触发事件
event OrderSent(address buyer, string goods, uint quantity, uint orderno);

实际上,对于每个更改合同状态的函数,都会触发事件以获取新的数据状态。对于序列图中的每个阶段,我们都有一个执行它的方法:sendPricesendSafepaysendInvoicedelivery。零售商是买方,制造商是卖方。

完整的代码被推送到我的Github:https://github.com/fabiojose/ethereum-ex

克隆它,玩得开心!

最后的话

现在是时候体验智能合约的功能,试图解决现实世界的问题。去吧,试试看,让我知道!我们可以分享我们的实验。

关于模式

在这一点上,我们应该关注一些模式。我注意到这两个与部署方法有关。

  • 部署一次,多次使用:这个工作就像一个应用程序,因为我们部署了一个智能合约版本并多次使用直到销毁它。这是本文使用的方法。
  • 一次部署,一次使用:在这种方法中,我们部署了一个智能合约的版本,一次性使用它,我们需要一个非常具体的目标并在最后销毁。

参考

  • http://solidity.readthedocs.io/en/develop/contracts.html
  • http://solidity.readthedocs.io/en/develop/solidity-by-example.html
  • https://vomtom.at/solidity-send-vs-transfer/
  • https://zupzup.org/smart-contract-solidity/
  • http://truffleframework.com/docs/getting_started/javascript-tests

======================================================================

分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程:

  • 以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。
  • 以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
  • java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
  • python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
  • php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。
  • C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。
  • EOS教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。
  • java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
  • php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。
  • tendermint区块链开发详解,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。

汇智网原创翻译,转载请标明出处。这里是原文如何通过构建智能合约来销售商品