分类
怎么在外汇短线交易中赚钱

以太坊是银行帐户

图灵完备性是以数学家艾伦.图灵命名的概念。具有图灵完备性的机器,能执行任何程式码。比特币有一种支持某种运算的手稿语言,但以太坊的图灵完备语言,是为了支持程式设计师梦想的任何东西,而且依然以分散的方式运行。

以太坊是银行帐户

对比比特币的 “UTXO” 余额模型,以太坊使用“账户”余额模型。 以太坊丰富了账户内容,除余额外还能自定义存放任意多数据。 并利用账户数据的可维护性,构建智能合约账户。

实际上以太坊是为了实现智能合约而提炼的账户模型。 以账户为单位,安全隔离数据。 账户间信息相互独立,互不干扰。 再配合以太坊虚拟机,让智能合约沙盒运行。

账户基本概念

EOAs-外部账户(external owned accouts)是由人们通过私钥创建的账户。 是真实世界的金融账户的映射,拥有该账户私钥的任何人都可以控制该账户。 如同银行卡,到ATM机取款时只需要密码输入正确即可交易。 这也是人类与以太坊账本沟通的唯一媒介,因为以太坊中的交易需要签名, 而只能使用拥有私有外部账户签名。

  1. 拥有以太余额。
  2. 能发送交易,包括转账和执行合约代码。
  3. 被私钥控制。
  4. 没有相关的可执行代码。

含有合约代码的账户。 被外部账户或者合约创建,合约在创建时被自动分配到一个账户地址, 用于存储合约代码以及合约部署或执行过程中产生的存储数据。 合约账户地址是通过SHA3哈希算法产生,而非私钥。 因无私钥,因此无人可以拿合约账户当做外部账户使用。 只能通过外部账户来驱动合约执行合约代码。

特别需要注意的是,在EIP1014中提出的另一种生成合约地址的算法。 其目的是为状态通道提供便利,通过确定内容输出稳定的合约地址。 在部署合约前就可以知道确切的合约地址。下面是算法方法: keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:] 。

  1. 拥有以太余额。
  2. 有相关的可执行代码(合约代码)。
  3. 合约代码能够被交易或者其他合约消息调用。
  4. 合约代码被执行时可再调用其他合约代码。
  5. 合约代码被执行时可执行复杂运算,可永久地改变合约内部的数据存储。

外部账户合约账户
私钥 private Key✔️✖️
余额 balance✔️✔️
代码 code✖️✔️
多重签名✖️✔️
控制方式私钥控制通过外部账户执行合约

账户数据结构

以太坊账户数据结构

但在数据存储上稍有不同, 因为外部账户无内部存储数据和合约代码,因此外部账户数据中 StateRootHash 和 CodeHash 是一个空默认值。 一旦属于空默认值,则不会存储对应物理数据库中。 在程序逻辑上,存在 code 则为合约账户。 即 CodeHash 为空值时,账户是一个外部账户,否则是合约账户。

以太坊账户数据存储结构

上图是以太坊账户数据存储结构,账户内部实际只存储关键数据,而合约代码以及合约自身数据则通过对应的哈希值关联。 因为每个账户对象,将作为一个以太坊账户树的一个叶子数据存储, 不能太大。

以太坊世界态

在密码学领域,Nonce 代表一个只使用一次的数字。它往往是一个随机或伪随机数,以避免重复。 以太坊账户中加入 Nonce,可避免重放攻击(具体细节,在讲解以太坊交易流程时介绍),但不是随机产生。 账户 Nonce 起始值是 0,后续每触发一次账户执行则 Nonce 值计加一次。 其中一处的计数逻辑如下:

这样的附加好处是,一般可将 Nonce 当做账户的交易次数计数器使用,特别是对于合约账户可以准确的记录合约被调用次数。

而 Balance 则记录该账户所拥有的以太(ETH)数量,称为账户余额 (注意,这里的余额的单位是 Wei )。 转移资产(Transfer)是在一个账户的 Balance 上计加,在另外一个账户计减。

当然必须保证转账方余额充足,在转移前需要 CanTransfer 检查, 如果余额充足,则执行 Transfer 转移 Value 数量的以太。

账户状态哈希值 StateRoot ,是合约所拥有的方法、字段信息构成的一颗默克尔压缩前缀树(Merkle Patricia Tree 后续独立文章讲解)的根值,简单地讲是一颗二叉树的根节点值。 合约状态中的任意一项细微变动都最终引起 StateRoot 变化,因此合约状态变化会反映在账户的 StateRoot 上。

