以太坊中比mapping更便宜的存储方案:事件日志?

logs.jpg

在我的前一篇文章中《以太坊 + IPFS 数据存储可行方案》 提到以太坊中以mapping存储的方式,为了节约gas,可以先将内容存在IPFS上,再存入mapping中。但今天看到一篇文章《智能合约事件应该这么用!》 有提到:mapping存储并不是最优方案,合约事件才是!

1
2
3
4
5
6
7
8
9
pragma solidity ^0.5.10;

contract DocumentRegistry {
event Registered(uint256 hash, address sender);

function register(uint256 hash) public {
emit Registered(hash, msg.sender);
}
}

看了一下案例,大体明白它的意思。就是说:任何触发的事件其实已经存入区块链了! 如果你只是想把数据存入区块链中,用事件的方式就可以解决,而无需用mapping存储!这样可以更节约gas! 具体对比数据:日志每个字节花费8个Gas,而合约存储(mapping)是每32个字节20,000个Gas!

嗯,但是又有新的问题:如何遍历读取事件日志呢?因为在合约中是没有办法读取到的,只能遍历区块去获取?what,这又是什么鬼?好吧,文章只是讲了前半段,至于如何读取区块是什么也没谈啊。我只能留着这个大问号去google!

问题解决留待下回分解!


This page is synchronized from the post: ‘以太坊中比mapping更便宜的存储方案:事件日志?’

以太坊 + IPFS 数据存储可行方案

ethipfs.jpg

画个图来表示下这个可行方案。以区块链来实现数据存储很明显会遇到数据过大的问题,这时IPFS可以派上用场。以太坊 + IPFS 这对组合其实经常被人提起,也算是区块链存储的可行方案了。

存数据

文章、图片、视频等内容先上传到IPFS网络,生成哈希值。将哈希值、内容的标题和关键词以mapping的形式存入以太坊。这三个mapping以相同的id关联,也就是说哈希值、内容的标题和关键词对应同一个id。

查询数据

查询数据可没有写好的方法供你使用,都得自己实现!我总结一下,大约是四步:

  1. 读取以太坊网络中所有的标题和关键词建立索引。这步有点像是字典前面的查询页。
  2. 以标题和关键词查出id。
  3. 以id查出内容的哈希值。
  4. 以内容的哈希值从IPFS中查出内容。

我想,这大概是比较好的办法吧,如果还有更好的,请多多建议!


This page is synchronized from the post: ‘以太坊 + IPFS 数据存储可行方案’

把文章存入以太坊网络是什么体验? EtherJiang来了!

etherjiang.jpg

https://etherjiang.github.io

疫情期间闭关修炼,把智能合约学了一遍,现在也总算是出了点小小的成绩:做出了一个基本能用的demo。这个小应用是改自SteemJiang, 把文章试着存入以太坊网络。既然都是区块链网络,道理应该基本一致。

在开发中就是开头入门比较难,很多概念不太懂,后来就比较轻松了,原理都差不多。所以,你在Steem上构建社交网络,和在以太坊上构建社交网络,道理都一样,都是使用区块链作数据库。

对于新手朋友,简单地说明一下EtherJiang的用法:

metamask2.jpg

第一,必须安装MetaMask!它是身份认证。
然后切换到Ropsten测试网络,去它的水管里申请点测试币来体验。毕竟真让大家花钱可能不太乐意。

metamask3.jpg

申请点测试币

login.jpg

