浅谈区块链DAPP学习

bluishfish 2022-04-06 12:43:29 阅读数:544

学习 区块 DApp 浅谈

f1ee83a8c17f90f3b31b689ab8065665.gif

前言

最近元宇宙火起来了,也一直在和朋友们聊,那什么是元宇宙(VR虚拟现实,现实世界的数字孪生体),然后就有聊到了web3.0,现实的讲元宇宙和web3.0都还是些模糊的感念,但是却都有了一些现实的技术解决方案,今天我不讲元宇宙(其实互联网本身就是无处不在的元宇宙。

我不讲是因为VR技术我不太懂,不过现在国内傻瓜化工具已经很多了thingjs,优诺科技都有不错产品,国外就不说了),今天我要聊聊web3.0一个未来人人可以拥有的互联网;简单的说web1.0是个只读网络(代表网易),web2.0是读写网络(代表微博微信)。

前两代网络都是中心化网络难以保证网络用户的信息权利也就是内容确权很难,web3.0能确保你的所有权。好吧,怎么确保所有权呢,其实就是区块链,元宇宙其实也避不开这个问题,所有未来网络貌似都需要区块链,不过现阶段区块链无论主链还是侧链都慢,要写那么多区块确权现阶段技术还是慢这个还是现实。

b39bd4ea0129deda6cba266cc1084c38.png

为什么要学习web3.0

公司(公:数人的财产;司:运转的意思)。现代社会在发展,公司与公司的经济生产合作,人与人的经济生产合作越来越复杂,尤其互联网下的各类合作越来越多,如何确认这数人或许多人的财产在一个或多个经济生产活动中的价值是互联网需要解决的问题。疫情居家办公,自由职业者,新的社会生产关系的需要在不停的催生web3.0和元宇宙的完善。

学习web3.0需要掌握哪些技术

Solidity 智能合约 编写语言

Solidity语言是一种面向合约的高级编程语言,用于在以太坊区块链网络上实现智能合约。它的开发工具Remix,推荐用它的在线编辑器[https://remix.ethereum.org],在线编辑器与matemask可以无缝对接,区块链智能合约必须能和智能钱包结合。

truffle

是一个基于以太坊虚拟机(EVM)的本地化智能合约开发环境,测试框架和上链工具。

geth

geth可以搭建一个完整的以太坊节点,这里不做过多介绍,因为开发用本地内存虚拟Ganache就够了。

Ganache

Ganache可以快速启动个人以太坊区块链,并可以使用它来运行测试,执行命令、检查状态,同时控制链条的运行方式。

node js

我介绍的web3.0的技术方案都是基于npm安装的,包括truffle,Ganache都基于npm 安装。下面的文章默认大家都了解node js知识。

开始上代码

便携solidity 投票代码

db7289d24040bcebb5af47d086782df8.png

以下是一个有关投票的简单合约

pragma solidity ^0.4.0;
contract Voting{
//投票列表
bytes32[] public candidateList;
//对应的票数
mapping(bytes32=>uint8) public votesReceived;
//构造投票列表
constructor(bytes32[] memory candidateListName) public{
candidateList = candidateListName;
}
//判断投票信息是否在待投票列表
function valiCandidate(bytes32 candidateName) internal view returns(bool)
{
for(uint8 i=0;i〈candidateList.length;i++)
{
if (candidateName==candidateList[i])
{
return true;
}
}
return false;
}
//对投票人增加投票
function voteForCandidate(bytes32 candidateName) public{
require(valiCandidate(candidateName));
votesReceived[candidateName] = votesReceived[candidateName] + 1;
}
function totalVotesFor(bytes32 candidateName) view public returns(uint8){
require(valiCandidate(candidateName));
//返回票数
return votesReceived[candidateName];
}
}

安装ganache

记得加-g 全局安装

npm install ganache-cli -g# 6.12
npm install ganache -g# 7.0
ganache-cli -d #启动它ganache
3a284c6e4485100e118dcea7f2a58a8c.png

安装truffle

记得加-g 全局安装

npm install truffle -g

初始化 truffle dapp框架(web3.0)

mkdir voting
cd voting
truffle unbox webpack

初始化好了的项目目录结构如下

e6d4963ed0d2dde32b8e50622aaa3cf4.pngAPP目录下是一个node js的web3.0项目;build下是合约编译后的目录用于调用;contracts是remix里编写的合约,migrations下是合约部署文件;test目录是测试文件;truffle-config.js是配置文件。

truffle-config.js配置

取消选中部分注释 127.0.0.1 port 8545 表示链接本地Ganache。b16a5689ccfa2307b3436a30a5c097cd.png

将voting.sol部署到项目contracts目录

1227cae95e07ec381456d48a52738d5d.png
truffle compile

项目默认合约放在此目录下:执行一下命令(truffle compile),进行编译,编译完成在build/contracts下会多出一个Voting.json文件

在migrations目录下新建3_deploy_contracts.js文件

const Voting = artifacts.require("Voting");
//0x4100000000000000000000000000000000000000000000000000000000000000 代表 A
//0x4200000000000000000000000000000000000000000000000000000000000000 代表 B
module.exports = function(deployer) {
//初始化合约 第二是投标列表参数
deployer.deploy(Voting, ["0x4100000000000000000000000000000000000000000000000000000000000000","0x4200000000000000000000000000000000000000000000000000000000000000"]);
};

执行命令:truffle migrate //部署合约

truffle migrate

d2afb41d564a0a546da720b8941832a8.pngcontract address是合约的地址 account是部署账户的地址。

app目录下代码实现及运行

在app/src/下有voting.js 和voting.html两个文件:

voting.js 代码:

import Web3 from "web3";
import votingArtifact from "../../build/contracts/Voting.json";
const aInBytes32 ="0x4100000000000000000000000000000000000000000000000000000000000000";
const bInBytes32 ="0x4200000000000000000000000000000000000000000000000000000000000000";
const App = {
web3: null,
account: null,
meta: null,
start: async function() {
const { web3 } = this;
try {
const networkId = await web3.eth.net.getId();
const deployedNetwork = votingArtifact.networks[networkId];
this.voting = new web3.eth.Contract(
votingArtifact.abi,
deployedNetwork.address,
);
const accounts = await web3.eth.getAccounts();
this.account = accounts[0];
this.ready();
this.refreshBalance();
} catch (error) {
console.error("Could not connect to contract or chain.");
}
},
ready:async function(){
try{
this.refresh("Alice",aInBytes32);
this.refresh("Bob",bInBytes32);
}catch(err){
console.log(err)
}
},
refresh:async function(id,nameBytes32){
const {totalVotesFor} = this.voting.methods;
const tickets = await totalVotesFor(nameBytes32).call();
const el = document.getElementById(id);
el.innerHTML = tickets.toString();
},
voteForCandidate:async function(){
try{
const {voteForCandidate} = this.voting.methods;
const condidateName = document.getElementById("candidate").value;
console.log(condidateName)
if (condidateName == "Alice")
{
await voteForCandidate(aInBytes32).send({from:this.account});
this.refresh("Alice",aInBytes32);
}
else{
await voteForCandidate(bInBytes32).send({from:this.account});
this.refresh("Bob",bInBytes32);
}
}catch(err){
console.log(err)
}
}
};
window.App = App;
window.addEventListener("load", function() {
if (window.ethereum) {
// use MetaMask's provider
App.web3 = new Web3(window.ethereum);
window.ethereum.enable(); // get permission to access accounts
} else {
console.warn(
"No web3 detected. Falling back to http://127.0.0.1:8545. You should remove this fallback when you deploy live",
);
// fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
App.web3 = new Web3(
new Web3.providers.HttpProvider("http://127.0.0.1:8545"),
);
}
App.start();
});

第一行导入web3;第二行导入投票合约;三四行是两个投票项

import Web3 from "web3";
import votingArtifact from "../../build/contracts/Voting.json";
const aInBytes32 ="0x4100000000000000000000000000000000000000000000000000000000000000";
const bInBytes32 ="0x4200000000000000000000000000000000000000000000000000000000000000";

这段代码获得区块链的网络和钱包账号,初始化voting合约

start: async function() {
const { web3 } = this;
try {
// get contract instance
const networkId = await web3.eth.net.getId();
const deployedNetwork = votingArtifact.networks[networkId];
this.voting = new web3.eth.Contract(
votingArtifact.abi,
deployedNetwork.address,
);
// get accounts
const accounts = await web3.eth.getAccounts();
this.account = accounts[0];
this.ready();
this.refreshBalance();
} catch (error) {
console.error("Could not connect to contract or chain.");
}
},
});