同时,你可以直接利用 StateRoot 从 Leveldb 中快速读取具体的某个状态数据,如合约的创建者。 通过以太坊API web3.eth.getStorageAt 可读取合约中任意位置的数据。

  • ❶ 一行代码涉及多个操作。首先是创建一个内存KV数据库,再包装为 stata 数据库实例, 最后利用一个空的DB级的 StateRoot ,初始化一个以太坊 statadb。
  • ❷ 定义两个账户 acct1和acct2,并分别添加100和888到账户余额。
  • ❸ 模拟合约账户的创建过程,由外部账户 acct1 创建合约账户地址,并将此地址载入 statadb。
  • ❹ 在将合约代码加入刚刚创建的合约账户中,在写入合约代码的同时, 会利用 crypto.Keccak256Hash(code) 计算合约代码哈希,保留在账户数据中。
  • 以太坊是银行帐户
  • ❺ 模拟合约执行过程,涉及修改合约状态,新增三项状态数据 owner , name 和 online ,分别对应不同值。
  • ❻ 这里和前面不同的是,是给状态 online 赋值为空 []byte<> ,因为所有状态的默认值均是 []byte<> , 在提交到数据库时,如Leveldb 认为这些状态无有效值,会从数据库文件中删除此记录。 因此,此操作实际是一个删除状态 online 操作。
  • ❼ 上面所有操作,还都只是发生在 statdb 内存中,并未真正的写入数据库文件。 执行 Commit ,才会将关于 statadb 的所有变更更新到数据库文件中。
  • ❽ 一旦提交数据,则可以使用 Dump 命令从数据库中查找此 stata 相关的所有数据,包括所有账户。 并以 JSON 格式返还。这里,我们将返还结果直接打印输出。

我们看到这些显示数据,直接对应我们刚刚的所有操作。 也只有合约账户才有 storage 和 code 。而外部账户的 codeHash 和 root 值相同,是一个默认值。

以太坊是银行帐户

账户是安全地进行以太坊交易的基础。 与在银行开户不同的是,以太坊的账户可以离线生成而不需要得到任何工作人员的许可, 并且这些账户是 完全匿名 的。 适用于生成账户的开源工具有很多,如网页工具、桌面软件、手机APP等。 它们遵循同一套账户生成标准。 一个用户也可以同时生成、保存、持有多个账户。

账户与账户状态¶

外部账户 (Externally Owned Account, EOA ) 与 智能合约 (Contract Account, CA )。

外部账户由 一把私钥 与该私钥对应的公开地址来表示。在一般情况下,私钥掌握在用户的手中。

智能合约账户 没有私钥 ,仅有公开的地址,它的行为由合约自身包含的代码逻辑来控制。

账户的状态(Acccount State)描述了一个账户当前的情况。 以太坊公链时时刻刻跟踪并维护着每一个账户的状态。 一个账户在初次接收或者发出交易后,都会形成初始状态。 随着时间的推移,每次针对该账户的交易将不断修改其状态。

../_images/Picture8.png

账户状态的内涵¶

  • nonce 已执行交易总数,用来标示该账户发出的交易数量;
  • balance 持币数量,记录用户的以太币余额;
  • storage hash 存储区的哈希值,指向智能合约账户的存储数据区;
  • code hash 代码区的哈希值,指向智能合约账户存储的智能合约代码。

../_images/Picture9.png

已执行交易总数¶

该值会随着用户不断发送交易而递增,保障用户发出的交易是按照顺序被收纳入最终的区块链。 因为在同一个账户中,已执行交易总数不可以在区块链中再次出现。 当用户创建智能合约时,要指定合约地址,该地址是由用户账户的已执行交易总数和用户账户地址联合计算而得出的。

假设我拥有一个账户,该数值为 13 如果我给人转账,则该数字增加到 14

存储区的哈希值¶

该值为 智能合约独有 ,外部账户不包含该值。 存储区即为智能合约在运行中,产生的数据的存储地。 在合约的生命周期里,该区域的内容被合约代码不断写入、读取。 存储区存放于以太坊网络节点的硬盘上。 存储区的内容通过散列函数得出校验哈希值,该值即为存储区的哈希值。

代码区的哈希值¶

该值为 智能合约独有,外部账户不包含该值。 代码区即为智能合约代码本身。 在合约的生命周期中,该区域的内容是不可更改的 只读状态。 代码区存放于以太坊网络节点的硬盘中,当运行时被读入虚拟机执行。代码区的内容通过散列函数得出校验哈希值,该值即为代码区的哈希值。

哈希算法就是通过一定的数学算法 y=Ϝ(x) 的单向函数,将不定长的输入值, 经过函数变换后变成定长的哈希值。 这个数学算法是不可逆向运算操作的(意即不可通过输出推断输入,却可通过输入轻松运算出输出), 并具有良好的抗碰撞特性。 唯一的输入对应了唯一输出,哪怕是改动一个输入字符,都可以让输出哈希值产生翻天覆地的变化。[1] 在数据校验领域中,哈希算法被用来对文档进行签名,以防止文档中途被篡改或者丢失字符。 在区块链中常用的安全哈希算法是 SHA3-256算法,即输出定长为256位的第三代哈希算法。[2]