第二,登录。打开网站(https://etherjiang.github.io),和MetaMask关联,设定呢称即可。

post.jpg

第三,编辑发布。这步想必大家比较熟悉了,使用Markdown语法书写,然后发布。

post2.jpg

发布时需要发费gas。点确认即可。这步可能有点慢,毕竟以太坊网络是出奇地慢!好了,等待完后就可以在首页看到你的文章啰!


This page is synchronized from the post: ‘把文章存入以太坊网络是什么体验? EtherJiang来了!’

ERC20代币合约 / 学习智能合约#5

智能合约

ERC20代币想必大家不陌生了,在以太坊上有数以千计的ERC20代币!本着学以致用的目的,自己也发个币装一把。

先上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
pragma solidity >=0.4.22 <0.7.0;

abstract contract ERC20Interface {
string public name;
string public symbol;
uint8 public decimals;
uint public totalSupply;


function transfer(address _to, uint256 _value) public virtual returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) public virtual returns (bool success);

function approve(address _spender, uint256 _value) public virtual returns (bool success);
function allowance(address _owner, address _spender) public virtual view returns (uint256 remaining);

event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);

}


contract ERC20 is ERC20Interface {
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) allowed;

constructor() public {
name = "Lemool";
symbol = "LEM";
decimals = 0;
totalSupply = 10000000;
balanceOf[msg.sender] = totalSupply;
}


function transfer(address _to, uint256 _value) public override returns (bool success) {
require(_to != address(0));
require(balanceOf[msg.sender] >= _value);
require(balanceOf[ _to] + _value >= balanceOf[ _to]);


balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;

emit Transfer(msg.sender, _to, _value);

return true;
}


function transferFrom(address _from, address _to, uint256 _value) public override returns (bool success) {
require(_to != address(0));
require(allowed[_from][msg.sender] >= _value);
require(balanceOf[_from] >= _value);
require(balanceOf[ _to] + _value >= balanceOf[ _to]);

balanceOf[_from] -= _value;
balanceOf[_to] += _value;

allowed[_from][msg.sender] -= _value;

emit Transfer(msg.sender, _to, _value);
return true;
}

function approve(address _spender, uint256 _value) public override returns (bool success) {
allowed[msg.sender][_spender] = _value;

emit Approval(msg.sender, _spender, _value);
return true;
}

function allowance(address _owner, address _spender) public override view returns (uint256 remaining) {
return allowed[_owner][_spender];
}

}

ERC20是有标准接口的,其实都很简单,就是几个参数和几个转帐的方法!想当年很多项目就是靠着这几行代码卷钱无数,现在想来会不会有点后悔呢。

在上面转帐的方法还是自己实现了一下,其实还有一种更简单和安全的方法:OpenZeppelin。只有少数几行代码就可以实现ERC20代币合约!

用前先安装一下:npm install @openzeppelin/contracts

1
2
3
4
5
6
7
8
9
10
pragma solidity >=0.4.22 <0.7.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";

contract TutorialToken is ERC20, ERC20Detailed {
constructor() ERC20Detailed("Lemool", "LEM", 0) public {
_mint(msg.sender, 10000000);
}
}

短短五六行代码就全搞定了,想想是不是很牛啊!感兴趣的朋友可以一试!


This page is synchronized from the post: ‘ERC20代币合约 / 学习智能合约#5’

简单代币合约 / 学习智能合约#4

智能合约

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
pragma solidity >=0.4.22 <0.7.0;

contract SimpleToken{
mapping(address => uint256) public balanceOf;
uint id;
constructor() public{
balanceOf[msg.sender] = 1000000;
}

function transfer(address _to, uint256 _value) public{
require(balanceOf[msg.sender] >= _value);
require(balanceOf[_to] + _value >= balanceOf[_to]);
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
}
}

把帐本信息存入一个mapping(映射)中,实现简单的转帐功能!代币想发多少有多少!


This page is synchronized from the post: ‘简单代币合约 / 学习智能合约#4’

天天大主播

zhubo.jpg

因为今年疫情的原因,都是改为了线上课程!我这读书人也要来玩转大主播啊!

还好,自己有些视频制作的基础在,拍片、裁片、字幕、合成,一气呵成!

直接录屏相对简单些,要有场景的话就复杂很多了。因为涉及景深,虚化,光线等问题,是要有专业级别才行!虽然我也有两把刷子,但也架不住时间有限,条件有限,能制作出来就是万幸了!


This page is synchronized from the post: ‘天天大主播’

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×