投票方法

voteForCandidate:async function(){
try{
const {voteForCandidate} = this.voting.methods;
const condidateName = document.getElementById("candidate").value;
console.log(condidateName)
if (condidateName == "Alice")
{
await voteForCandidate(aInBytes32).send({from:this.account});
this.refresh("Alice",aInBytes32);
}
else{
await voteForCandidate(bInBytes32).send({from:this.account});
this.refresh("Bob",bInBytes32);
}
}catch(err){
console.log(err)
}
}

voting.html代码

<!DOCTYPE html>
<html>
<head>
<title>My Voting Dapp</title>
</head>
<style>
input {
display: block;
margin-bottom: 12px;
}
</style>
<body>
<h1>Voting Dapp</h1>
<p>Alice <strong id="Alice">loading...</strong> tickets</p>
<p>Bob <strong id="Bob">loading...</strong> tickets</p>
<input type="text" id="candidate" />
<button onclick="App.voteForCandidate()">Send</button>
<script src="voting.js"></script>
</body>
</html>

初始化DAPP项目并启动

npm install
npm run dev

dafbead345261405879bf248f0a6f168.png访问http://localhost:8080/voting.html100f406ada124d85594060eaa271518d.png输入Alice--》点击send(matemask钱包会告诉你需要花些eth币确认就好,我这个是本地的模拟币随便花)228c13bf34160fb5b3088817cc1e9fc4.png确认完会发现Alice投票数变成2了,这个可是区块链上的无法串改哦。

96fdad6293833a08d8ef3e573cbccb23.png

总结

在合约solidity语言中storage是需要花gas的会永久存在区块中 ,我们就是用了这个特性写了投票合约,这样的投票久不会被串改,还有一种memory是存在内存的不用花费gas。这样我们可以发觉web3.0或者说dapp就是把那些需要信用保证的内容通过智能合约保存在区块链中,起到去中心化的信任作用,也保证了归属权的保证。用这种方式web3.0为之前读写网络又提供了确权的功能及所属权,为元宇宙打下基础的基石。

版权声明:本文为[bluishfish]所创,转载请带上原文链接,感谢。 https://blog.csdn.net/weixin_47479625/article/details/123911587