没有钱包App, 如何生成账户?¶

普通用户最频繁使用的账户主要是外部账户(Externally Owned Account, EOA)。 这个账户可以用来发送/接受以太币,也可以发起部署智能合约的行为。 以太坊的外部账户仅由私钥(private key)与它所相对应的公开地址(address)组成。

Okay, 第一步,我如何生成私钥?

私钥 是一个32 bytes (以太坊是银行帐户 256 bits) 长度的随机数。用户需要一个可靠的随机源来产生该随机数,该随机数取值在0~2 256 之间。 私钥的举例如下所示(16进制表示)。生成私钥的逻辑如代码清单2-1所示。

私钥 bdb2c8d55b47e7c37dabdead589eec3d463b2de656ed6ba9b75143e72180ae09

在代码清单2-1中主要逻辑是生成一个32字节长度的随机数。我们选用了 Javascript 的 randombytes 库函数辅助我们生成该随机数。

第二步,公开地址是如何从私钥派生的呢?

这分为几个步骤:首先,我们特殊选定的椭圆曲线(ECDSA-secp256k1)算法 [3], 代入 私钥 作为参数进行运算,得出的结果为 公钥 。

这个过程是不可逆的,并且是唯一与私钥对应的。 其次,在生成公钥后,再将其进一步放入一个哈希算法生成哈希值,截取哈希值的最后40位16进制字符得到地址(160 bits或20 bytes)。 对于上述我们举例的的私钥,由其派生的 地址 如下表所示。

地址 0xda36cd6F5aF1CA5A226c02B3BD74E3F1BA354B9F
私钥 bdb2c8d55b47e7c37dabdead589eec3d463b2de656ed6ba9b75143e72180ae09

  • 32 字节私钥生成的长度为 65 字节的公钥。
  • 删除为首的一个字节 0x04 ,还剩 64 字节。
  • 将其放入 keccak256 哈希算法,生成一个 256 位的哈希值。
  • 截取哈希值的最后 20 字节, 即为所求的公开地址。
  • (可选)辅以 0x 的开头装饰,表明这是一个16进制的书面记录形式。

我生成的账户安全吗?

和一般的网站申请账户不同, 加密货币的账户仅需要可靠的软件在离线状态下生成 , 而不需要去特殊网站进行注册。 很多虚拟货币交易所的管理大额虚拟货币的账户都是通过上述方法在一台离线的计算机上生成的。 那么,如何保证每次生成的私钥不是已经被他人生成过的?在现实中,两个私钥碰撞的概率有多大呢?

我们已知:私钥地址空间有 2 256 ,而宇宙中的已知原子总数有 10 80 , 两者比较谁大谁小?我们做一个除法。

从上述算式可以看出,私钥空间比我们宇宙空间的原子总数的倍数还要多。 可以说在全人类都参与使用加密货币的情况下,即使每次交易都使用新的地址, 碰巧遇上他人私钥的概率比生活中选中一个原子去砸中另外一个原子的概率还要小。

智能合约地址的生成¶

  • 合约转出以太币,并非通过私钥签名方式。
  • 只有合约自身的逻辑代码能够管理它的以太币,除极少数例外(例如合约创建者销毁合约,合约收到的以太币将默认打给该创建者)。

我们将在动手实践环节中,用 web3 以太坊是银行帐户 向读者展示合约的部署生成过程,在这里仅演示当创建一个合约时,究竟发生了什么。代码如清单2-3所示。

  • 合约创建人(发送方)的账户地址( 20字节 )。
  • 发送方账户内的已发生交易总数 nonce 值。

为了得出合约的部署地址,将上述两个参数放入 RLP 函数进行编码,经由 keccak256 哈希算法算出哈希值,最终取出结果中的20 bytes,将其设定为合约地址。

RLP (Recursive Length Prefix)函数 [4] ,全名递归长度前缀编码函数,是以太坊序列化所采用的序列化和反序列化的主要方式。在进行网络传输、数据库存储之前,二进制数组数据都会经过这个函数进行编码,该函数的详细定义请参见以太坊的官方维基 以及本书4.2章节。

比特币跟以太币有何不同?比特币像钞票,以太坊是银行帐户

