以太坊中常用名词的解释与联系
Keccak256
比特币和以太坊中,都采用了SHA(Security Hash Algorithm)哈希函数进行加密,比特币中采用了SHA256(属于SHA2),而在以太坊中使用的是SHA3(Keccak256函数)。
以太坊中多处用到了Keccak256:地址的生成、签名、交易。
账户
在以太坊中,有两种类型的账户:
1.外部账户(EOAs,Externally Owned Accounts)
2.合约账户(Contracts Accounts)
当我们提到账户这个术语的时候,我们通常指的是外部账户(EOA),当提到合约账户的时候我们通常称其为“智能合约”。
Gas
每笔交易都被要求包括一个gas limit(有的时候被称为startGas)和一个gas price(交易愿为单位gas支付的费用)。
Gas是由这两个部分组成: Gas limit(限制)* Gas Price(价格)
如果我在交易中设置的gas价格太低,没有人会接纳我的交易作为优先运行。矿工基本不会愿意将你的交易打包进区块里。如果我提供了一个大家可接受的gas价格,然而我的交易产生如此多的计算工作,gas的成本费用超过了我附加的费用,这个gas是已“花费”了得,没有办法收回。矿工将停止处理交易,还原这个交易所做的任何更改,但仍将其作为“交易失败”包含在块中,收取费用你支付的费用。 这可能看起来很苛刻,但是当您意识到矿工的真正工作正在执行计算时,您可以看到他们将永远不会获得这些资源。所以只有你支付了费用,他们做了他们应做的任务这样才会是公平的,尽管是你的设计不当,导致没有支付足够的gas。 提供太高的费用也不同于提供太多的ether。 如果你设定了非常高的gas价格,您所需要只是简单几个操作,就为其支付大量的ether,就像在比特币中设置一个超高的交易费用一样。 你的任务一定会在最优先考虑队列前,但是你的钱已经被支付了。 但是,如果您提供正常的gas价格,并且只要附加的ether比您交易消耗的gas所需的更多,那么以太网络将会把超额费用将退还给您。 矿工只收取你们实际工作的费用。您可以将gas价格视为矿工的小时工资,gas成本作为工作时间。
地址与公私钥
地址是我们与以太坊系统进行交互的标识,它是以太坊账户与外界进行交互的名字,对于外部账户来说,地址表示的是该账户公钥的后20字节(通常会以0x开头)。
大体来说,地址的生成的流程是:私钥->公钥->地址。因此地址的生成需要三步:
1. 生成一个随机的私钥(32字节)
2. 通过私钥生成公钥(64字节)
3. 通过公钥得到地址(20字节)
签名
数字签名是用于证明数字消息或文档的真实性的数学方案。有效的数字签名使收件人有理由相信该邮件是由已知发件人(身份验证)创建的,发件人不能拒绝发送邮件(不可否认),并且邮件在传输过程中未被更改(完整性) 。
数字签名是一种由两部分组成的数学方案。第一部分是使用来自消息(交易)的私钥(签名密钥)创建签名的算法。第二部算法允许任何人仅使用消息和公钥来验证签名。
目前主流的两种非对称加密算法非别是RSA和ECDSA(椭圆曲线数字签名算法),而以太坊是采用了ECDSA加密算法进行数字签名。sendRawTransaction函数的各个入参都将会被 from 所对应的密钥 进行签名而得出三个量:v,r,s,同时,各个入参依然以原来的可见的形式进入序列化步骤。
1、数据签名:
在以太坊的ECDSA实现中,有签名的“消息”是交易,签名密钥是EOA的私钥。利用签名函数对序列化消息的Keccak256散列与私钥进行计算,得出签名Sig=(v,r,s)
2、签名验证:
对应到以太坊的sendRawTransaction RPC接口,收到RLP序列化的数据后,先进行RLP的反序列化,用消息和签名推导出对方的公钥。再通过公钥,签名,消息的哈希值计算出一个叫r的值,这个r是签名的一部分,校验签名就是拿计算出来的r和签名中携带的r经行对比,如果一致就校验通过。
交易
首先是两段有关交易的定义:
1.被外部账户生成的加密签名的一段指令,序列化后交给区块链,分为消息通信和合约创建。
2.由外部拥有的账户发起的签名消息,由以太坊网络传输,并记录(挖掘)在以太网区块链上。
通常以太坊中有3类交易存在:转帐交易、合约创建、合约调用。
转账交易:
{
nonce: '0x28',
gasPrice: '0x3b9aca00',
gasLimit: '0x12cab',
to: '0x71c541231f5bb1ccf924ab1ae2259a82318c9df4',
value: '0xde0b6b3a7640000',
data: ''
}
该类型交易的to字段为收款方的地址,value字段为转账的ether数量,data字段为空。
合约创建:
{
nonce: '0x18',
gasPrice: '0x3b9aca00',
gasLimit: '0xa23d8',
to: '',
value: '0x00',
data: '0x6060604052341561000f57600080fd5b6108f98061001e6000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063762db2b4146100675780639d4ff8ad14610120578063b2c21c9114610191578063bcea56e014610221575b600080fd5b341561007257600080fd5b61009e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102da565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156100e45780820151818401526020810190506100c9565b50505050905090810190601f1680156101115780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b341561012b57600080fd5b61017b600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610486565b6040518082815260200191505060405180910390f35b341561019c57600080fd5b61020b600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610499565b6040518082815260200191505060405180910390f35b341561022c57600080fd5b610258600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610654565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561029e578082015181840152602081019050610283565b50505050905090810190601f1680156102cb5780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b60006102e4610800565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001546000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101808054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104765780601f1061044b57610100808354040283529160200191610476565b820191906000526020600020905b81548152906001019060200180831161045957829003601f168201915b5050505050905091509150915091565b60006104928233610499565b9050919050565b60006104a3610814565b839050600081511180156104b8575060648151105b15156104c357600080fd5b4291506040805190810160405280838152602001858152506000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000155602082015181600101908051906020019061057c929190610828565b509050508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f3a2267d580cf7cd5f1c6b0aaefb67f309eb1469554ef9b8355bbf413dcc97317866040518080602001828103825283818151815260200191508051906020019080838360005b838110156106105780820151818401526020810190506105f5565b50505050905090810190601f16801561063d5780820380516001836020036101000a031916815260200191505b509250505060405180910390a38191505092915050565b600061065e610800565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001546000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101808054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107f05780601f106107c5576101008083540402835291602001916107f0565b820191906000526020600020905b8154815290600101906020018083116107d357829003601f168201915b5050505050905091509150915091565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061086957805160ff1916838001178555610897565b82800160010185558215610897579182015b8281111561089657825182559160200191906001019061087b565b5b5090506108a491906108a8565b5090565b6108ca91905b808211156108c65760008160009055506001016108ae565b5090565b905600a165627a7a72305820125d82944ab5d02eb4d5d6182e6eb60dd47a0e64494bec20f9300b3fdb33f6a20029'
}
创建合约的交易to为空,value为0,data为合约编译后的BineryCode。
合约调用:
0x48be4583a90f253bcc92cec60b244d7de57aa1f425e181545ac036d0d20c47a1
{
nonce: '0x19',
gasPrice: '0x3b9aca00',
gasLimit: '0x18c67',
to: '0xc59565465f95cd80e7317dd5a03929e6900090ff',
value: '0x00',
data: '0xb2c21c9100000000000000000000000000000000000000000000000000000000000000400000000000000000000000005902598fc6c9c85bec8452f9ba3fca2f8b226a1b000000000000000000000000000000000000000000000000000000000000000548656c6c6f000000000000000000000000000000000000000000000000000000'
}
调用合约的交易to为合约地址,value为0,data的构造较为复杂一点,对它的探究也是此次写这篇博客的主要目的,之后还将了解交易数据在区块链1.0网络中以怎样的形式传输与记录。
发送给合约的数据有效负载是十六进制序列化编码:
>函数选择器:函数原型的Keccak256哈希的前4个字节。这允许EVM明确地识别您要调用的函数。
>函数参数:根据EVM定义的各种基本类型的规则进行编码。
简单点将就是把要调用的函数名签名拼接上函数调用参数的编码共同构成data数据。
按照Ethereum Contract ABI的规则,首先得到函数的签名,计算方式是使用函数签名的keccak256的哈希,取4个字节,转换为hex之后就是前8个字符。
接下来对参数进行编码,首先根据参数类型,若为动态类型参数(如string)位数不确定,则相对于所有参数要放在最后,偏移量为:2 * 32字节 (两个参数,每个参数32字节),转为hex并补充到32字节;若参数类型固定位数,直接编码并补全到32位。之后拼接第一个参数的数据(如string,要先计算字符长度并补全到32位:0000000000000000000000000000000000000000000000000000000000000005),最后对参数的内容进行编码(如'Hello'字符串经过hex编码为:48656c6c6f000000000000000000000000000000000000000000000000000000)。
有了交易的数据就可以利用之前生成的私钥对交易进行签名了,要涉及到交易数据格式的转换(RLP序列化),也可以直接利用ethereumjs-tx完成对交易的签名(www.jianshu.com/p/ecb80386c…):
import EthereumTx from 'ethereumjs-tx';
/**
* 交易签名并序列化
* @param {Buffer} privateKeyBuffer 私钥
* @param {Object} txParams 交易结构体
*/
function signTx(privateKeyBuffer, txParams) {
const tx = new EthereumTx(txParams);
tx.sign(privateKey);
const serializedTx = tx.serialize();
return serializedTx;
}
let txParams = {
nonce: '0x19',
gasPrice: '0x3b9aca00',
gasLimit: '0x18c63',
to: '0xc59565465f95cd80e7317dd5a03929e6900090ff',
value: '0x00',
data: '0xb2c21c9100000000000000000000000000000000000000000000000000000000000000400000000000000000000000005902598fc6c9c85bec8452f9ba3fca2f8b226a1b000000000000000000000000000000000000000000000000000000000000000548656c6c6f000000000000000000000000000000000000000000000000000000',
chainId: 3
}
let serializedTx = signTx(privateKey, txParams).hexSlice();
console.log("交易" + ":" + serializedTx);
交易数据:f8e919843b9aca0083018c6394c59565465f95cd80e7317dd5a03929e6900090ff80b884b2c21c9100000000000000000000000000000000000000000000000000000000000000400000000000000000000000005902598fc6c9c85bec8452f9ba3fca2f8b226a1b000000000000000000000000000000000000000000000000000000000000000548656c6c6f0000000000000000000000000000000000000000000000000000002aa082accda7fe28468bda030cd5ae8dad359b7963a9d2ab63c897d1f17196171ff5a053544c8a49e921e7f35c1c35d9340215566f0b9dd1e0504f768b8c993bc96bcf
这些便是以太坊的三种交易类型。
小结
这段时间看的论文中很多用到了以太坊技术,但是由于对其步骤原理了解不深入使得很多应用框架无法很好的理解,特地利用一天的时间查阅了相关的博客与文章,对自己不熟悉的地方进行了总结。 希望自己能每天都有进步^ ^