heyuan 发布的文章 - 六币之门
首页
视频教程
网站导航
活动日历
关于我们
用户投稿
推荐
新闻动态
搜 索
1
融资周报 | 公开融资事件11起;加密技术公司Toposware完成500万美元融资,Polygon联创参投
112 阅读
2
六币日报 | 九只比特币ETF在6天内积累了9.5万枚BTC;贝莱德决定停止推出XRP现货ETF计划
76 阅读
3
融资周报 | 公开融资事件27起;L1区块链Monad Labs完成2.25亿美元融资,Paradigm领投
74 阅读
4
六币日报 | 美国SEC再次推迟对灰度以太坊期货ETF做出决定;Do Kwon已出黑山监狱等待引渡
72 阅读
5
【ETH钱包开发06】查询某个地址的交易记录
55 阅读
新闻动态
每日快报
一周精选
融资情况
项目投研
自治组织
数字藏品
去中心化应用
去中心化游戏
去中心化社交
去中心化金融
区块链交易所
科普知识
小白入门
用户手册
开发文档
行业报告
技术前沿
登录
搜 索
标签搜索
新闻
日报
元歌Eden
累计撰写
1,087
篇文章
累计收到
0
条评论
首页
栏目
新闻动态
每日快报
一周精选
融资情况
项目投研
自治组织
数字藏品
去中心化应用
去中心化游戏
去中心化社交
去中心化金融
区块链交易所
科普知识
小白入门
用户手册
开发文档
行业报告
技术前沿
页面
视频教程
网站导航
活动日历
关于我们
用户投稿
推荐
新闻动态
用户登录
登录
找到
1087
篇与
heyuan
相关的结果
2023-03-24
[译] 使用 Web3 和 Vue.js 来创建你的第一个以太坊 dAPP(第二部分)
原文地址:Create your first Ethereum dAPP with Web3 and Vue.JS (Part 2) 原文作者:Alt Street 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:L9m 校对者:allen, 玉儿 使用 Web3 和 Vue.js 来创建你的第一个以太坊 dAPP(第一部分) 使用 Web3 和 Vue.js 来创建你的第一个以太坊 dAPP(第二部分) 使用 Web3 和 Vue.js 来创建你的第一个以太坊 dAPP(第三部分) 点此在 LinkedIn 分享本文 »欢迎回到这个很棒的系列教程的第二部分,在个教程中我们要亲身实践,创建我们的第一个去中心化应用(decentralized application)。在第二部分中,我们将介绍 VueJS 和 VueX 的核心概念以及 web3js 与 metamask 的交互。如果你错过了第一部分,你可以在下面找到,也请在 Twitter 上关注我们。进入正题:VueJSVueJS 是一个用于构建用户界面的 JavaScript 框架。初看起来,它类似传统的 mustache(译者注:原文为 moustache)模板,但其实 Vue 在后面做了很多工作。<div id=”app”> } </div> var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } }) 复制代码这是一个很基本的 Vue 应用的结构。数据对象中的 message 属性会被渲染到屏幕上 id 为「app」的元素中,当我们改变 message 时,屏幕上的值也会实时更新。你可以去这个 jsfiddle 上查看(开启自动运行):jsfiddle.net/tn1mfxwr/2/。VueJS 的另一个重要特征是组件。组件是小的、可复用的并且可嵌套的小段代码。本质上,一个 Web 应用是由较小组件组成的组件树构成的。当我们着手编写我们前端应用时,我们会愈加清楚。这个页面示例是由组件构成的。页面由三个组件组成的,其中的两个有子组件。状态的整合: Vuex我们使用 Vuex 管理应用的状态。类似于 Redux,Vuex 实现了一个对于我们应用数据「单一数据源」的容器。Vuex 允许我们使用一种可预见的方法操作和提供应用程序使用的数据。它工作的方式是非常直观的。当组件需要数据进行渲染时,它会触发(dispatch)一个 action 获取所需的数据。Action 中获取数据的 API 调用是异步的。一旦取得数据,action 会将数据提交(commit)给一个变化(mutation)。然后,Mutation 会使得我们容器(store)的状态发生改变(alert the state)。当组件使用的容器中的数据改变时,它会重新进行渲染。Vuex 的状态管理模式。在我们继续之前...在第一部分中,我们已经通过 vue-cli 生成了一个 Vue 应用,我们也安装了所需的依赖。如果你没有这样做的话,请查看上面第一部分的链接。如果你正确完成了各项的话,你的目录看起来应该是这样的:新生成的 vue 应用。小提示:如果你要从这里复制粘贴代码段的话,请在你的 .eslintignore 文件中添加 /src/,以免出现缩进错误。你可以在终端中输入 npm start 运行这个应用。首先我们需要清理它包含的这个默认的 Vue 应用。 注解:尽管只有一个路由,但是我们还是会使用 Vue Router,虽然我们并不需要,但是因为这个教程相当简单,我想将其保留会更好。 贴士:在你的 Atom 编辑器右下角中将 .vue 文件设置为 HTML 语法(高亮)现在处理这个刚生成的应用:在 app.vue 中删除 img 标签和 style 标签中的内容。 删除 components/HelloWorld.vue,创建两个名为 casino-dapp.vue(我们的主组件)和 hello-metamask.vue(将包含我们的 Metamask 数据)的两个新文件。 在我们的新 hello-metamask.vue 文件中粘贴下面的代码,它现在只显示了在一个 p 标签内的「hello」文本。 <template> <p>Hello</p> </template> <script>export default { name: 'hello-metamask' }</script> <style scoped> </style> 复制代码现在我们首先导入 hello-metamask 组件文件,通过导入文件将其加载到主组件 casino-app 中,然后在我们的 vue 实例中,引用它作为模板中一个标签。在 casino-dapp.vue 中粘贴这些代码: <template> <hello-metamask/> </template> <script>import HelloMetamask from '@/components/hello-metamask' export default { name: 'casino-dapp', components: { 'hello-metamask': HelloMetamask } }</script> <style scoped> </style> 复制代码现在如果你打开 router/index.js 你会看到 root 下只有一个路由,它现在仍指向我们已删除的 HelloWorld.vue 组件。我们需要将其指向我们主组件 casino-app.vue。 import Vue from 'vue' import Router from 'vue-router' import CasinoDapp from '@/components/casino-dapp' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'casino-dapp', component: CasinoDapp } ] }) 复制代码关于 Vue Router:你可以增加额外的路径并为其绑定组件,当你访问定义的路径时,在 App.vue 文件中的 router-view 标签中,对应的组件会被渲染,并进行显示。在 src 中创建一个名为 util 的新文件夹,在这个文件夹中创建另一个名为 constants 的新文件夹,并创建一个名为 networks.js 的文件,粘贴下面的代码。我们用 ID 来代替以太坊(Ethereum)网络名称显示,这样做会保持我们代码的整洁。 export const NETWORKS = { '1': 'Main Net', '2': 'Deprecated Morden test network', '3': 'Ropsten test network', '4': 'Rinkeby test network', '42': 'Kovan test network', '4447': 'Truffle Develop Network', '5777': 'Ganache Blockchain' } 复制代码最后的但同样重要的(实际上现在用不到)是,在 src 中创建一个名为 store 的新文件夹。我们将在下一节继续讨论。 如果你在终端中执行 npm start,并在浏览器中访问 localhost:8000,你应该可以看到「Hello」出现在屏幕上。如果是这样的话,就表示你准备好进入下一步了。设置我们的 Vuex 容器在这一节中,我们要设置我们的容器(store)。首先从在 store 目录(上一节的最后一部分)下创建两个文件开始:index.js 和 state.js;我们先从 state.js 开始,它是我们所检索的数据一个空白表示(Blank representation)。let state = { web3: { isInjected: false, web3Instance: null, networkId: null, coinbase: null, balance: null, error: null }, contractInstance: null } export default state 复制代码好了,现在我们要对 index.js 进行设置。我们会导入 Vuex 库并且告诉 VueJS 使用它。我们也会把 state 导入到我们的 store 文件中。import Vue from 'vue' import Vuex from 'vuex' import state from './state' Vue.use(Vuex) export const store = new Vuex.Store({ strict: true, state, mutations: , actions: }) 复制代码最后一步是编辑 main.js ,以包含我们的 store 文件:import Vue from 'vue' import App from './App' import router from './router' import from './store/' Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', router, store, components: , template: '<App/>' }) 复制代码干得好!因为这里有很多设置,(所以请)给你自己一点鼓励。现在已经准备好通过 web3 API 获取我们 Metamask 的数据,并使其在我们的应用发挥作用了。该来点真的了!入门 Web3 和 Metamask就像前面提到的,为了让 Vue 应用能获取到数据,我们需要触发(dispatch)一个 action 执行异步的 API 调用。我们会使用 promise 将几个方法链式调用,并将这些代码提取(封装)到文件 util/getWeb3.js 中。粘贴以下的代码,其中包含了一些有助你遵循的注释。我们会在代码块下面对它进行解析:import Web3 from 'web3' /* * 1. Check for injected web3 (mist/metamask) * 2. If metamask/mist create a new web3 instance and pass on result * 3. Get networkId - Now we can check the user is connected to the right network to use our dApp * 4. Get user account from metamask * 5. Get user balance */ let getWeb3 = new Promise(function (resolve, reject) { // Check for injected web3 (mist/metamask) var web3js = window.web3 if (typeof web3js !== 'undefined') { var web3 = new Web3(web3js.currentProvider) resolve({ injectedWeb3: web3.isConnected(), web3 () { return web3 } }) } else { // web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')) GANACHE FALLBACK reject(new Error('Unable to connect to Metamask')) } }) .then(result => { return new Promise(function (resolve, reject) { // Retrieve network ID result.web3().version.getNetwork((err, networkId) => { if (err) { // If we can't find a networkId keep result the same and reject the promise reject(new Error('Unable to retrieve network ID')) } else { // Assign the networkId property to our result and resolve promise result = Object.assign(, result, ) resolve(result) } }) }) }) .then(result => { return new Promise(function (resolve, reject) { // Retrieve coinbase result.web3().eth.getCoinbase((err, coinbase) => { if (err) { reject(new Error('Unable to retrieve coinbase')) } else { result = Object.assign(, result, ) resolve(result) } }) }) }) .then(result => { return new Promise(function (resolve, reject) { // Retrieve balance for coinbase result.web3().eth.getBalance(result.coinbase, (err, balance) => { if (err) { reject(new Error('Unable to retrieve balance for address: ' + result.coinbase)) } else { result = Object.assign(, result, ) resolve(result) } }) }) }) export default getWeb3 复制代码第一步要注意的是我们使用 promise 链接了我们的回调方法,如果你不太熟悉 promise 的话,请参考此链接。下面我们要检查用户是否有 Metamask(或 Mist)运行。Metamask 注入 web3 本身的实例,所以我们要检查 window.web3(注入的实例)是否有定义。如果是否的话,我们会用 Metamask 作为当前提供者(currentProvider)创建一个 web3 的实例,这样一来,实例就不依赖于注入对象的版本。我们把新创建的实例传递给接下来的 promise,在那里我们做几个 API 调用:web3.version.getNetwork() 将返回我们连接的网络 ID。 web3.eth.coinbase() 返回我们节点挖矿的地址,当使用 Metamask 时,它应该会是已选择的账户。 web3.eth.getBalance(<address>) 返回作为参数传入的该地址的余额。 还记得我们说过 Vuex 容器中的 action 需要异步地进行 API 调用吗?我们在这里将其联系起来,然后再从组件中将其触发。在 store/index.js 中,我们会导入 getWeb3.js 文件,调用它,然后将其(结果)commit 给一个 mutation,并让其(状态)保留在容器中。在你的 import 声明中增加:import getWeb3 from '../util/getWeb3' 复制代码然后在(store 内部)的 action 对象中调用 getWeb3 并 commit 其结果。我们会添加一些 console.log 在我们的逻辑中,这样做是希望让 dispatch-action-commit-mutation-statechange 流程更加清楚,有助于我们理解整个执行的步骤。registerWeb3 () { console.log('registerWeb3 Action being executed') getWeb3.then(result => { console.log('committing result to registerWeb3Instance mutation') commit('registerWeb3Instance', result) }).catch(e => { console.log('error in action registerWeb3', e) }) } 复制代码现在我们要创建我们的 mutation,它会将数据存储为容器中的状态。通过访问第二个参数,我们可以访问我们 commit 到 mutation 中的数据。在 mutations 对象中增加下面的方法:registerWeb3Instance (state, payload) { console.log('registerWeb3instance Mutation being executed', payload) let result = payload let web3Copy = state.web3 web3Copy.coinbase = result.coinbase web3Copy.networkId = result.networkId web3Copy.balance = parseInt(result.balance, 10) web3Copy.isInjected = result.injectedWeb3 web3Copy.web3Instance = result.web3 state.web3 = web3Copy } 复制代码很棒!现在剩下要做的是在我们的组件中触发(dispatch)一个 action,取得数据并在我们的应用中进行呈现。为了触发(dispatch)action,我们将会用到 Vue 的生命周期钩子。在我们的例子中,我们要在它创建之前触发(dispatch)action。在 components/casino-dapp.vue 中的 name 属性下增加以下方法:export default { name: 'casino-dapp', beforeCreate () { console.log('registerWeb3 Action dispatched from casino-dapp.vue') this.$store.dispatch('registerWeb3') }, components: { 'hello-metamask': HelloMetamask } } 复制代码很好!现在我们要渲染 hello-metamask 组件的数据,我们账户的所有数据都将在此组件中进行呈现。从容器(store)中获得数据,我们需要在计算属性中增加一个 getter 方法。然后,我们就可以在模板中使用大括号来引用数据了。<template> <div class='metamask-info'> <p>Metamask: }</p> <p>Network: }</p> <p>Account: }</p> <p>Balance: }</p> </div> </template> <script>export default { name: 'hello-metamask', computed: { web3 () { return this.$store.state.web3 } } }</script> <style scoped></style> 复制代码太棒啦!现在一切都应该完成了。在你的终端(terminal)中通过 npm start 启动这个项目,并访问 localhost:8080。现在,我们可以看到 Metamask 的数据。当我们打开控制台,应该可以看到 console.log 输出的 —— 在 Vuex 那段中的描述状态管理模式信息。说真的,如果你走到了这一步并且一切正常,那么你真的很棒!这是本系列教程目前为止,难度最大的一部分。在下一部分中,我们将学到如何轮询 Metamask(如:账户切换)的变化,并将在第一部分描述智能合约与我们的应用相连接。以防万一你出现错误,在这个 Github 仓库 的 hello-metamask 分支上有此部分完整的代码不要错过本系列的最后一部分!如果你喜欢本教程的话,请让我们知道,谢谢你坚持读到最后。ETH — 0x6d31cb338b5590adafec46462a1b095ebdc37d50想完成自己的想法吗?我们提供以太坊(Ethereum)概念验证和开发众募。Alt Street —— 区块链顾问:区块链概念验证和代币销售等等... altstreet.io 掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。
2023年03月24日
9 阅读
0 评论
0 点赞
2023-03-24
以太坊智能合约开发试水-开发一个自己的智能合约需要准备什么
准备工作-必备知识智能合约智能合约就是存在于以太坊区块链上的计算机程序(用 Solidity 语言编写),仅在由用户(或其他合约)发出的交易触发时执行(区块链存储的是状态,智能合约是区块链用于状态转换的方式),无法由发起者直接调用 一旦智能合约发布到以太坊,只要以太坊存在,它就会一直在线并运行,就连创作者也无法让它离线 智能合约并不只是一个可以自动执行的计算机程序,也是一个系统参与者,它可以对接收到的信息进行回应,可以接收和储存价值,也可以向外发送信息和价值 智能合约就像一个可以被信任的人,可以临时保存资产,总是按照事先的规则执行操作-可以理解成自动贩卖机 适合场景SoliditySolidity是一种智能合约高级语言,运行在Ethereum虚拟机(EVM)之上 Solidity是以太坊的首选语言 语法接近于Javascript,是一种面向对象的语言 使用Solidity,您可以创建用于投票、众筹、盲拍卖和多签名钱包等用途的合同(程序) 文档 HardhatHardhat是一个编译、部署、测试和调试以太坊应用的开发环境。它可以帮助开发人员管理和自动化构建智能合约和dApps过程中固有的重复性任务,并围绕这一工作流程轻松引入更多功能。 Hardhat内置了Hardhat网络,这是一个专为开发设计的本地以太坊网络。主要功能有Solidity调试,跟踪调用堆栈、console.log()和交易失败时的明确错误信息提示等。 文档 QuickNode高性能以太坊节点服务 使用专用节点以获得更好的区块链访问性能 快捷发布以太坊区块链(帮助广播发布合约和交易,以便快速被挖矿者捕获到,一旦被捕获到,发布和交易行为就会作为合法交易广播到区块链上,链上的所有节点就会就会对自己的数据进行更新) QuikNode支持几乎所有流行的以太坊测试网,这使得开发者在测试网的选择上有了充分的灵活性,可以在自己喜欢的测试网上进行Dapp的测试 官网 Metamask 加密钱包购买、存储、发送和交换代币 MetaMask可作为浏览器扩展程序和移动应用程序提供,为您提供密钥库、安全登录、令牌钱包和令牌交换——管理您的数字资产所需的一切。 保存个人数据 MetaMask在您的设备上生成密码和密钥,因此只有您可以访问您的帐户和数据。您可以选择要分享的内容和保密的内容。 探索区块链应用 MetaMask提供了连接到基于区块链的应用程序的最简单但最安全的方式。在新的去中心化网络上进行交互时,您始终处于控制之中。 相当于你的个人账户 chrome插件示例: GoerliethGoerli 是最活跃的以太坊测试网之一 获取测试以太币,以便进行开发测试 水龙头:goerli-faucet.pk910.de/ ,只要输入你的钱包地址,就可以开始挂机挖矿,可以增加工作数量以提高效率 Gas以太坊的Gas(中文直译:气体),是以太坊上衡量工作量的计量单位,类似于我们每小时用了多少度电用千瓦/小时。 以太坊上产生的各种交易、存储等活动都是需要Gas来推动的,Gas好比是燃料,推动以太坊虚拟机(EVM)来工作。 在Goerli上挖到的测试币就是用来支付这个gas费用,同时智能合约里面也能发起转账 区块交易记录查询官网 查看所有区块和交易(不管是谁的) 查看指定合约发布状态 查看交易记录和交易内容(无需登录,只需要输入地址hash则可以查看) goerli.etherscan.io/address/[合约… 开发过程本地开发智能合约步骤使用hardhat创建项目, 参考文档 创建xxx.sol文件,使用solidity语法进行合约编写,例如我的合约名称为:WavePortal // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.17; import "hardhat/console.sol"; contract WavePortal { //... // 具体实现可参考solidy文档 } 复制代码编写测试js: scripts/run.js(通过hardhat提供的全局对象hre来获取ether环境数据:测试或实际环境) const waveFactory = await hre.ethers.getContractFactory("WavePortal") // 发布,并充值0.001(可用于后续合约内部交易) const waveContract = await waveFactory.deploy({ value: hre.ethers.utils.parseEther("0.001") }) 复制代码运行测试程序 npx hardhat run scripts/run.js 复制代码发布智能合约步骤编写发布js:scripts/deploy.js // 调用智能合约的方法更新任意参数也视为“交易-transaction” // 发布一个智能合约也属于-transaction const mainD = async () => { const [deployer] = await hre.ethers.getSigners() const accountBalance = await deployer.getBalance() console.log('Deploying contracts with account:', deployer.address) console.log('Account balance:', accountBalance.toString()) const waveFactory = await hre.ethers.getContractFactory("WavePortal") const waveContract = await waveFactory.deploy({ value: hre.ethers.utils.parseEther("0.001"), }) await waveContract.deployed() console.log('WavePortal address:', waveContract.address) } const runMainD = async () => { try { await mainD(); process.exit(0) } catch (err) { console.log(err); process.exit(1) } } runMainD(); 复制代码执行发布命令-以下为发布到goerli网络 npx hardhat run scripts/deploy.js --network goerli 复制代码提交修改后的智能合约代码到区块链,尽管只是修改一部分,都相当于是新的一次发布,原来保存在区块内的数据会丢失; 前端需要更新新的区块地址和abi文件(执行发布后生成的json文件) 前端调用连接加密钱包metamask MetaMask会向网页注入一个全局的API变量window.ethereum,可以从用户接入的区块链读取数据,并且能够提示用户签名要提交的交易 通过window.ethereum能获取用户签名的加密钱包账户 引入发布合约生成的ABI json文件 安装引用ethers.js 依赖包 根据合约地址和ABI文件实例化合约,以便调用合约方法 连接到以太坊节点,读取账户地址数据等 一个小demo如果你已经有metamask账户,欢迎访问我的测试Dapp应用: waveportal-starter-project.caryiwong.repl.co/连接钱包,切换到goerli测试网络后就可以跟我打招呼啦~
2023年03月24日
5 阅读
0 评论
0 点赞
2023-03-24
如何实现一个简单的以太坊 - 蒋金洋 | Jeth 第二期
编者按:本文系秘猿科技区块链工程师蒋金洋讲师,在由掘金技术社区主办,以太坊社区基金会、以太坊爱好者与 ConsenSys 协办的《开发者的以太坊入门指南 | Jeth 第二期 - 杭州场》 活动上的分享整理。Jeth 围绕以太坊技术开发主题的系列线下活动。每期 Jeth 会邀请以太坊开发领域的优秀技术团队和工程师在线下分享技术干货。旨在为开发者提供线下技术交流互动机会,帮助开发者成长。本场分享视频回放链接(B 站)我先自我介绍一下,我是秘猿科技区块链工程师蒋金洋,这次的主题是如何实现一个简单的以太坊。我之前从事 Web 开发和云计算的开发,对第一次接触以太坊是在两年,作为技术人员不仅是看重以太坊这种货币,我们更要看重区块链的这一代技术。说实话,加密猫最火的时候我是比较失望,以太坊写的是去中心化的全世界的计算机,但居然有人用来做猫。随着我深入对以太坊的了解和学习,我看到很多 APP 一步一步去履行以太坊的使命,深度使用去中心化的功能,比如 the DAO 这个项目。DAO 这个项目虽然因为智能合约有漏洞挂掉了,但它因为使用智能合约的 DAO 这一功能让我眼前一亮。DAO 是指去中心化的自治组织。在 the DAO 这个项目上面,我用我的私钥可以给这个项目转一笔资金,获得相应的投票权,投票权来表决我的资金投在哪个地方。虽然 DAO 最后也挂掉了,但是它相较于加密猫在技术上跨出了一大步。去中心化交易所去中心化交易所大家或多或少听说过,但是去中心化的交易所原理是用智能合约保证其安全性。我们假设现在有一个设计良好、使用了智能合约的去中心化交易所,理论上面我的资产放在交易所里面交易,可能这个交易所有一部分的中心化的服务帮助我匹配交易的过程,但是这笔钱永远是通过我的私钥以及以太坊智能合约来控制的,这样资产永远在我的手中。智能合约和 Web 3.0通过这些事例来说,我感觉智能合约和以太坊 Web3.0 的概念名副其实。刚才提及的两个例子中有两个特点:资金和机制公开透明,比如 the DAO 这个项目; 给使用者更多权力 我身为一个使用者我可以百分之百控制自己的资金的权利,这在当下的 Web 中心化服务里面是一种奢望。 Web → BlockChainBlockchain区块链是一个 Web3.0 的平台,现在参与到当中,就是在创建下一代开发者使用的平台,这个对于我来说是最大的吸引力。秘猿科技最早听到秘猿科技时,给我留下了深刻的印象,因为这家公司的项目和主要产品都在 GitHub 上开源,包括钱包和区块链浏览器,而且 License 相当得开放。这也意味着我要是使用他们的代码,我不需要支付费用,为了了解这家公司如何运营,我决定加入进去看看。还有一点,我听说秘猿科技他们是被称之为少林寺,我当时在想为什么是少林寺,是不是公司里面没有妹子,都是男的。这个误会很快被揭开:少林寺的寓意就是“天下武功出少林”,秘猿也确实在当下的区块链生态中培养出了一大帮像峨眉、武当这样的门派,为区块链事业做出了自己的贡献。面试:Web → 区块链我去秘猿科技参与面试,当时比较尴尬我是 Web 出身,对区块链中的区块、共识等概念只是有所耳闻但了解不深,所以面试的时候心里没有底。当时我应聘的是 Web 开发的职位,好在我们有试用期,我给自己打气,要是能在试用期内把知识都研究透就可以转到 BlockChain 的开发方向这是我列举 Web 开发和 BlockChain 开发在技术栈上的区别,右侧的也就是你要进入 Web3.0 平台需要的技术。区块链工程师的秘密在我面试的时候,当时的老板提醒我,秘猿科技的区块链工程师之前也是很多都是搞 Web 出身的,有个秘密可以让你很快学会区块链的开发,这个秘密叫做撸链。撸链就是自己做一条区块链出来,我们很多同事做过一些比特币和以太坊的实现,在这个过程中相当于你从 Web 技术栈,走了一条很长的路转到 BlockChain 技术栈,这时你已经做出来区块链了,不必再问自己有没有资格去做区块链。撸链的权衡撸链的好处在可以成为以太坊的专家,我当初下决心要撸链时,选择了第二代区块链的以太坊而没选择第一代的比特币。这个是我们公司的撸链文化,最早开始撸链的是我们的 CEO。我当时问他着手搞以太坊有没有什么价值和意义,因为需要两三个月的时间成本且不一定能搞出来。他告诉我说,撸以太坊是困难模式,他鼓舞我说,如果你能撸出来一块以太坊,代表着你对区块链的理解能达到我们公司 TOP 5的水平。我的考虑是去做还是不去做。老板后来又在公司内说到,谁能实现以太坊,工资翻倍。本着帮助领导分忧,帮助老板花钱的理念,我决定还是要去做以太坊。我刚开始做到现在过了三个月的时间,三个月时间不到给大家展示一下做成什么样子。以下是我的 GitHub 项目主页(https://github.com/ciri-ethereum/ciri)截图:难度曲线在做的过程当中,我有这样的一个难度曲线,一开始是以太坊的 Wiki,在 Wiki 上你可以找到所有的以太坊资料的入口。你要实现以太坊核心的话,需要查阅由以太坊的技术合伙人撰写的以太坊黄皮书,书中你可以看到大量的公式,这个时候你感觉非常非常困难。众所周知,以太坊是一个仍在开发的项目,它没有固定的规范,可以理解为以太坊的规范每天都在变,很多情况下你需要调试你的客户端,这样你才能理解当前的实现。黄皮书是一个巨大的门槛,当你把黄皮书看完后,理解现有的以太坊的实现,剩下的事情还有很多,但难度降低了不少,剩下的花时间即可完成。以太坊测试项目设定链的初始状态我介绍一下这个叫做 以太坊 tests 的 GitHub 项目,刚才我们提到以太坊的规范一直在变动,这个项目是唯一一个在追踪以太坊规范变动的项目。大家看一下项目的目录,频繁更新的也就3-4个目录左右,里面集中几千条测试。下面我简单介绍一些测试:BlockChain 的测试,主要涉及以太坊区块的验证、还有一些比如 POW 的其他测试,这是在测试共识算法。 RLP 测试,RLP 是以太坊的一个编码库,类似于 json 但是以太坊选择 LP 作为格式。 下面给大家展示 tests 这个库怎么运行的,如何确保实现的就是以太坊。设定链的初始状态 它的原理很简单,一开始给我一个 json 格式文件,文件中是它的初始状态。右边图里就是它的格式了,有我们平时可以看到的钱包的地址;balance 是钱包的余额;code 为空的地址代表的是一个钱包,而不是一段合约,如果是合约的话他有一段代码;storage 是我们合约里存储的一些数据。下面这个地址就是真正的一条合约的地址。我会根据这段资料设定链的初始状态,把这一段资料塞进去。输入块数据 第二个部分它会提供一些输入。我举的这个例子是 BlockChain 的,块包括块头和一大堆的 Transaction,这时输入到测试中实现,这时它会根据里面的内容执行相应的合约。检验处理完块后的状态 转账和调用合约在以太坊里面都是以交易的形式呈现的这个过程当中就是相当于一个计算机的初始状态,这个状态要变化,我验证一下变化完的状态跟测试的时候状态是不是一致,如果是一致证明通过这个测试。这样的测试一共有8000多个,我的项目目前现在通过过了5000多个,还有很多以太坊 fork 的规则没有处理,所以剩下的测试应该还是比较容易通过的。其余成果我在 GitHub 上发布了用 Ruby 语言便携的 RLP 编码库,叫做 ciri-rlp。同时我们公司很多后台是用 Ruby 写得,同事用 ciri 库解决了加密问题。如何实现以太坊思考与建议关于以太坊的规范 开源项目如何吸引开发者的思考 如何了解以太坊的规范正如我前面所讲,以太坊目前没有完整的规范,尽管如此以太坊的规范是非常有用的:第一点,你想要实现一个客户端你一定要去了解这个东西;第二点,如果不实现客户端,你想要做以太坊相关的开发,比如说你可能去开发一个 imToken 这样的钱包、区块链的浏览器和其他以太坊周边的东西,你也需要了解以太坊的规范。有时你只是看了 Wiki 和文章整理上的规范,是不足以让你实现这个东西。我以 DevP2P 作为一个例子,它是以太坊的一个底层网络组件,它会以 P2P 的方式跟节点进行连接,与上层应用实现随意通信。我们从这三个地方可能找到寻找 DevP2P 的认证规范。第一个是 Wiki ,它相当于是一个以太坊所有资料的总入口,但在里面可能找不到特别详细的东西。幻灯片右侧截图是 Wiki 上 Libp2p 的介绍,它会告诉你 Libp2p 是什么东西。但这里只是告诉你是什么,没有详细告诉你如何实现。第二张图是 Devp2p 的协议,Libp2p 其实就是 Devp2p,但它没有将非常规范的方式告诉你,所以你只看协议是实现不了。黄皮书实质上是以太坊 EVM 的规范,它里面写的是 EVM 的东西,但网络部分的话在里面是无法找到的。除此之外你还可能找的就是 EIPs,它是一个由社区驱动的以太坊提升提案。如果你发现以太坊做得不好,我可以提升他,你可以先提交一个 EIP,如果官方觉得 EIP不错 会分配 EIP 的编号,社区里的其他成员在里面讨论这个东西,并最终实现这个提案。我们现在以太坊大部分的规范是放在这里,你一定要去找 EIP 的东西。可惜的是,在 EIP 里也没有对 Devp2p 非常详细的规范,这个时候使用从官方的客户端里面去看它的代码并且去调试。这里我们可以使用 Geth 来完成,我当时实现就是利用这个方法一段一段把 Geth 收到的数据一点一点打印出来。然后进行对比。开源项目如何吸引开发者接下来我想分享的是开源的项目如何吸引开发者。开源项目的关键:一堆人做这个项目可以决定这个项目能不能开始,如果想要持续下去,必须让更多人的力量投入到其中,包括以太坊也是如此。这是以太坊官方支持的客户端,py-EVM,另一个是我实现的,Ciri,这个时候我要考虑的是如何增加参与者,这需要各位的帮助。如果各位对实现以太坊感兴趣,想多了解以太坊的原理,最好的方式是自己去实现一下;第二个好的方式大家参与项目一起来做;还有一个就是大家如果不是想了解以太坊,可以帮忙给我的 ciri 项目点赞,这也是对开源项目的一种帮助。降低开发者参与门槛开源方式管理项目 我做的过程当中,我对比下来,我发现有很多东西还是缺乏的.在座的各位都是程序员,如果自己做项目的时候,自己根本不会去写文档,自己也不会考虑项目管理。这时如果想要别人参与到这个项目中,需要让他把你的源代码看一遍了。想到这一点的时候,我一开始就是在 GitHub 的 issue 里在管理这个项目。README 和 Roadmap 如果别人想要参与,可以看到我做了哪些东西,有的东西为什么没有做,现在这个工作进行到哪个地步,包括去写比较详细的 README 和 Roadmap 文档。方便开发者 Setup 我觉得已经超越了很多的开源项目,我做了一个 Docker 镜像给开发者用,如果你的电脑上有 Docker, 可以拿容器试一下是不是真的有五千多个测试可以通过,省去了安装依赖文件的烦恼。总结如果你了解以太坊的规范,或者你要更深入了解以太坊的实现和设计,记住有三个方式:黄皮书,WIKI,EIPs,进一步深入的话还需要用已有的客户端进行调试;第二个思考如何去参与开源项目,保括开源方式和管理项目,提供 readme 和 ROADMAP 文档;第三个是尽量方便开发者了解这个项目。联系方式: jjy@cryptape.com 我的博客: justjjy.com Ciri Ethereum: github.com/ciri-ethere… 我的微信: fweedm 这是我的联系方式,以及我们少林寺的招聘内推,有兴趣的同学留意一下。谢谢大家!
2023年03月24日
5 阅读
0 评论
0 点赞
2023-03-24
从以太坊Solidity概述以及合约示例开始学习区块链技术吧!
本文正在参加「金石计划 . 瓜分6万现金大奖」 Solidity语言简介solidity是一种静态类型的编程语言,用于开发在以太坊(Ethereum)上运行的智能合约。solidity被编译为可在以太坊虚拟机(EVM)上运行的字节码。以太坊虚拟机(EVM)是智能合约的运行环境。借由solidity,开发人员能够编写出运行在以太坊上的应用程序。当然,目前市面上不止一种智能合约,很多链都有自己的智能合约,他们基本上都是基于solidity衍生出来的。比如波场、sCrypt、币安链等等。solidity是一门专门被设计的 可在以太坊虚拟机上运行的语言。 以太坊简介以太坊(Ethereum)是一个开源的有智能合约功能的公共区块链平台。以太坊平台上面提供各种模块让用户来搭建应用,如果将搭建应用比作造房子,那么以太坊就提供了墙面、屋顶、地板等模块,用户只需像搭积木一样把房子搭起来,因此在以太坊上建立应用的成本和速度都大大改善。以太坊通过一套图灵完备的以太坊虚拟机语言(Ethereum Virtual Machinecode)来建立应用以太坊分层以太坊系统大致可以分为 3 层:应用层、区块链核心层、基础底层。以太坊客户端包含了区块链核心层及基础底层,不同的以太坊客户端通过点对点通信(p2p,peer to peer)通信网络,形成一个以太坊网络。 应用层是用户参与开发的部分,基于区块链网络运行的应用,也称为去中心化应用(DApp),我们在刚接触区块链的时候就可以从这一层出发,学习智能合约,然后使用web3.js和前端交互,就实现了一个简单的DAPP。 注:还有一些东西网上都很多,就不一一赘述了。 合约我们编写合约前需要掌握一些最基本的知识:合约文件的后缀名为.sol。一个solidity 文件可以包含任意数量的合约(contract)定义、import指令和pragma指令。我们也许会好奇,为什么当我们删除第一行注释掉代码的时候会警告,它算是一个许可证,SPDX 许可证列表是 SPDX 规范的一个组成部分,可以看一下这篇文章: 智能合约基础--语法基础 代码示例以及注释 pragma solidity ^0.6.0; //确定运行的版本号 contract SimpleStorage { //合约定义 uint storedData; //声明变量 function set(uint x) public { //set方法 storedData = x; //参数赋值 } function get() public view returns (uint) { //get方法 return storedData; //返回该变量 } } 复制代码注:若有错误,欢迎理性交流!,谢谢!
2023年03月24日
7 阅读
0 评论
0 点赞
2023-03-24
实战:以太坊 DApp 开发与构建 - 李明 | Jeth 第二期
编者按:本文系 ConsenSys 中国特约讲师李明,在由掘金技术社区主办,以太坊社区基金会、以太坊爱好者与 ConsenSys 协办的《开发者的以太坊入门指南 | Jeth 第二期 - 杭州场》 活动上的分享整理。Jeth 围绕以太坊技术开发主题的系列线下活动。每期 Jeth 会邀请以太坊开发领域的优秀技术团队和工程师在线下分享技术干货。旨在为开发者提供线下技术交流互动机会,帮助开发者成长。本场分享视频回放链接(B 站)大家下午好!我今天带来的分享是DApp的开发与实践。我们将用40分钟时间从头写一个DApp,学习以太坊智能合约开发。我将通过实践的方式给大家做一个展示,希望大家在短时间内可以从0到1快速地了解以太坊全栈开发的核心知识。首先自我介绍一下,我曾在微软亚研担任了四年半的软件工程师,之后在深圳多翼科技担任研发总监。我在13年的时候第一次比特币,并少量投资。14年是熊市,在发现不能赚钱以后,我开始做量化交易,在国内各个交易所之间做基于统计模型的搬砖套利,为市场提供流动性。15年区块链概念开始爆发,人们发现区块链不只是数字货币,还可以做非常多的应用。这种新的认知引发了我的思考,于是从16年开始我开始研究区块链的共识和智能合约的开发,在这个领域不断探索。今天的分享主要内容如下:从0到1构建一个以太坊DApp Solidity、Web前端语言 重要工具:Remix、Truffle、Ganache、Metamask 今天要讲的 DApp 非常有特点。第一,它是一个非常有用的 App,大家可以发现它可以用来洗碗、买菜、做家务。二是这个 DApp 虽然非常有用,但代码并不长,只有100行多一点,可以比较快速开发完成。最后,虽然这个 DApp 代码不长,但展示了 Solidity 语言的主要特性,甚至包含了一些大家需要注意的安全陷阱,所以希望大家通过这个 DApp 对 Solidity 编程有更多的了解。那今天要讲的 DApp 是什么呢?就是石头剪子布。这是我们平常经常玩的游戏。这个游戏的一个问题是,每个人出拳的速度不一样,我是属于比较笨的人,经常因为被别人看出想要出拳的手势而吃亏。这个问题怎么解决呢?生活中出现了一种非常有意思的方法,就是分歧终端机,出自《非诚勿扰》。它通过外壳把两人的手套起来,俩人出好拳以后同时打开盖子看结果,以避免作弊。网络版的分歧终端机?那这种问题在计算机系统或者是网络系统如何解决呢?这个问题确实有点难。假设我们通过服务器做这个事情,我们如何信任服务器?我们也无法保证服务器是否会作假。但是,这时候如果引入区块链,当我们要使用以太坊上的智能合约来开发这个系统,我们会发现它的一些特性是可以帮助我们解决这个问题的。这就是我们今天要讲的基于以太坊的石头剪子布 DApp。接下来进入 Live Coding 环节,我们将从0到1一起见证 DApp 诞生过程,用到的第一个工具就是 Remix,算得上是以太坊开发的瑞士军刀,它结合开发中的编辑、编译、部署和测试等等功能,我们先从这里开始。编辑注: Live Coding 环节无PPT,请参见 IT 大咖说视频回放(2:56:50——3:48:40),链接: http://www.itdks.com/eventlist/detail/240实战项目 Demo 链接(GitHub):github.com/washingweb/…
2023年03月24日
8 阅读
0 评论
0 点赞
2023-03-24
Solidity 简易教程
Solidity是以太坊的主要编程语言,它是一种静态类型的 JavaScript-esque 语言,是面向合约的、为实现智能合约而创建的高级编程语言,设计的目的是能在以太坊虚拟机(EVM)上运行。本文基于CryptoZombies,教程地址为:cryptozombies.io/zh/合约Solidity 的代码都包裹在合约里面. 一份合约就是以太应币应用的基本模块, 所有的变量和函数都属于一份合约, 它是你所有应用的起点.一份名为 HelloWorld 的空合约如下:contract HelloWorld { } 复制代码hello world首先看一个简单的智能合约。pragma solidity ^0.4.0; contract SimpleStorage { uint storedData; // 声明一个类型为 uint (256位无符号整数)的状态变量,叫做 storedData function set(uint x) public { storedData = x; // 状态变量可以直接访问,不需要使用 this. 或者 self. 这样的前缀 } function get() public view returns (uint) { return storedData; } } 复制代码所有的 Solidity 源码都必须冠以 "version pragma" — 标明 Solidity 编译器的版本. 以避免将来新的编译器可能破坏你的代码。例如: pragma solidity ^0.4.0; (当前 Solidity 的最新版本是 0.4.0).关键字 pragma 的含义是,一般来说,pragmas(编译指令)是告知编译器如何处理源代码的指令的(例如, pragma once )。Solidity中合约的含义就是一组代码(它的 函数 )和数据(它的 状态 ),它们位于以太坊区块链的一个特定地址上。该合约能完成的事情并不多:它能允许任何人在合约中存储一个单独的数字,并且这个数字可以被世界上任何人访问,且没有可行的办法阻止你发布这个数字。当然,任何人都可以再次调用 set ,传入不同的值,覆盖你的数字,但是这个数字仍会被存储在区块链的历史记录中。Solidity 语句以分号(;)结尾状态变量状态变量是被永久地保存在合约中。也就是说它们被写入以太币区块链中,想象成写入一个数据库。contract HelloWorld { // 这个无符号整数将会永久的被保存在区块链中 uint myUnsignedInteger = 100; } 复制代码在上面的例子中,定义 myUnsignedInteger 为 uint 类型,并赋值100。uint 无符号数据类型, 指其值不能是负数,对于有符号的整数存在名为 int 的数据类型。Solidity中, uint 实际上是 uint256代名词, 一个256位的无符号整数。程序有时需要对不同类型的数据进行操作,因为 Solidity 是静态类型语言,对不同类型的数据进行运算会抛出异常,比如:uint8 a = 5; uint b = 6; // 将会抛出错误,因为 a * b 返回 uint, 而不是 uint8: uint8 c = a * b; 复制代码a * b 返回类型是 uint, 但是当我们尝试用 uint8 类型接收时, 就会造成潜在的错误。这时,就需要显式的进行数据类型转换:// 我们需要将 b 转换为 uint8: uint8 c = a * uint8(b); 复制代码把它的数据类型转换为 uint8, 就可以了,编译器也不会出错。Solidity 支持多种数据类型,比如:string(字符串):字符串用于保存任意长度的 UTF-8 编码数据 fixedArray(静态数组):固定长度的数组 dynamicArray(动态数组):长度不固定,可以动态添加元素的数组 enum(枚举) mapping 等 数学运算在 Solidity 中,数学运算很直观明了,与其它程序设计语言相同:加法: x + y 减法: x - y, 乘法: x * y 除法: x / y 取模 / 求余: x % y (例如, 13 % 5 余 3, 因为13除以5,余3) 乘方: x ** y 结构体Solidity 提供了 结构体,用来表示更复杂的数据类型。struct Person { uint age; string name; } 复制代码结构体允许你生成一个更复杂的数据类型,它有多个属性。创建结构体方式为:// 创建一个新的Person: Person satoshi = Person(172, "Satoshi"); 复制代码数组Solidity 提供两种类型的数组:静态数组和动态数组。// 固定长度为2的静态数组: uint[2] fixedArray; // 固定长度为5的string类型的静态数组: string[5] stringArray; // 动态数组,长度不固定,可以动态添加元素: uint[] dynamicArray; 复制代码使用 push 函数向数组中添加值:fixedArray.push[123] fixedArray.push[234] // fixedArray 值为 [123, 234] 复制代码array.push() 在数组的 尾部 加入新元素 ,所以元素在数组中的顺序就是添加的顺序 array.push() 会返回数组的长度。Solidity 数组支持多种类型,比如结构体:struct Person { uint age; string name; } Person[] people; // dynamic Array, we can keep adding to it 复制代码结构体类型的数组添加值的方式为:people.push(Person(16, "Vitalik")); // 也可以使用下面的方式,推荐使用上述一行简洁的方式 Person satoshi = Person(172, "Satoshi"); people.push(satoshi); 复制代码公共数组也可以使用public定义公共数组,Solidity 会自动创建getter方法。语法如下:struct Person { uint age; string name; } Person[] public people; // dynamic Array, we can keep adding to it 复制代码公共数组支持其它的合约读取数据(但不能写入数据),所以这在合约中是一个有用的保存公共数据的模式。(有点像全局变量,所有合约共享同一个“内存空间“,厉害了!)函数Solidity 中,函数定义如下:function eatHamburgers(string _name, uint _amount) { } 复制代码Solidity 习惯上函数里的变量都是以(_)开头 (但不是硬性规定) 以区别全局变量。这是一个名为 eatHamburgers 的函数,它接受两个参数:一个 string类型的 和 一个 uint类型的。现在函数内部还是空的。函数调用如下:eatHamburgers("vitalik", 100); 复制代码私有/公共函数Solidity 函数分为私有函数和共有函数。Solidity 定义的函数的属性默认为公共。 这就意味着任何一方 (或其它合约) 都可以调用你合约里的函数。显然,不是什么时候都需要这样,而且这样的合约易于受到攻击。所以将自己的函数定义为私有是一个好的编程习惯,只有当你需要外部世界调用它时才将它设置为公共。可以把所有的函数都显式的声明 public和private来规避这个问题。定义私有函数比较简单,只需要在函数参数后添加 private关键字即可。示例如下:uint[] numbers; function _addToArray(uint _number) private { numbers.push(_number); } 复制代码这意味着只有我们合约中的其它函数才能够调用这个函数,给 numbers数组添加新成员。和函数的参数类似,私有函数的名字用(_)起始。注意:在智能合约中你所用的一切都是公开可见的,即便是局部变量和被标记成 private 的状态变量也是如此。返回值和其它语言一样,Solidity 函数也有返回值,示例如下:string greeting = "What's up dog"; function sayHello() public returns (string) { return greeting; } 复制代码返回值使用 returns关键字标注。(已经是非常奇怪的写法了。。)修饰符viewconstant 是 view 的别名string greeting = "What's up dog"; function sayHello() public returns (string) { return greeting; } 复制代码像 sayHello 函数这种实际上没有改变合约中数据内容的情况,可以把函数定义为view,这意味着此函数只读不修改数据。可以使用以下声明方式:function sayHello() public view returns (string) 复制代码可以将函数声明为 view 类型,这种情况下要保证不修改状态。下面的语句被认为是修改状态:修改状态变量。 产生事件。 创建其它合约。 使用 selfdestruct。 通过调用发送以太币。 调用任何没有标记为 view 或者 pure 的函数。 使用低级调用。 使用包含特定操作码的内联汇编。 purepure 比 view 更轻量,使用这个修饰符修饰的函数甚至都不会读取合约中的数据,例如:function _multiply(uint a, uint b) private pure returns (uint) 复制代码这个函数没有读取应用里的状态,它的返回值只和它输入的参数相关。Solidity 编辑器会给出提示,提醒你使用 pure/view修饰符。函数可以声明为 pure ,在这种情况下,承诺不读取或修改状态。除了上面解释的状态修改语句列表之外,以下被认为是从状态中读取:读取状态变量。 访问 this.balance 或者 <address>.balance。 访问 block,tx, msg 中任意成员 (除 msg.sig 和 msg.data 之外)。 调用任何未标记为 pure 的函数。 使用包含某些操作码的内联汇编。 payablepayable 关键字用来说明,这个函数可以接受以太币,如果没有这个关键字,函数会自动拒绝所有发送给它的以太币。事件事件 是合约和区块链通讯的一种机制。你的前端应用“监听”某些事件,并做出反应。例如:// 这里建立事件 event IntegersAdded(uint x, uint y, uint result); function add(uint _x, uint _y) public { uint result = _x + _y; //触发事件,通知app IntegersAdded(_x, _y, result); return result; } 复制代码用户界面(当然也包括服务器应用程序)可以监听区块链上正在发送的事件,而不会花费太多成本。一旦它被发出,监听该事件的listener都将收到通知。而所有的事件都包含了 from , to 和 amount 三个参数,可方便追踪事务。 为了监听这个事件,你可以使用如下代码(javascript 实现):var abi = /* abi 由编译器产生 */; var ClientReceipt = web3.eth.contract(abi); var clientReceipt = ClientReceipt.at("0x1234...ab67" /* 地址 */); var event = clientReceipt.IntegersAdded(); // 监视变化 event.watch(function(error, result){ // 结果包括对 `Deposit` 的调用参数在内的各种信息。 if (!error) console.log(result); }); // 或者通过回调立即开始观察 var event = clientReceipt.IntegersAdded(function(error, result) { if (!error) console.log(result); }); 复制代码代码示例下面是一个完整的代码示例:pragma solidity ^0.4.19; contract ZombieFactory { // 建立事件 event NewZombie(uint zombieId, string name, uint dna); uint dnaDigits = 16; // 定义状态变量 uint dnaModulus = 10 ** dnaDigits; struct Zombie { // 定义结构体 string name; uint dna; } Zombie[] public zombies; // 定义动态数组 // 创建私有函数,私有函数命名使用 _ 前缀 function _createZombie(string _name, uint _dna) private { // 函数参数命名 使用 _ 作为前缀 // arrays.push() 将元素加入到数组尾部,并且返回数组的长度 uint id = zombies.push(Zombie(_name, _dna)) - 1; // 触发事件 NewZombie(id, _name, _dna); } // view 为函数修饰符,表示此函数不需要更新或创建状态变量 // pure 表示函数不需要使用状态变量 function _generateRandomDna(string _str) private view returns (uint) { // 使用 keccak256 创建一个伪随机数 uint rand = uint(keccak256(_str)); return rand % dnaModulus; } function createRandomZombie(string _name) public { uint randDna = _generateRandomDna(_name); _createZombie(_name, randDna); } } 复制代码Ethereum 内部有一个散列函数keccak256,它用了SHA3版本。一个散列函数基本上就是把一个字符串转换为一个256位的16进制数字。 在智能合约中使用随机数很难保证节点不作弊, 这是因为智能合约中的随机数一般要依赖计算节点的本地时间得到, 而本地时间是可以被恶意节点伪造的,因此这种方法并不安全。 通行的做法是采用 链外off-chain 的第三方服务,比如 Oraclize 来获取随机数)。参考链接Solidity 文档: https://solidity-cn.readthedocs.io/zh/develop/index.html cryptozombie-lessons: https://cryptozombies.io/zh/ 最后,感谢女朋友支持和包容,比❤️也可以在公号输入以下关键字获取历史文章:公号&小程序 | 设计模式 | 并发&协程
2023年03月24日
4 阅读
0 评论
0 点赞
2023-03-24
[译] EthList:众包维护的以太坊阅读清单
原文地址:EthList: The Crowdsourced Ethereum Reading List 原文作者:Scanate 译文出自:掘金翻译计划 — 区块链分舵 本文永久链接:github.com/xitu/blockc… 译者:StellaBauhinia 校对者:davelet 发现了一个很棒的资源吗?提交一个 Pull 请求就可以加入进来了!贡献者:Phil Kurtland (Scanate), Robert Hackett (Fortune Magazine), Jorge Izquierdo and Luis Cuende (Aragon), Jake Brukhman (CoinFund), Maksim Balashevich (Santiment), Michal Brazewicz (Status), Nate Rush, Krishna Aradhi, Justin Poirier, Griff Green (Giveth.io), Eeks, Anonymous在推特上发布这个清单吧!简介 入门 生态 思想碎片 交易 编程 法务 简介以太坊的简单解释区块链视频演示 —— 区块链技术的视效演示 精简区块链命令行学习实操 虚拟货币演示 —— 数字货币技术的视效演示 区块链视频演示 以太坊,世界的计算机(视频) Vitalik Buterin 解释以太坊(视频) Joseph Lubin 对于构建去中心化应用的访谈(视频) BBC 解释以太坊(视频) 以太坊上的技术难题(视频) 什么是以太坊? 向小白解释:什么是以太坊? 以太坊:与比特币不同的、可以取代 Uber 服务的数字货币 以太坊简介:互联网共治 以太坊初学者入门 什么是以太坊? 足以用来理解以太坊的比特币知识 以太坊:比特币加上一切 以太坊和智能合约简介:一个可编程的区块链 一个非常不技术的以太坊解释(又名 另一个以太坊的解释) 以太坊特么到底是个啥? 以太坊的初学者超级指南 区块链:关于信任的新技术 给 Web 开发者的以太坊知识 以太坊的深入解释以太坊到底是怎么运作的? 最简可行的区块链 大众版白皮书,技术版 黄皮书 (PDF) 在区块链的内容中编程:以太坊 以太坊:平台概况 Vitalik Buterin 在第一次以太坊开发者大会上对以太坊的介绍(视频) 立于区块之外思考 理解以太坊报告(PDF) 非常深入的以太坊阅读清单 剖析以太坊中的庞氏骗局:身份认证,分析和影响 全面的以太坊学习大纲,附带总结和资源分享 历史文章:这个 22 岁的程序员能基于突破比特币吗? 这个怪异的天才造就了以太坊 我想要更多深入的细节!以太坊年度开发者大会(Devcon):Devcon 0(柏林,2014)座谈会和视频 Devcon 1(伦敦,2015)座谈会和视频 Devcon 2(上海,2016)座谈会和视频 Devcon 3(坎昆,2017)座谈会和视频 协议更新列表和硬分叉:(译者注:下文中的 EIP 为 Ethereum Improvement Proposal 的缩写,意思是以太坊优化计划,按数字分了不同的计划或者提议。)Olympic(奥运)预发布版本(测试网,Chain #0 —— 5 月 9 日,2015) 发布博客 **Frontier(前沿)**公开发布版本(包含以太坊创始区块,Chain #1 —— 7 月 30 日,2015) 发布博客 Homestead(家园)(区块编号至 1,150,000 —— 3 月 14 日,2016) 发布博客,EIP-2,EIP-7,EIP-8 DAO 分叉(区块编号至 1,920,000 —— 7 月 20 日,2016) 发布博客,分叉的反对者停留在了 r/EthereumClassic(译者注:即 ETC,该分叉由著名的 DAO 攻击引致。) DoS 分叉(区块编号至 2,463,000 —— 10 月 18 日,2016) 发布博客,EIP-150,EIP-158 伪龙分叉(区块编号至 2,675,000 —— 11 月 22 日,2016)(译者注:该分叉为 DoS 分叉的后续,应对的是相似的问题。) 发布博客,EIP-155,EIP-160,EIP-161,EIP-170 Metropolis(大都会) 会按计划于 2017 年 6 月(to be announced) 工作进行中:EIP-86,EIP-96,EIP-98,EIP-100,EIP-140,EIP-196,EIP-197,EIP-198 (译者注:现在已经是 2018 年中了,这个版本还没发布,不知道 2019 年能不能出,更别提楼下的最终版了。) Serenity(宁静)等待宣布(2018) 为什么以太坊计划迁移到权益证明模式?? 公开的测试网列表:Olympic,预发布的公开测试网,网络编号为 0(已被 Morden 取代) Morden,基于 Fontier 的公开测试网,网络编号为 2(已被 Ropsten 取代) Ropsten,基于 Homestead 的公开测试网,网络编号为 3(刚刚重启) ConsenSys,工作量证明模式的 公开测试网 Kovan, 权威证明模式的 公开测试网 Rinkeby,权威证明模式,等待宣布(EIP-225) (译者注:现在已经是 2018 年中了,ConsenSys 已经凉了,Rinkeby 上线也很久了。) 测试币水龙头:Ropsten 水龙头 Rinkeby 水龙头 杂文收集:了解区块链 一些区块链读物 如何投资以太坊上基于以太币的代币 以太坊的阅读指南 为潜在的 Dapp 开发者准备的以太坊阅读清单 Reddit 的以太坊指南 以太坊 Wiki 以太坊 Stack Exchange(问答平台) 区块链、代币和数字货币的终极版阅读清单 区块链相关学术文章的初创列表 研究以太坊第二层的扩容解决思路的实际方案:状态通道、Plasma、和 Truebit 权益证明(PoS)权益证明模式的问与答 Casper FFG 文章(译者注:FFG 为 Friendly Finality Gadget 的缩写,直译为 “友好的终结工具”。) Alpha 版 Casper FFG 测试网操作指南 Plasma(译者注:一种以太坊外链解决方案)Plasma 白皮书 最简可行版的 Plasma Sharding(分片技术)Sharding 研究 Sharding 在 GitHub 上的代码库 入门使用以太坊的简易指南 以太坊 —— 入门 —— 澳大利亚版 这些词好难啊:以太坊/密码界中常用词的定义 在以太坊中快速起航 安全:给数字货币交易者的线上安全指南 给你的数字生活的私人安全指引 是时候实现了:请停止依赖第三方来保护你和你的资产,你可以对你的安全负责。 傻瓜式的离线存储方式 生态区块链行业中的女性 我可以在哪里加入以太坊社区? Dapp 的状况 (译者注:Dapp 为 decentralized application 的缩写,意思是 “去中心化应用”。) 以太坊商业目录 其他的会议,工作坊,meetups(线下聚会)或者教程:欧洲以太坊开发会议(EDCON) 伦敦以太坊(meetup) 柏林以太坊(meetup) 以太坊核心开发者会议(电话会议) 用 Solidity 构建以太坊 DApp(教程) 时讯以太坊一周新闻 Dapp 日报 Consensys 媒体 The Etherian(译者注:下面这三个链接好像都失效了) The Control HEAT Crypto Roundup YouTube 频道Crypt0's News —— 每日视频博客 Ameer Rosic Decypher 媒体 Ivan 聊技术 新闻币报 ETH 新闻 CoinDesk(Digital Currency Group 所有,它的报道对竞品数字货币有利益偏向。) 以太坊区块浏览器Etherscan Ethplorer 小币浏览器 钱包My Ether Wallet(译者注:很多时候会以 MEW 缩写来表示,所以不予翻译。) MetaMask 谷歌浏览器插件 跨平台 Jaxx 钱包 Mist 钱包 Parity 钱包 Harmony 钱包 imToken Toshi 钱包 + Dapp 浏览器 + 通讯器 Trust 钱包 + Dapp 浏览器 硬件钱包Ledger Nano S Trezor ICOs (原始代币发售):ICO 日历 Smith and Crown TokenMarket imToken ICO Dapp 思想碎片为什么去中心化很重要 去中心化技术的发展可能性 以太坊的风险 以太坊社区的价值 以太坊生态的成长 协议组成的互联网:构建在区块链上的超连接未来 货币、区块链和社交的扩容 去中心化应用或协议数字通证和即将到来的协议创新时代 开放协议的黄金纪元 关于通证的思考 “胖”式协议 去中心化组织可以解决世界上最难的问题 区块链上的通证和去中心化商业模式的黎明 Dapp 的商业案例 —— 把去中心化当成一种策略 “去中心化”给 DApp 带来了一个短而新的黑暗时代 数字经济的难点 众筹区块链证券式代币适用的法律框架简介 区块链投资和新型资产给现代风投机构带来的问题 如何使用代币在区块链上募资 探索连续性代币模型:面向百万级网络的价值 不给糖就捣蛋?区块链上数字资产的投资 向代币(和代币众筹)说不 数字货币和区块链初创公司是如何使传统风头机构转向的? 如何衡量一个(项目的)原始代币发售价值(ICO)? ICO 2.0 —— 什么是理想的 ICO? 搭上区块链投资的快车:全球零售化投资的未来 交易在 Pipsology 学院中学习外汇交易(非常适用于数字货币交易) 范式转换:比特币和山寨币市场的技术分析,市场周期、结构和操纵的简介 数字货币市场资本状况 交易所去中心化交易所 (大部分基于以太坊资产)OasisDexEtherDeltaForkDeltaIdexCryptoDerivativesRadex0x Relayers:(译者注:去中心化交易所的市场平台)ParadexRadarRelayEthfinex编程在以太坊上创建并部署一个完全去中心化 DApp 的终极版由头到尾的指南 审计智能合约的终极指南 + Solidity 上的危险攻击 Dapp 全简介:我如何在以太坊上开始开发? 在以太坊上发行你自己的数字货币 不借用第三方从朋友处募资 在区块链上建立民主机制 只需十步就构建出你第一个 DApp 以太坊 DApp 开发(视频) 监测网络状态(镜像站)和 gas 费用市场状况 阅读技术文档 (Homestead 版本) 试试一些在以太坊上运行的 DApp 吧 学习 Solidity,以太坊智能合约语言 试试 Truffle 吧!一个智能合约开发框架 以太坊商业生态路径一览 在以太坊 Stack Exchange 上问问题吧 与以太坊开发者队伍、社区在线通话 发现你附近的以太坊 Meetup 在以太坊上开发智能合约的菜鸟全简介 我可以在哪里学习如何使用 Solidity 语言开发 DApp 呢? 学习在以太坊上编程 Windows 平台上以太坊、Solidity 和 Geth 的入门 —— Part 1 以太坊、Solidity 和 Geth 的入门 —— Part 2 CryptoZombies.io —— 以制作游戏的方法学习 Solicity 如何使用 Geth 部署智能合约 开发一个完整的以太坊投票 DApp 的三部曲 以太坊开发指南 —— Part 1. 开发一个以太坊文件认证合约 以太坊开发指南 —— Part 2. 与智能合约交互 以太坊开发指南 —— Part 3. 为智能合约开发网页界面 开发以太坊区块链应用 —— 实用且详尽的研究项目 以太坊智能合约安全 以太坊智能合约最佳实践案例 探索以太坊和智能合约 —— 完全版在线课程 法务比特法律地图 区块链证券式代币适用的法律框架简介 区块链代币适用的证券法律框架 智能合约适用的法律和合法性 IRS 虚拟货币指引:为保证美国联保税收,虚拟货币被定义成资产;适用于资产交易的一般规则 比特币在不同国家的合法性 如果发现译文存在错误或其他需要改进的地方,欢迎到 掘金翻译计划 — 区块链分舵 对译文进行修改并 PR,也可获得相应奖励积分。文章开头的 本文永久链接 即为本文在 GitHub 上的 MarkDown 链接。掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。
2023年03月24日
7 阅读
0 评论
0 点赞
2023-03-24
什么是智能合约
前言智能合约是在以太坊的EVM上运行的一段经过编译的代码。在这篇文章中我将详细阐述智能合约到底意味着什么,开发的时候有哪些需要思维模式的转变,如何避免踩坑等。智能合约智能合约与平时的代码其实没有什么区别,只是运行于一个以太坊这样的分布式平台上而已。这个运行的平台,赋予了这些代码不可变,确定性,分布式和可自校验状态等特点。代码运行过程中状态的存储,是不可变的。每一个人,都可以开一个自己的节点,重放整个区块链,将会获得同样的结果。在以太坊中,每个合约都有一个唯一的地址来标识它自己。客户端可以与这个地址进行交互,可以发送接收ether,调用函数,查询当前的状态等。智能合约,本质上来说就是代码,以及代码运行后存储到区块链上的状态两个元素组成。比如,你用来收发ETH的钱包,本质上就是一个智能合约,只是外面套了一个界面。GAS是什么既然提到了智能合约,就不得不提和他相伴的GAS限制。智能合约,就是一些代码,运行整个分布式网络中。由于网络中的每一个节点都是一个全节点。这样的好处是容错性强,坏处是效率低,消耗资源与时间。因为执行计算要花钱,而要执行的运算量与代码直接相关。所以,每个在网络运行的底层操作都需要一定量的gas。gas只是一个名字,它代表的是执行所需要花费的成本。更详尽的请参考:《Calculating Costs in Ethereum Contracts》开发智能合约意味着什么开发智能合约意味着什么,或者说为什么我们要开发智能合约,这是一个需要思考的问题,通常的示例一般都是投票,竞价,代币等,这些但是这些例子总是让人很迷惑,为什么要用智能合约来实现这些东西,能不能实现一些有实际价值的,更通俗,与真正的合约相关的内容。前面介绍了合约是什么,可能你们还是没有很清楚,合约可不可以等于合同,合同是不是具有约束性,能在双方(合同一般是双方或者多方)间提供约束,现在的智能合约是否具有法律约束。我们需不需要智能合约虽然现在区块链很火,但是我们必须要承认,他的应用面不是很广,只有少部分特定的行业适合使用。合约开发方式现在常用的语言是 solidity 类js语言,用用remix作为编辑,编译和调试的工具。或者本地使用文本编辑器编写代码,并保存为.sol 的文件,然后使用solcjs 工具将 源码编译为.abi .bin文件。合约的部署方式通过终端部署 通过web3js部署 通过JsonApi部署 引用深入浅出以太坊 4--写一个简单的智能合约 对于以太坊中gas的理解本人网站出处:www.gethgeek.com/archives/sm…
2023年03月24日
9 阅读
0 评论
0 点赞
2023-03-24
使用 React+ethers.js 开发简单加密钱包
最近在开发一个 NFT 二创平台,其中包含了很多概念和技术。我会更新一个系列的文章来总结和沉淀在这个过程中的一些知识与思考。本文是对 ethers.js 进行一个全方位介绍,非常适合 web3 入门学习。什么是 ethers.js?Web3 中的各类 DApp,都需要与智能合约进行交互。如果用原生 JS 来做这些事会很麻烦。这时就需要使用专属的 SDK。目前 JS 环境中有两个主流的库可以用来和智能合约进行交互,一个是 web3.js,另一个是 ethers.js。ethers.js VS web3.jsweb3.js 比 ethers.js 出现的更早。但是目前 ethers.js 更受欢迎。主要原因有如下两点:体积:ethers.js 体积仅有 116.5kb,web3.js 有 590.6kb。相差 5 倍左右。 设计理念:由于设计理念不同。web3.js 认为用户会在本地部署以太坊节点,私钥和网络连接状态由这个节点管理。但实际上大部分人都不会在本地部署以太坊节点。ethers.js 充分考虑了这一点,它是用 Provider 管理网络连接状态,用 Wallet 管理密钥,更加安全和灵活。而且原生支持 ENS。 ethers.js 基本使用介绍节点即服务由于在本地部署一个区块链节点的成本并不低,很少会有人真的部署一个节点,而是选择使用节点即服务。这类服务有很多,比如老牌的 Alchemy、Infura、Moralis 以及今年估值 102 亿美金的新秀 Tenderly。在这里我们选择 Alchemy,目前它的市场占有率是最高的。alchemy 的网址在这:dashboard.alchemy.com/。具体的注册登陆就不讲了。登陆之后我们创建一个 App。Chain 选择 Ethereum,Network 选择 Goerli。这样就成功创建了一个 App,点击后面的 view key,就可以查看 key。我们把它复制下来,后面会用到。构造合约在对合约进行读取或交互之前,我们首先需要构造一个合约对象。合约对象有三个构造参数,第一个是合约地址,是一个字符串。第二个是合约的 abi,可以是一个 JSON,第三个参数是 provider 对象,它用于管理网络连接状态。下面的例子中就是使用 alchemy 提供的 JSON RPC 接口作为网络连接。const rpc = `https://eth-goerli.g.alchemy.com/v2/$`; const provider = new ethers.providers.JsonRpcProvider(rpc); const contract = new ethers.Contract(contractAddress, abi, provider) 复制代码除了 JsonRpcProvider 以外,ethers 还有 IpcProvider、InfuraProvider、AlchemyProvider、Web3Provider 等多种 Provider。读取合约信息abi 中的方法会直接挂载到 contract 对象上,我们可以直接调用。不过需要注意,所有的操作都是异步的。(async () => { const owner = await contract.owner(); console.log(owner); })(); 复制代码连接钱包由于和合约交互需要支付 gas 费用,所以必须有一个数字钱包。钱包有很多种,比如 MetaMask、Rainbow、Coinbase Wallet 等。其中 MetaMask 是最常用的一种数字钱包。这里主要介绍如何连接到 MetaMask。MetaMask 有一个浏览器插件,如果用户安装了该插件,在 window 对象下会有一个 ethereum 对象。我们可以调用 ethereum.request 方法发起请求,参数是一个对象,对象的 method 描述该次请求的操作。ethereum.request 方法是异步的,会返回一个数组,该数组是所有登陆钱包的账户地址字符串,第一个账户就是当前激活的账户。如果返回的数组长度为 0,则意味着没有登陆任何账户。(async ()=> { const accounts = await ethereum.request() if(accounts.length === 0) { throw Error('未登录任何账户') } const activeAccount = accounts[0] console.log(activeAccount) })() 复制代码我们还可以通过 ethereum.request 方法获取当前的网络状态。(async ()=> { const chainId = await ethereum.request() console.log(chainId) })() 复制代码它会返回一个字符串。0x1 表示以太网主网;0x5 表示 Goerli 测试网,更多网络的 chainId 可以在这个网站查看:chainlist.org/。下面是使用 ethers.js 来连接 MetaMask 的代码。(async ()=> { const provider = new ethers.providers.Web3Provider(window.ethereum) const accounts = await provider.send("eth_requestAccounts", []) const activeAccount = accounts[0] })() 复制代码如果使用 MetaMask 作为 provider,那么就不需要再使用 alchemy 了。钱包在转账交易之前,我们需要创建一个 Wallet 实例,它的作用是对交易和消息进行签名。创建 Wallet 对象的方法有三种。通过 Wallet.createRandom 创建随机钱包这种方式创建的是一个单机钱包,需要连接网络。const wallet = ethers.Wallet.createRandom() wallet.connect(provider) 复制代码通过助记词创建const wallet = new ethers.Wallet.fromMnemonic(mnenonic.phrase) 复制代码通过私钥和 provider 创建const wallet = new ethers.Wallet(privateKey, provider) 复制代码钱包信息我们可以在创建好的钱包上面获取很多有用的信息,比如钱包地址、助记词、私钥、交易次数等。console.log(wallet.address) console.log(await wallet.getAddress()) console.log(wallet.mnemonic) console.log(wallet.privateKey) console.log(wallet.getTransactionCount()) 复制代码转账一旦又了钱包,我们就可以向其他人发起转账交易。创建一个 tx 对象,它最少需要两个属性,to 和 value,分别表示接受钱包地址和转账额度。然后使用 wallet.sendTransaction 方法发送转账,它会返回一个 receipt 对象。这个对象有一个异步的 wait 方法,当交易上链后会返回。const tx = { to: address, value: ethers.utils.parseEther("0.1"), } console.log('开始转账') const receipt = await wallet.sendTransaction(tx) await receipt.wait() console.log('完成转账') 复制代码通过合约转账交易交易需要使用 Wallet 对象。再通过 wallet 作为合约的第三个构造参数创建 Contract 对象。调用合约的 transfer 方法,进行转账交易。该方法需要两个参数,转入的钱包地址字符串和转入的数量。transfer 会返回一个 tx 对象,该对象有一个异步的 wait 方法,会在交易完成后执行。const wallet = new ethers.Wallet(privateKey, provider) const contract = new ethers.Contract(contractAddress, abi, wallet) (async ()=> { const tx = await contract.transfer(toAddress, ethers.utils.parseEther("1")) await tx.wait() })() 复制代码通过 signer 进行转账通常我们无法直接拿到 privateKey,但是可以通过 signer 对象间接使用 privateKey。只需要进行签名就可以进行交易。这也是最常用的交易方式。const signer = walletProvider.getSigner(); const tx = { to, value, }; const receipt = await signer.sendTransaction(tx); await receipt.wait(); 复制代码使用 React 和 ethers.js 开发加密钱包接下来我们开发一个最简单的加密钱包,具备最基础的转账功能和查询余额功能。创建项目我们首先创建一个 Next.js 项目。npx create-next-app 复制代码需要选择 TypeScript。安装依赖安装 ethers.jsnpm i ethers 复制代码安装 tailwindcssnpm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p 复制代码修改 tailwind.cinfig.js。/** @type */ module.exports = { content: [ "./pages/**/*.", "./components/**/*.", ], theme: { extend: , }, plugins: [], } 复制代码修改 styles/globals.css。@tailwind base; @tailwind components; @tailwind utilities; 复制代码安装 headless-uinpm install @headlessui/react 复制代码整体架构设计由于业务并不复杂,我们可以将它简单划分为几个组件。使用 Context 足够应对这个场景,而不需要额外导入状态管理库来增加复杂性。Wallet 是根组件,内部维护了很多 state,以 Context 的方式将数据和操作注入到子组件。Connect 负责连接钱包和断开连接。Details 负责显示钱包信息,是纯展示型组件。Transfer 负责向其他账户进行转账。Loading 负责渲染加载动画,是纯展示型组件。创建上下文type IWalletCtx = { walletProvider: any; setWalletProvider: (walletProvider: any) => void; msgIsOpen: boolean; setMsgIsOpen: (msgIsOpen: boolean) => void; msg: string; setMsg: (msg: string) => void; account: string; setAccount: (account: string) => void; networkName: string; setNetworkName: (networkName: string) => void; balance: string; setBalance: (balance: string) => void; showMessage: (message: string) => void; refresh: boolean; setRefresh: (refresh: boolean) => void; }; const WalletCtx = createContext<IWalletCtx>( as IWalletCtx); 复制代码通过初始化一个对象,然后断言为 IWalletCtx 的方式,可以避免在使用 WalletCtx 时添加是否为 undefined 或 null 的判断。因为我们一定会注入数据。Loading 组件Loading 作为纯展示型组件,是最简单的组件。SVG 的代码是直接从 tailwindcss 文档中搬运过来的。仅仅是添加了一个 size 属性,用来展示不同大小的尺寸。function Loading(: ) { const sizes = { sm: "h-3 w-3", md: "h-5 w-5", lg: "h-7 w-7", xl: "h-9 w-9", }; return ( <svg className= text-black`} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" > <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" ></circle> <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" ></path> </svg> ); } 复制代码Wallet 组件在 Wallet 组件中创建这些 state,并注入到 context 中。export default function Wallet() { const [walletProvider, setWalletProvider] = useState<any>(null); const [msgIsOpen, setMsgIsOpen] = useState(false); const [msg, setMsg] = useState(""); const [account, setAccount] = useState<string>(""); const [networkName, setNetworkName] = useState<string>(""); const [balance, setBalance] = useState<string>(""); const [refresh, setRefresh] = useState<boolean>(false); useEffect(() => { setWalletProvider(new ethers.providers.Web3Provider(window.ethereum)); }, []); const showMessage = (message: string) => { setMsg(message); setMsgIsOpen(true); setTimeout(() => { setMsg(""); setMsgIsOpen(false); }, 2000); }; return ( <WalletCtx.Provider value={{ walletProvider, setWalletProvider, msgIsOpen, setMsgIsOpen, msg, setMsg, account, setAccount, networkName, setNetworkName, balance, setBalance, showMessage, refresh, setRefresh, }} > <div className="flex flex-col gap-4 p-4"> <Dialog open= as= onClose=> <div className="fixed flex justify-center items-center w-full top-2"> <Dialog.Panel className="inline-flex flex-col bg-green-400 text-slate-600 p-4 shadow-xl rounded-3xl"> <Dialog.Title></Dialog.Title> </Dialog.Panel> </div> </Dialog> <Connect /> <Details /> <Transfer /> </div> </WalletCtx.Provider> ); } 复制代码Wallet 组件基本上没有什么逻辑,它的主要作用有三个:向 context 注入数据。 创建 ethers.provider。 使用 Dialog 组件作为全局消息提示。 Connect 组件在 styles/globals.css 中添加按钮样式。@layer components { .btn { @apply bg-black text-white py-2 px-4 rounded-3xl; } } 复制代码在 index.tsx 中编写逻辑。function Connect() { const { walletProvider, account, setAccount, setNetworkName, setBalance, showMessage, refresh, } = useContext(WalletCtx); const refreshBalance = useCallback(async () => { if (!walletProvider || !account) return; const balance = await walletProvider.getBalance(account); setBalance(ethers.utils.formatEther(balance)); }, [setBalance, walletProvider, account]); useEffect(() => { refreshBalance(); }, [refresh, refreshBalance]); const connectToMetamask = async () => { try { await window.ethereum.enable(); const accounts = await walletProvider.send("eth_requestAccounts", []); const network = await walletProvider.getNetwork(); const balance = await walletProvider.getBalance(accounts[0]); setAccount(accounts[0]); setNetworkName(network.name); setBalance(ethers.utils.formatEther(balance)); } catch (error) { console.log(error); showMessage("failed to connect to metamask"); } }; const disconnect = async () => { setAccount(""); }; if (!account) { return ( <div className="flex justify-end p-4"> {walletProvider ? ( <button className="btn" onClick=> connect to metamask </button> ) : ( <Loading /> )} </div> ); } return ( <div className="flex justify-end items-center gap-2"> <h1 className="text-end">Hello, </h1> <button className="btn" onClick=> disconnect </button> </div> ); } 复制代码我们连接钱包后会获取 3 个重要的信息:钱包账户地址、连接的网络和余额。分别通过 walletProvider.listAccounts()、walletProvider.getNetwork() 和 walletProvider.getBalance(accounts[0]) 来获取,需要注意它们都是异步操作。Details 组件Details 作为纯展示型组件没有什么逻辑,主要是一些样式。function Details() { const = useContext(WalletCtx); if (!account) { return null; } return ( <div className="flex flex-col gap-4 w-full bg-slate-800 text-white p-4 rounded-md"> <div className="flex justify-between"> <div className="text-2xl font-thin">balance</div> <div>network: </div> </div> <div className="flex items-end gap-2"> <div className="text-2xl"></div> <div>ETH</div> </div> </div> ); } 复制代码现在我们看一下 Connect 和 Details 组件一起使用的效果。Transfer 组件Transfer 的功能比较简单,它在 UI 上仅仅包含两个输入框和一个 send 按钮。两个输入框分别可以输入 to 和 value,表示转账的钱包地址和转账金额。function Transfer() { const = useContext(WalletCtx); const [to, setTo] = useState<string>(""); const [amount, setAmount] = useState<string>(""); const [transferring, setTransferring] = useState<boolean>(false); const transfer = async () => { try { const value = ethers.utils.parseEther(amount); const signer = walletProvider.getSigner(); const tx = { to, value, }; setTransferring(true); const receipt = await signer.sendTransaction(tx); await receipt.wait(); setTo(""); setAmount(""); showMessage("successfully transferred"); } catch (error) { console.log(error); showMessage("failed to transfer"); } finally { setTransferring(false); setRefresh(!refresh); } }; if (!account) { return null; } return ( <div className="flex flex-col gap-4 mt-4"> <div className="font-bold text-4xl">Transfer</div> {transferring ? ( <div className="flex flex-col items-center gap-4"> <div className="text-3xl">transferring...</div> <Loading size="xl" /> </div> ) : ( <div className="flex flex-col gap-2"> <input className="input" value= onInput= type="text" placeholder="address" /> <input className="input" value= onInput= type="number" placeholder="amount" /> <button className="btn" onClick=> send </button> </div> )} </div> ); } 复制代码转账是通过 signer.sendTransaction 方法进行的,它会返回收据对象 receipt。在转账时使用到了 ethers.utils.parseEther,因为 value 默认的单位是 wei,它非常小,10 的 18 次方才是一个 ehter。在 JS 中需要使用 BigInt 类型表示,并不方便操作,而我们更喜欢用 ether 来描述货币。所以这个 API 可以帮我们转换货币单位。需要注意,在测试时需要选择 goerli 网或者其他测试网,否则会浪费 gas 费。你至少要有两个钱包账户,这样可以从一个钱包账户转到另一个钱包账户。下面我们来测试一下转账。这时 MetaMask 钱包会弹出来签名界面。点击确认后,需要等待一段时间上链,大约 1 分钟,或者更久。转账成功后,当前账户的余额会刷新。完成现在一个简单的加密钱包就完成了。通过这个项目的学习,相信你已经学会了 ethers.js 常规 API 的使用。源码链接:github.com/luzhenqian/…线上地址:web3-examples.vercel.app/我一直在深入研究 Web3 的最新趋势,相信这些趋势会使我们的生活变得更好。如果你对 Web3 感兴趣,欢迎联系我,一起打造一个更公平的世界吧。同时也可以关注我的 Web3 专栏,我会持续更新更多 Web3 相关内容。
2023年03月24日
14 阅读
0 评论
0 点赞
2023-03-24
智能合约全栈介绍 - Howard | Jeth 第一期
编者按:本文系 Qtum 的 Howard 叶倍宏讲师,在由掘金技术社区主办,以太坊社区基金会、以太坊爱好者与 ConsenSys 协办的《开发者的以太坊入门指南 | Jeth 第一期 - 北京场》 活动上的分享整理。Jeth 围绕以太坊技术开发主题的系列线下活动。每期 Jeth 会邀请以太坊开发领域的优秀技术团队和工程师在线下分享技术干货。旨在为开发者提供线下技术交流互动机会,帮助开发者成长。Howard 老师本次分享视频回放(B站分享整理传送门以太坊智能合约 + DApp 从入门到上线:来自前端工程师的实战指南 - 王仕军 | Jeth 第一期详解 ERC20 代币及众筹 - 熊丽兵 | Jeth 第一期Howard 是《Deep Dive Into Ethereum Virtual Machine》一书的作者,该书深度剖析了 Solidity 和以太坊的原理。目前,Howard 任 Qtum 量子链 DApp 平台核心工程师,负责开发工具和数据库。Howard 在创业界拥有10年的产品开发经验,并且对构建去中心化产品充满热情。他也是本次活动的出品人。大家好,很荣幸今天跟大家分享一下以太坊智能合约的一些开发经验,在开始之前,我今天先给大家先讲一个高层面的介绍,从前端到后端介绍一下以太坊的技术栈;然后之后我们两位老师会给大家去介绍一些细节。所以我的这场分享只需要大家脑海里有个对以太坊的概念即可,具体细节后面我们两位老师会给大家更精彩的讲解。我今天就先介绍一下智能合约以及它存在的理由,然后带大家看一下智能合约长什么样子,最后会带大家梳理以太坊的整个架构,从前面面对用户的DApp到后面的存储数据库。先简单自我介绍一下,我是台湾同胞,目前在大理远程办公。为什么要智能合约切入主题,为什么要有智能合约,挖矿非常的费资源,为什么要花这么多的精力这么多的资源在挖矿上面?有位区块链先驱者提了这样一个概念:技术让人跟人之间去协作。我们个人自己跟自己协作,但是我可能多做一点事情,会找我的朋友找我的亲人去合作,以此让我做更大的事情,这样我们需要一些合作,我信任我的兄弟,我信任我的同学这种类型的合作。更多的合作我们跟以太坊的爱好者我们掘金的事情我们互相的爱好及把我们捆绑在一起让我们做更大的事情,再更大一点在一个城市,这个时候我们要有法律,我们需要各种政府部门,机关,就算我不认识你,我不认识买我产品的人,但我可以通过我们的合约去保证我们合作的可行性,更大一点就是国家跟国家、国际法院的合作等,这些跨边界的合作是更复杂的体系。人类的文明跟技术是随着这个合作的复杂性而增长的。那为什么我们要有规则呢,信任其实是非常昂贵的资源,我最信任的人就是我的亲人和我的朋友,尤其是从小一起长大的朋友;但是我来到城市、国家这个级别的话,其实是很难信任一个不认识的人,所以我们要提高达成合作的可能性,就要降低信任最小的需求。我们只要通过这个概念降低互相伤害的风险,友谊的小船就不会翻。我们要尽量的信任别人,他讲这些东西是科技,我们从人跟人之间的信任上升到法律,所以我们开始讲法律时就不需要提及信任。从人情到市场,我可能愿意跟人合作,到市场我们开始讲价格,我们有价格的协调机制,就不需要讲人情了。我们点对点的对话,必须要认识你这个人我才有办法跟你协作,多对多的撮合市场机制,这是一个持续演化的过程。所以我们开始讲这些事情的时候,会牵扯到社会扩容,社会的扩容是需要成本的,我们需要有政府,需要有法院,需要有警察机构。上图中我们可以看到OECD政府的GDP占比是从36%到58%不等。我们虽然没有买单、没有直接的去支付这些成本,但是实际上这些东西在政府开销上占了很大比重。那区块链做的事情他是因为取代信任的机制,即以计算机替代人工成为核心的概念。所以说智能合约他具体就是一个计算机程序,它来替代靠人工运营的这些机构。智能合约具体是什么接下来我们可看一下智能合约具体是什么东西。第一个例子就是亚马逊的 LAMBDA 服务,LAMBDA一个特性是你在LAMBDA这个平台写程序的时候,你只是去写你的业务逻辑,而这个业务逻辑你直接上传到 LAMBDA 平台上面,好像只是一个服务器的回调。只要有请求进来它就调用这个回调,计算完成后就直接终止了,你要自己去部署一个服务器,没有逻辑。LAMBDA 这个平台让你直接把服务器的这个业务逻辑放在平台上面,完全不用去管后面对应哪些具体服务器,一有请求进来,并把 LAMBDA 启动,这个跟智能合约的架构非常像。我们可以看一个较为简单的例子,这个计数器的业务逻辑很简单,这边有一个COUNT,把它想成数据库里的数据,这个合约有数据也有业务逻辑,这个业务逻辑要做的事情就是把这个数字递增。当外部调用这个递增的时候,它去数据库里面修改这个COUNT这个变量,这个就是你的智能合约,从概念上来讲也没有什么,它之所以牛逼是因为我们用去中心化的网络去同意了这个数据应该是什么,我们具体接下来看一个更好的例子。我们把这个合约的这些变量理解成一个数据库,我们可能平常在写一个加法的类型,它只是存在于类型里面,你的假若死掉了,这个内存就清空了。在智能合约里面,虽然它是变量,但是你是写在链上面,而这个数据库恰巧是特别昂贵的数据库。我们类比成 Java 的伪代码,我们会想象后面每一个合约它有一个相对应的数据存储,它是一个对象,是一个数据库,在这个方法里面刚才讲了递增的方法,它只是去操作这个数据库,在这个键修改它里面的值,所以你每次去改一个变量其实是对数据库做一个操作,而且这个操作是特别昂贵的操作,可以给一个概念,普通所有的这些指定是要费用的,普通的一个纸币,比如说加减乘除,大概是2到5个不等,存储的话是2万个,大概算是5000倍的倍增。我们看一个更完整的例子,功德香火链,这个例子大概介绍了智能合约非常本质的一个东西。为什么要写智能合约,我们并不是只是为了写这个数据,他之所以牛逼是因为他里面有金融属性,大家可以相信你,如果在我自己的亚马逊 LAMBDA 上搞一个功德香火链是没有人相信的,我在数据库里面可以随便修改,但如果我们改成在智能合约中就变成是一个去中心化、不需要信任的一个程序。大家来看一下这个东西,有一些需求,他初始化的时候我们要设定管理员,任何人我们都允许他捐款,最后要用这个款项的时候我们允许管理员取款,然后让他写出所有取款他的去处去了哪里。这个就是我们整个智能合约的代码,就十几行而已,这上面大概有两点需要留意,有合约属性,拥有者的姓名,我们会用这个属性来存储他的管理员,我们控制了管理员权限才可以进行修改。下方分别是捐款和取款的函数,我们接下来把这两个函数分开讲解。初始化设定管理员,所以说这边我们是要把数据存起来,我们要知道谁是管理员,在创建这个合约的时候它是用一笔交易创建的,即有一个钱包去付钱然后去说这笔交易谁创建的。这里的属性指出当前用户的身份,这一笔交易的操作者以及合约的操作者。我们这边做的事情很简单,在创建这个合约的时候我们把当前的操作者存储在这个数据库里面,有了这个东西之后我们就可以验证正在操作的人是不是管理员。接下来我们开始做这个核心的东西,即任何人都可以转款,之后你要做众筹让别人给你转钱,这个东西就涉及到金融的属性了。我们看到这个函数也是一样,在操作这个把钱的用户,我们要记下来,也就是要记下这个功德;PAYABLE 它只是一般拿来处理跟金钱相关的东西,这里是处理存进来的钱。这里要有个断言,要确认这笔钱必须要大于0.001,因为我不想要太少,太少就看不上、不想要;最后这边有一个日志,说我们把这个输出和这个功德记下来,然后保佑发送这个钱的人,这个日志就记在链子上面了。报错是直接退款,他没有满足这一个条件这笔交易就失败了,他捐了钱就打回原本的帐号,当然这个真实的合约你会做各种其他的需求,理念上就是你先检查满足了你的需求之后,你再去操作你的业务逻辑,然后最后你就可以输出记录这个事情。我认为比较有意思的事情,这个合约他有一个相对应的帐号,这个帐号合约有多少钱,你看里面的业务逻辑并没有显性的说把这个钱给这个合约,你这个隐性只是说这一笔交易进来了,只喜欢这个逻辑,然后最后就会给这个帐号,但是你不需要代码直接说这个事。接下来看看看管理员取款,我们这个函数可以让管理员指出取钱的数量,这里又有一个断言,我们在断言里面判断当前操作这一笔交易的人是否是这个合约的拥有者,我们一开始就要把这个拥有者记录下来,之后的操作中我们再去验证一下他是否是当初创建合约的人,如果是的话我就给这个用户给他打钱,转给他所要的钱。我们首先要做一个小测试,假如说这个帐号当前有10个以太坊币,然后拥有者试着去取11个以太坊会发生什么事、触发什么条件会报错。假如说它试着转钱,这边是从合约里面把钱转给A,它账户里面的钱不够多就会报错,同事状态会直接全部回到原来的状态。这个回滚的概念特别的重要,一般你在写程序做一个操作的时候就有一个请求进来了,你对数据库做一个操作,那你报错了,之前的数据库要回滚;以太坊会自动做这个回滚的事情,只要一失败它就马上回滚。我们可以看一下一些平台的特性,过去通常是你自己公司买这个服务器,大家用这个服务是不用钱的;现在是用户承担所有的计算费用,GAS模型去计算,然后很核心的点是用户他掌握了权限,比如说你用支付宝想转帐你在支付宝平台上确认这笔帐能不能转,那现在用客户端在客户端做了签名,然后服务端说让你转帐,他是不会去验证这个客户在终端到底是谁。还有一点,虽然说以太坊或者量子,有着几千几万的节点,其中以太坊是有17000多个节点,看似这17000个节点计算能力还不错,事实上并没有。因为每一个节点要重复每一个计算,计算每一个数据,所以当我们说存储数据库,如果是当成传统数据库来用是不可行的,因为太贵了。去中心化平台也是有他自己的缺点,他很慢,处理一笔交易要花20秒;其次贵,每一笔交易要花大概0.1或者是0.2美元,如果你要发一笔比较大的合约就是10美元到100块人民币左右了。你做应用交易的生命周期极其复杂,这个东西你必须要等他确认,等一次两次三次,然后他可能中间会抛错,各种不同抛错情况,有可能是业务逻辑抛错,也有可能是他给的GAS不够,然后跑一半逻辑他没有钱了,就终止了,还有一些其他的在业务上有一些没有办法做,没有网络请求没有随机员,还有你不能更新合约代码,之前出了一些漏洞,有些人写了合约,这个合约被别人删了,然后他很多钱就卡在里面,几千万美金的钱卡在里面。所以说在做的时候就可能需要思考一下我这个东西去中心化有意义吗,到底是哪些东西值得去中心化。DAPP全栈走一回那我们接下来更深入的看一下,DApp全栈走一回,我们用一个简单的例子然后走到最后面的区块链上面存储的数据。这个合约中,我有一个变量,有一个值,然后我唯一要做的事情就是修改这个值或者是读取这个值,这个就是我的一个简单的智能合约。我们会从前端开始,我们看一下从前端再递增RPC,这个是ABI的编码,我们一会儿再展开来说,这个合约就是他的业务逻辑,EVM最后到区块链存储,我们一个一个展开来再说。所以说你可以比较一下WEB 2.0到3.0他们技术站的对比,然后WEB 3.0就在吹牛说WEB3.0技术是一样的,只是换汤不换药,在WEB 2.0我们做了一个请求,用户按一个钮就产生一个请求,用户按一个钮就产生了一笔交易,会带有一定的金额,这个需要整个网络去确认,而不是单一的服务器去确认,但是在前端是由用户批准交易之后再丢给网络让网络去处理。然后你写后端说我这个请求他里面具体的数据是怎么样的给一些结构,那我们现在做后台的话常常是用ABI的结构,以太坊这边它相对应的这个数据结构就是叫做ABI编码,传给智能合约的数据就是用ABI编码,在WEB 2.0我们做服务,后来在WEB 3.0我们想写智能合约去做这些服务。但操作系统层面在WEB 2.0时是 Windows 这些操作系统,现在的以太坊就是虚拟机,同时也能做一些操作系统方面的处理,比如说存储数据转钱,或者是调用其他合约,这些是用EBM来做的,这些是混合了两个不同的东西在一起,又是虚拟机又是操作系统。最后我们要存储数据,就是在WEB 2.0文件系统这些去存数据,在WEB 3.0我们有电子版本控制,你可以有各个版本。那我们看看前端,前端要做的事情就是展现链上的数据,重点还是一样,用户在本地签名之后再把数据提交到链上,这个权利是握在用户的手上,我们可以比较一下WEB服务和纯客户端的两个概念,大家熟悉这个应用就是币安这种平台做交易,实际上这些不够形成这些权限的控制都在平台手上,像钱包这种东西才是比较正儿八经去中心化,你说了话不算,是用户控制权限。在这两个极端去纠结如果我真的要做一个去中心化应用的话,它的用户体验会很差很难用;好处是中心化的服务,用户体验好且反应快,但是就是出了事的话那大家都一锅掀了,现在是在两个极端里面去纠结怎么做。我们看一下前端的例子,这个REMIX IDE,他指向合约,他有两个按钮,一个是GET 的按纽,还有一个是SET的按钮,我要通过调用的方法去改那个值。然后当我按向那个按钮我要去设定666,这个时候他用RPC去递交一个事物,然后在以太坊就是这个RPC的方法,他们的概念是一样的。所以我调用这个方法从我的钱包去打这个数据,然后我们之后会把这个数据去展开,它也是一个RPC,这里面的数据传给智能合约的数据,我们来展开看一下。我把刚刚那个东西调用到网络上面,我就可以看到这一笔交易,这个就会把交易里面的一些信息显示出来,我花了多少 Gas,然后里面传了一些数据。我们看 ABI 的编码,我们可以拆开两部分,这个 60fe47b1 他也是调用方法,这个是他的方法名然后拼接在一起去取这个前面四个字节就是这个方法的选择器,我调调用智能合约的时候前面四个字节指定我要调用哪些方法,后面那些就是我传参,就是用这个编码出来的,虽然666其实只需要2个字节,但是他ABI编码的设计必须要32个字节,所以说这里可以看到他是有一定的浪费的。刚刚传到数据上来之后EVM的节点就会把智能合约的代码加在这个里面去执行,这个是我们刚刚设定的方法,传值进去进行修改。我们可以看一下EVM的字节码,刚刚看到这个是智能合约,这个智能合约最后通过编译器会编译到字节码,他基本上是从上到下一个一个执行的。我们要关注的是有两个可以关注的,上面这边60fe47b1这个就是我们选择器,我先判断一下是不是这个方法,是这个方法的话我跳到这边来去继续执行。所以说这个就是我们SED方法,最下面我们存储数据了,这点是一个关键点,我们刚刚是要存到value这个属性,这个属性他可以理解为建值,他直接是映射到0的位置,我用0去存储,最终把这个数据存储到内存里面去,所以说这是整个合约最关键的指令,存储数据。我们把刚刚说的那些东西从EVM字节码变成代码,这个是我发的时候他里面会带着一些数据,这个数据就是有一个指令,然后我取前面四个字节这个就是我要选择的方法,如果匹配了这个字节我就跳到tag这边,这边我要取参数,我也是从这里去取,我直接从四个字节以后取32个字节出来,这个就是我的参数,然后最后我把我读出来的参数存到这个位置,这个就是我们刚刚合约做的事情。我们下面分析一下sstore这个指令是在干啥,我们刚刚做的事情就是把数据存在第一个位置,L1这个位置,这个位置可以是无限多的,我存在这个位置之后他就会更改,其实最上面的这个就是我的版本号,我的版本号他是取这两边的,然后每一个节点都一样,这边的 hash 是由下面来更改的,如果我更改了这里面的数据,这边的 hash 会变,然后导致最上面的这个版本号也变了,所以说直接把这个 hash 当成版本号就可以了。如果我去改动这边的数据那通过这个路径去改变最上面的版本,下面这边是我存储数据的地方,我任何地方存储的数据都会影响到最上面的版本号,跟 top 的版本控制有点像。这边就是我们存储数据的数据结构,接下来我们看一下这个数据结构最后是如何融入到链里面去,这个就是咱们的区块链,里面会存着版本号,像说你去 GitHub 上面看一个项目,会有历史更新文档,会讲这个版本号修改了什么,这个版本号修改了什么。这个就数据结构类似于一个版本,每个版本会去记录这一个相对应的版本号是什么,然后从这个版本号可以取出相对版本所有的数据。再回顾一下刚才提到的,我们从前端通过RPC,这个是以太坊节点提供的服务,通过到RPC调用这个节点,调用里面的数据是由ABI编码结构化,然后传给合约,合约处理这个数据,最后这个合约是相对应字节码,然后由EVM解析,解析的结果通常就是存出去要么就是给别的帐号打钱,大概就是这样。区块链现状&未来区块链的现况大家体会一下,有点天下大乱的样子,区块链的新世界,这个是我们对未来的小展望,现在大概是5000万个用户在炒币,可能未来十年区块链会增长到10亿用户,像手机一样普及。如果这个事成真,每个人都会有一些数据的资产,变得像手机一样普及,这样的话我们要讨论。这就牵扯到扩容,扩容的话有几种方案我现在比较看好侧链和跨链的方案,如果我们要做产品那就考虑说这个到底怎么样做出好的产品给人用,所以说现在很多正在驱动的区块链产品很难用被各种喷;再一个是隐私的问题,区块链就是公开帐本,毫无隐私可言。智能合约发现了很多的问题,智能合约在安全上或者是在可用性上面他学习成本是相当高的,因为它是不同的平台,所用的编程语言也与其他语言不同,一切都要从头开始学。现在我们可以看到一些新一代的智能合约平台可以出现了,像WEB 3.0是在浏览器里面做一个接近底层的版本。所以说我们可以看到像以太坊生态圈里面truebit在尝试然后像rholang这类项目,它也解决了合约并发的问题,像我们公司量子我现在做一个虚拟机,这个是模拟了CPU的架构,我们希望说通过这个架构可以支持一些比较底层的开发去做智能合约,然后我们会比较关注像操作系统和虚拟机的分层,现在你去分析EBM的原理,它是字节码,里面会看到一些属于操作系统的的这个指令,它其实是建在虚拟机里面,这个也是一个技术上的一些问题。刚刚也提到了一个问题,就是智能合约到底能不能更新,应该怎么更新,这也是现在行业里面讨论的问题,我们会采用一个像DGP这种方式,我们通过投票去让用户选择这个智能合约应该怎么更新。欢迎大家跟我交流,谢谢大家。
2023年03月24日
9 阅读
0 评论
0 点赞
1
...
76
77
78
...
109