区块链 web3.0 Metamask
区块链原理
区块链本质就是以区块为单位记录数据,通过指针来指向前一个区块和后一个区块,指针的内容就是区块数据hash后的内容,第一个区块是创世区块,其后每一个区块都首尾互联,所以每一笔数据都可以通过区块链回溯到创世区块,而且区块链数据是公开、透明的,想要篡改数据几乎不可能。
背景
我最近参与的项目也涉及Web3.0的区块链技术,主要是围绕去中心化应用Metamask来集成三方用户认证系统与虚拟货币的支付系统。
去中心化
本质上,Metamask是一个浏览器插件钱包,它是一种非托管(或自托管)加密货币钱包。这意味着没有第三方“保管人”持有我们的私钥,MetaMask不存储有关钱包的任何数据,我们看到的所有内容都在本地级别的浏览器或移动应用程序中。
这就是所谓的去中心化
一般情况下,用户注册后会得到三个私密信息,助记词、私钥以及钱包密码,私钥和助记词用来生成和恢复钱包,密码则只是用来在当前设备上打开钱包而已
metamask的核心功能除了生成钱包的相关信息,最重要的功能就是帮我们链接区块链网络,数据通信的方式采用json-rpc
集成三方登录
由于我们平台本身是中心化系统,需要中心化存储用户的信息,比如账号和密码,而metamask是去中心化系统,我们如果想用户通过metamask登录我们系统,就需要记录一个唯一的标识位,这里通过metamask生成的钱包地址来进行登录
不同于当下的互联网世界的账号体系,一个区块链的钱包地址并不是注册得来。 而是通过使用私钥进过一系列复杂的加密算法得来。 生成钱包地址的加密算法是公开且固定的。意味这任何人可以在任何时候用任何设备任何编程语言实现该方法后生成钱包地址。无需联网。 每一个符合条件的唯一私钥对应唯一一个钱包地址。 私钥是操作钱包的唯一凭证。 私钥丢失不可找回。
所以钱包地址不是我们通常认为的区跨链网络的某个地址,而是一个通过算法生成的字符串,这个字符串是唯一的,而区块链网络只负责记录有关这个钱包地址的交易记录,包括转账或者收款,而这些记录也是公开的,可以通过钱包地址进行查询。
所以我们的系统只要得到用户授权,能够获取到当前用户的钱包地址即可。
钱包生成算法(可说可不说)
生成一个随机的私钥(64 个 16 进制字符, (256 bits / 32 bytes)) 通过 Elliptic Curve Digital Signature Algorithm 用私钥生成公钥(128 个 16 进制字符,64 bytes) 通过 Keccak-256 的哈希函数用公钥得到一个 64 个字符长度的字符串,然后取最后 40 个字符作为地址(40 个 16 进制字符,20 bytes)
再加上 0x 开头变为 42 个字符十六进制字符串。例如:0x5e97870f263700f46aa00d967821199b9bc5a120
三方登录流程
web3.0登录和传统登录有很大区别,并不需要跳转授权,也不需要标识码和token的参与,
而metamask登录则是先在前端通过Web3.js浏览器插件中保存的私钥对钱包地址进行签名操作,随后将签名和钱包地址发送到后端,后端利用Web3的库用同样的算法进行验签操作,如果验签通过,则将钱包信息,也就是地址存入平台token,并且返回给前端。
既然钱包私钥是存储在浏览器中,也就是保存在客户端,那签名已经通过私钥生成了,为什么还要过一遍后端呢?这不是多此一举吗?事实上,攻击者完全可能获取到前端生成的所有信息,因为前段所有的代码都是暴露的,而后端不会,所以签名一定必须得是后端提供,或者至少有一步后端验证,防止签名或者钱包地址被篡改。
这里后端基于web3库通过recoverHash方法对签名进行反编译操作,如果反编译后的钱包地址和前端传过来的钱包地址吻合,那么说明当前账户的身份验证通过
相比传统认证方式,去中心化验证更加方便。只需要保存一个钱包地址(公钥),不会泄露用户的隐私数据。
三方支付
区块链三方支付指的是用户可以在平台上通过虚拟货币进行支付的行为,区别于传统支付流程,区块链支付可以理解为用户通过metamask授权的钱包地址为打款方,往平台的钱包地址打款的行为。
和支付宝类似,区块链也有类似沙盒的测试网络,一般情况下,我们会在Rinkeby测试网络进行测试,代码通过测试后,再进行主链的操作。
支付流程
当页面首次加载时,我们希望检查用户是否已经将钱包连接到站点。为此,我们需要使用eth_accounts方法获取用户的帐户。如果没有返回帐户,这意味着用户没有连接
当用户通过验证后,在前端通过Web3Provider获取到签名实例,随后根据时间戳+域名+支付金额生成签名,签名生成后,立刻调用异步回调方法向后台发起异步请求进行验签操作
后端通过同样的算法对签名进行验证,如果验签通过,后端将会返回商户的钱包地址,也就是用户转账的钱包地址,同时会将付款金额通过w3.toWei方法进行转换,以太币的最小单位为wei,1个以太币相当于10的8次方wei。通常,大家也使用Gwei作为展示单位。比较常用的就是eth,Gwei和wei。
但为了统一标准,支付表单汇总显示的是eth最大单位,所以通过toWei方法,将最大单位转换为最小单位,即0.001eth=100000000000000wei,注意转换后需要以字符串的形式返回到前端。
验签通过后,前端获取支付钱包地址和金额,旋即通过钱包创建支付
通过eth_sendTransaction方法发起交易,当用户同意支付请求时,将会返回此笔交易的TransactionHash:0xe937c66e337322cf3b83788b495af2da35ff9635aaaa20f156c74c7f7fddad26
可以理解为订单号
事实上,每一笔支付交易都会产生另一笔“燃料费”,交易燃料费将归属于挖出区跨链中本次交易区块的矿工。当矿工挖矿时,他需要决定哪些交易放入到区块中,可以随机选择交易, 也可以不包含任何交易。为了鼓励让矿工将你的交易放入区块,相应地,你必须付出一部分“小费”,这里燃料费由客户进行支付
支付确认之后,我们可以利用Rinkeby网络站点通过输入交易哈希号来查询这一笔交易
本质上,如果出现网络波动或者燃料费问题导致交易失败,区块链交易也需要轮询服务进行托底。
同时区块链交易区别于传统的线上交易,它是同步计算模式,所以速度上要慢于普通的法币业务,也不支持退款操作,想要退款只能重新发起一笔交易。