这促成了以太坊和比特币的另一个关键差异,布特林称之为以太坊的「第一类公民」(first-class citizen,程式语言中的术语,亦称First-class object,指能在程式执行期间,创造并做为参数传递给其他函数或存入一个变数的实体)——合约帐户和外部帐户拥有同等的权力,而这个特征也使得自动执行程式码的应用程式变得更加容易使用。如果区块链技术的目的是去掉中介者,这个概念就深植在以太坊的核心中。

布特林写道,有些应用程式可以建立在以太坊的基础上,例如数位货币、避险合约、网域名称系统、信誉系统(reputation system,一种由实体相互给出看法和评价,以确定这些实体的等级和类别的合作性筛选机制。

另一个例子是农作物保险。「怎么做?很简单,就是依据天气资料、而不是任何价格指数」,换言之,就是一种分散式的交易市场。类似的例子不胜枚举。

他想像的是一台世界电脑,把权力从那些傲慢的公司与政府的手中拿回来,让世界变得更有效率、更公平。可能性无限宽广。

以太坊则反其道而行,取消了一些功能。以太坊的协定不支持多签交易、多重输入与输出、杂凑码、锁定时间、甚至连比特币提供的许多功能也不支援。

比特币像钞票,以太坊是银行帐户

a3eb0fffadfe6f3adc1cfd77119f3b9e

图灵完备性是以数学家艾伦.图灵命名的概念。具有图灵完备性的机器,能执行任何程式码。比特币有一种支持某种运算的手稿语言,但以太坊的图灵完备语言,是为了支持程式设计师梦想的任何东西,而且依然以分散的方式运行。

「对,所以布特林把以太币称为”加密燃料“,它是推动以太坊网路运作的燃料。」乐文说。

以太坊和比特币一样,是采用工作量证明的区块链,这表示矿工会因为验证交易而获得以太币做为奖励。矿工决定要不要为了赚酬金而去处理那笔交易。以太坊把燃料跟以太币分开,用意是即便加密货币的价格会随着市场上的供需波动,运算成本仍可持平。

例如,一笔交易的运算成本是100 gas,它永远需要100 gas,但是发送者付给矿工去处理交易的以太币数量,则根据以太币的市价而定。

09e166ca984529bfd86014eda802b02c比特币和以太坊的帐户模式,就像钱包和存折

比特币是使用「未花费交易输出」(Unspent Transaction Output, UTXO)模式。比特币帐户的每一笔余额,是由其他交易剩余未花用的比特币所组成。一笔余额通常包括许多UTXO,就像一个实体钱包,里面可能包含许多面额的钞票和硬币。用比特币买东西,你可能必须使用UTXO的组合,就像你用十美元和五美元的纸钞去买价值十二美元的东西。这笔交易余下的三美元,将成为一个新的UTXO。

以太坊则是使用「帐户/余额」(Account/Balance)模式,追踪每个帐户的总余额或「状态」。如果说比特币的UTXO模式类似钞票和硬币,那么以太坊的模式比较像支存帐户,可以针对可领取的金额进行细腻的掌控,更容易执行较复杂的程式。

但以太坊则有两种帐户:外部拥有帐户(externally owned account)与合约帐户(contract account)。外部拥有帐户是由人们的私钥所控制,不含程式码。合约帐户是由程式码控制,每次合约帐户收到一则讯息,程式码就会啟动,让它把讯息读写到内部储存中、发送其他讯息,或创造新合约。

这促成了以太坊和比特币的另一个关键差异,布特林称之为以太坊的「第一类公民」(first-class citizen,程式语言中的术语,亦称First-class object,指能在程式执行期间,创造并做为参数传递给其他函数或存入一个变数的实体)——合约帐户和外部帐户拥有同等的权力,而这个特征也使得自动执行程式码的应用程式变得更加容易使用。如果区块链技术的目的是去掉中介者,这个概念就深植在以太坊的核心中。

布特林写道,有些应用程式可以建立在以太坊的基础上,例如数位货币、避险合约、网域名称系统、信誉系统(reputation system,一种由实体相互给出看法和评价,以确定这些实体的等级和类别的合作性筛选机制。

0a2bd043b9986b77f9c28a3938e3ea26

例如eBay的信誉系统,是在每一对用户完成一次交易之后,记录下双方的评级)、股东经营的公司(资金要转移到哪裡,可由法定人数的投资者来决定),「甚至有可能成为社群网路的基础」。

另一个例子是农作物保险。「怎么做?很简单,就是依据天气资料、而不是任何价格指数」,换言之,就是一种分散式的交易市场。类似的例子不胜枚举。

他想像的是一台世界电脑,把权力从那些傲慢的公司与政府的手中拿回来,让世界变得更有效率、更公平。可能性无限宽广。

以太坊则反其道而行,取消了一些功能。以太坊的协定不支持多签交易、多重输入与输出、杂凑码、锁定时间、甚至连比特币提供的许多功能也不支援。