在拥有55年历史的IBM 1401上开采比特币

受到用户发布的启发 mark_ablov通过使用纸和笔的比特币, ”我们决定,希克时间的读者会对原帖的作者Ken Shirriff设法实现的其他疯狂想法感兴趣。

上世纪60年代的IBM大型机能否用于开采比特币?我决定查看这个看似疯狂的想法。我将比特币哈希算法注入到IBM 1401的汇编代码中,并通过在这个古老的大型机的可行模型上运行它进行了实际测试。


在IBM 1401大型机上计算出SHA-256哈希值的卡,在卡后可以看到打印输出,其中显示了算法的输入和产生的哈希值

事实证明,使用这台计算机可以进行挖掘,但是此过程将花费大量时间,以至于即使整个宇宙的生命周期也可能不足以成功挖掘一个区块。

虽然现代硬件允许您每秒计算数十亿个哈希,但是计算机1401每次花费80秒来计算单个哈希。过去几十年来,计算机性能的进步是显而易见的,戈登·摩尔定律对此也有明确的描述。

上张照片显示了参与该实验的打孔卡以及使用行式打印机的SHA-256打印输出(第一张打孔卡仅用于美容-突破这种模式并不容易)。请注意,第二行以一组零结尾;这意味着成功的哈希。

比特币挖矿原理


最近,互联网用户可以相互转移的电子货币比特币(Bitcoin)变得非常流行。为了理解这种加密货币工作的本质,可以以一种会计日记帐的形式来表示比特币系统,该日记帐存储有关数字硬币(比特币)的拥有者及其拥有的硬币数量的记录。比特币会员可以相互转移数字硬币。

应当指出,比特币系统是分散式的:它没有一个可以监视交易进度的监管服务器。而是通过Internet上的数千台计算机通过分布式网络发送记录。

困难在于这样的分布式系统必须以某种方式确保所有用户都同意记录。也就是说,尽心尽责的用户必须确认交易的有效性并予以批准,尽管可能存在欺诈者和网络运行缓慢。解决这个问题的方法就是所谓的“采矿”。在采矿过程中,大约每10分钟会确认一大笔外向交易,因此被视为正式确认。

基于可靠密码学的挖掘过程非常复杂,因此没有人可以控制正在挖掘的交易。特别是,比特币系统的关键思想是工作的结果越来越困难,但易于验证。这就是所谓的“工作量证明”技术。

区块挖掘的过程需要大量的计算成本。但是,在确认阻止之后,对等用户可以轻松地验证其有效性。挖矿的复杂性可以防止欺诈性地使用比特币,而检查区块有效性的简便性使用户可以对交易的有效性充满信心。

挖矿的副作用是向系统中添加了新的比特币。目前,确认该区块的每个人都为此收到25个生成的比特币(现在以传统货币计算,这种数量的虚拟硬币的成本约为6000美元)。这项鼓励措施鼓励矿工努力工作,并将资源用于采矿。如果有机会每10分钟获得6000美元,采矿似乎是一个真正的“金矿”,鼓励用户在采矿硬件上花费大量资金。


在计算机历史博物馆中展出了行式打印机和IBM 1401大型机。这台计算机正在运行我的程序。控制台位于左上方。计算机上深色的矩形面板是机架的“门”,它们可以倾斜,为维护提供了方便。

采矿过程非常复杂,但是结果很容易验证。比特币挖矿使用具有双倍SHA-256哈希函数的加密技术。散列在输入处获取数据块并将其减少为较低的散列值(在这种情况下为256位)。

密码散列算法将不允许您获得所需的散列值,而不必对输入端的大量数据进行排序。但是,找到提供期望值的输入后,每个人都可以轻松检查哈希。因此,加密散列是实现“工作量证明”比特币的好方法。

更详细地说,为了分散一个区块,首先需要将新事务收集到一个区块中。然后,您需要对块进行哈希处理以获得(基本上是随机的)该块的哈希值。如果哈希值以16个零开头,则认为该块已成功确认并发送到比特币网络。在大多数情况下,哈希无法成功执行,因此您需要进行十亿次以上的计算操作,然后稍稍更改一下块并再次尝试。大约每10分钟,某人成功地成功确认该阻止,然后该过程再次开始。这让人想起矿工参加的彩票,一次又一次尝试,直到有人成为“赢家”为止。哈希处理的复杂性很难形象化:在地球的整个沙子中查找沙粒要比查找有效的哈希值容易。为了搜索此类哈希值,矿工使用配备了特殊硬件的数据中心进行挖掘。

我特意简化了本文中的许多解释。如果您想了解有关比特币系统和采矿的更多信息,我建议您研究我的文章开采比特币艰难经验和比特币开采严酷教训

比特币SHA-256哈希算法


现在,我将看一下比特币使用的哈希函数,该函数基于一种称为SHA-256的标准加密哈希函数。比特币系统使用“双SHA-256”。这意味着SHA-256功能执行两次。 SHA-256算法非常简单,您仅需使用铅笔和纸即可执行它,并且该算法允许您以不可预测的方式混合数据。该算法在输入处接受64个字节的块,对数据进行加密处理,并生成256位(32个字节)的加密数据。该算法使用一轮,重复64次。下图显示了该算法的一轮运算,它占用了8个4字节的块,从A到H,执行几次运算并为A到N产生新的值。


圆角SHA-256,例如,来自Wikipedia的示例,作者:kockmeyer,CC BY-SA 3.0。

深蓝色块以非线性方式混合位,这对于密码分析是困难的。 (如果您设法找到数学上更快的方法来成功获得哈希,则可以控制比特币的挖掘)。单元格“ select” Ch基于输入E的值从F或G中选择位。单元格“ sum”对位A(或E)进行旋转以生成三个循环移位的版本,然后将它们以模2求和。

Ma多数单元检查A,B和C每个位置的位,并根据多数中的哪个值选择0或1。红细胞执行32位加法,为A和E生成新值。输入Wt基于经过稍微处理的输入。(这是将输入块引入算法的地方。)输入Kt是为每一轮定义的常数。

根据上面的图示,每轮仅更改A和E.剩余值将保持不变。A的旧值变成B的新值,B的旧值变成C的新值,依此类推。尽管每轮SHA-256都会略微更改数据,但在64轮之后,输入数据会完全混合在一起,从而产生不可预测的哈希值。

伊拉克1401


我决定在IBM 1401大型机上执行此算法,这台计算机于1959年问世,到60年代中期成为最畅销的计算机-当时有超过一万台计算机处于活跃状态。即使在1960年,1401电脑也不是一台功能强大的电脑。但是,对于以前无法拥有一台计算机的中型公司来说,它是负担得起的,原因是它可以以很少的钱租用-每月2500美元。

IBM 1401不使用硅芯片。而且,在这台计算机上根本没有芯片。它的晶体管建立在半导体,锗晶体之上,而锗晶体早于硅。晶体管和其他组件一起安装在大小为SMS的扑克牌上。计算机包含成千上万个此类卡,这些卡以称为“门”的机架形式安装。 IBM 1401具有二十个此类“门”,这些“门”已经提出用于计算机维护。在上图中,一个打开的门可见,可以访问微芯片和电缆。


该图显示了IBM 1401大型机的开放式机架(所谓的“门”),图上显示了连接到电路的SMS卡。该机架驱动磁带机

这种计算机的工作原理与现代PC明显不同。这台计算机不是使用8位字节,而是使用基于二进制编码的十进制数字(BCD)的6位字符。由于该计算机是用于解决经济问题的计算机,因此它使用十进制而不是二进制算术,并且存储器中的每个字符的数字值均为0到9。磁芯上的计算机存储器包含4000个字符。洗碗机大小的内存扩展模块使内存容量增加了12,000个字符。使用穿孔卡将数据输入计算机。读卡器从卡中读取数据和程序。输出数据通过高速排水打印机打印出来或在地图上打孔。

计算机历史博物馆计算机历史博物馆在Mountain View中,它有两个工作的IBM 1401大型机,其中一个运行了SHA-256哈希码。在我的文章IBM 1401上的分形中,我会更多地谈论IBM 1401

在IBM 1401上运行SHA-256


当然,在可以选择执行SHA-256哈希算法的所有机器中,IBM 1401计算机是最差的。为了有效地工作,该算法要求机器能够以32位字执行位操作。不幸的是,IBM 1401不支持32位字或字节。该计算机使用6位字符,并且不允许位操作。此外,在其中使用十进制算术代替二进制。因此,计算机1401上的算法对于用户而言将是缓慢且不便的。

我最终每位使用一个字符。 32位值存储为32个字符,即“ 0”或“ 1”。我的代码必须逐个字符执行按位运算,乘法和加法,检查每个字符并决定如何处理它。如您所料,代码执行花费了很长时间。

接下来,我介绍我编写的汇编代码。通常,注释中描述了代码的原理。在代码的末尾,有一个十六进制形式的SHA-256算法必需的常量表。由于计算机1401不支持十六进制格式,因此我不得不编写自己的例程以转换十六进制和二进制格式。在本文中,我将不解释IBM 1401的汇编代码,仅强调它与现代计算机使用的代码有很大不同。此代码不调用子例程,也不返回结果。由于缺少通用寄存器,因此在内存中进行操作。

在扰流板下查找代码:
隐藏文字
job  bitcoin
     * SHA-256 hash
     * Ken Shirriff  http://righto.com
               ctl  6641

               org  087
     X1        dcw  @000@
               org  092
     X2        dcw  @000@
               org  097
     X3        dcw  @000@
     
               org  333
     start     cs   299
               r
               sw   001
               lca  064, input0
               mcw  064, 264
               w
     * Initialize word marks on storage
               mcw  +s0, x3

     wmloop    sw   0&x3  
               ma   @032@, x3
               c    +h7+32, x3
               bu   wmloop
     
               mcw  +input-127, x3      * Put input into warr[0] to warr[15]
               mcw  +warr, x1
               mcw  @128@, tobinc
               b    tobin
     
     * Compute message schedule array w[0..63]
  
               mcw  @16@, i
     * i is word index 16-63   
     * x1 is start of warr[i-16], i.e. bit 0 (bit 0 on left, bit 31 on right)   
               mcw  +warr, x1
     wloop     c    @64@, i
               be   wloopd
     
     * Compute s0
               mcw  +s0, x2
               za   +0, 31&x2               * Zero s0
     * Add w[i-15] rightrotate 7
               sw   7&x2               * Wordmark at bit 7 (from left) of s0
               a    56&x1, 31&x2       * Right shifted: 32+31-7 = bit 24 of w[i-15], 31 = end of s0
               a    63&x1, 6&x2        * Wrapped: 32+31 = end of w[i-15], 7-1 = bit 6 of s0   
               cw   7&x2               * Clear wordmark
     * Add w[i-15] rightrotate 18
               sw   18&x2              * Wordmark at bit 18 (from left) of s0
               a    45&x1, 31&x2       * Right shifted: 32+31-18 = bit 13 of w[i-15], 31 = end of s0
               a    63&x1, 17&x2       * Wrapped: 32+31 = end of w[i-15], 18-1 = bit 17 of s0   
               cw   18&x2              * Clear wordmark
     * Add w[i-15] rightshift 3
               sw   3&x2               * Wordmark at bit 3 (from left) of s0
               a    60&x1, 31&x2       * Right shifted: 32+31-3 = bit 28 of w[i-15], 31 = end of s0
               cw   3&x2               * Clear wordmark
     * Convert sum to xor
               mcw  x1, x1tmp
               mcw  +s0+31, x1         * x1 = right end of s0
               mcw  @032@, x2          * Process 32 bits
               b    xor
               sw   s0                 * Restore wordmark cleared by xor
     
               mcw  x1tmp, x1
     
     * Compute s1         
               mcw  +s1, x2
               za   +0, 31&x2               * Zero s1
     * Add w[i-2] rightrotate 17
               sw   17&x2              * Wordmark at bit 17 (from left) of s1
               a    462&x1, 31&x2      * Right shifted: 14*32+31-17 = bit 14 of w[i-2], 31 = end of s1
               a    479&x1, 16&x2      * Wrapped: 14*32+31 = end of w[i-2], 17-1 = bit 16 of s1   
               cw   17&x2              * Clear wordmark
     * Add w[i-2] rightrotate 19
               sw   19&x2              * Wordmark at bit 19 (from left) of s1
               a    460&x1, 31&x2      * Right shifted: 14*32+31-19 = bit 12 of w[i-2], 31 = end of s1
               a    479&x1, 18&x2      * Wrapped: 14*32+31 = end of w[i-2], 19-1 = bit 18 of s1  
               cw   19&x2              * Clear wordmark
     * Add w[i-2] rightshift 10
               sw   10&x2              * Wordmark at bit 10 (from left) of s1
               a    469&x1, 31&x2      * Right shifted: 14*32+31-10 = bit 21 of w[i-2], 31 = end of s1
               cw   10&x2              * Clear wordmark
     * Convert sum to xor
               mcw  +s1+31, x1         * x1 = right end of s1
               mcw  @032@, x2          * Process 32 bits
               b    xor
               sw   s1                 * Restore wordmark cleared by xor
     
     * Compute w[i] := w[i-16] + s0 + w[i-7] + s1
               mcw  x1tmp, x1
               a    s1+31, s0+31       * Add s1 to s0
               a    31&x1, s0+31       * Add w[i-16] to s0
               a    319&x1, s0+31      * Add 9*32+31 = w[i-7] to s0
     * Convert bit sum to 32-bit sum
               mcw  +s0+31, x1         * x1 = right end of s0
               mcw  @032@, x2          * Process 32 bits
               b    sum
               sw   s0                 * Restore wordmark cleared by sum
     

     
               mcw  x1tmp, x1
               mcw  s0+31, 543&x1      * Move s0 to w[i]
       
              
               ma   @032@, x1
               a    +1, i
               mz   @0@, i
               b    wloop
     
     x1tmp     dcw  #5
     

     * Initialize: Copy hex h0init-h7init into binary h0-h7
     wloopd    mcw  +h0init-7, x3
               mcw  +h0, x1
               mcw  @064@, tobinc       * 8*8 hex digits
               b    tobin
     
     
     * Initialize a-h from h0-h7
               mcw  @000@, x1
     ilp       mcw  h0+31&x1, a+31&x1
               ma   @032@, x1
               c    x1, @256@
               bu   ilp
     
               mcw  @000@, bitidx      * bitidx = i*32 = bit index
               mcw  @000@, kidx        * kidx = i*8 = key index
                

     * Compute s1 from e        
     mainlp    mcw  +e, x1
               mcw  +s1, x2
               za   +0, 31&x2               * Zero s1
     * Add e rightrotate 6
               sw   6&x2               * Wordmark at bit 6 (from left) of s1
               a    25&x1, 31&x2       * Right shifted: 31-6 = bit 25 of e, 31 = end of s1
               a    31&x1, 5&x2        * Wrapped: 31 = end of e, 6-1 = bit 5 of s1   
               cw   6&x2               * Clear wordmark
     * Add e rightrotate 11
               sw   11&x2              * Wordmark at bit 11 (from left) of s1
               a    20&x1, 31&x2       * Right shifted: 31-11 = bit 20 of e, 31 = end of s1
               a    31&x1, 10&x2       * Wrapped: 31 = end of e, 11-1 = bit 10 of s1   
               cw   11&x2              * Clear wordmark
     * Add e rightrotate 25
               sw   25&x2              * Wordmark at bit 25 (from left) of s1
               a    6&x1, 31&x2        * Right shifted: 31-25 = bit 6 of e, 31 = end of s1
               a    31&x1, 24&x2       * Wrapped: 31 = end of e, 25-1 = bit 24 of s1   
               cw   25&x2              * Clear wordmark
     * Convert sum to xor
               mcw  +s1+31, x1         * x1 = right end of s1
               mcw  @032@, x2          * Process 32 bits
               b    xor
               sw   s1                 * Restore wordmark cleared by xor

     * Compute ch: choose function
               mcw  @000@, x1          * x1 is index from 0 to 31
     chl       c    e&x1, @0@
               be   chzero
               mn   f&x1, ch&x1        * for 1, select f bit
               b    chincr
     chzero    mn   g&x1, ch&x1        * for 0, select g bit
     chincr    a    +1, x1
               mz   @0@, x1
               c    @032@, x1
               bu   chl

     * Compute temp1: k[i] + h + S1 + ch + w[i]
               cs   299
               mcw  +k-7, x3            * Convert k[i] to binary in temp1
               ma   kidx, x3
               mcw  +temp1, x1
               mcw  @008@, tobinc       * 8 hex digits
               b    tobin
               mcw  @237@, x3
               mcw  +temp1, x1
               mcw  @008@, tobinc
               b    tohex
               a    h+31, temp1+31     * +h
               a    s1+31, temp1+31    * +s1
               a    ch+31, temp1+31    * +ch
               mcw  bitidx, x1
               a    warr+31&x1, temp1+31         * + w[i]
     * Convert bit sum to 32-bit sum
               mcw  +temp1+31, x1      * x1 = right end of temp1
               b    sum
  

     * Compute s0 from a
               mcw  +a, x1
               mcw  +s0, x2
               za   +0, 31&x2               * Zero s0
     * Add a rightrotate 2
               sw   2&x2               * Wordmark at bit 2 (from left) of s0
               a    29&x1, 31&x2       * Right shifted: 31-2 = bit 29 of a, 31 = end of s0
               a    31&x1, 1&x2        * Wrapped: 31 = end of a, 2-1 = bit 1 of s0   
               cw   2&x2               * Clear wordmark
     * Add a rightrotate 13
               sw   13&x2              * Wordmark at bit 13 (from left) of s0
               a    18&x1, 31&x2       * Right shifted: 31-13 = bit 18 of a, 31 = end of s0
               a    31&x1, 12&x2       * Wrapped: 31 = end of a, 13-1 = bit 12 of s0   
               cw   13&x2              * Clear wordmark
     * Add a rightrotate 22
               sw   22&x2              * Wordmark at bit 22 (from left) of s0
               a    9&x1, 31&x2        * Right shifted: 31-22 = bit 9 of a, 31 = end of s0
               a    31&x1, 21&x2       * Wrapped: 31 = end of a, 22-1 = bit 21 of s0   
               cw   22&x2              * Clear wordmark
     * Convert sum to xor
               mcw  +s0+31, x1         * x1 = right end of s0
               mcw  @032@, x2          * Process 32 bits
               b    xor
               sw   s0                 * Restore wordmark cleared by xor

     * Compute maj(a, b, c): majority function
               za   +0, maj+31
               a    a+31, maj+31
               a    b+31, maj+31
               a    c+31, maj+31
               mz   @0@, maj+31
               mcw  @000@, x1          * x1 is index from 0 to 31
     mjl       c    maj&x1, @2@
               bh   mjzero
               mn   @1@, maj&x1       * majority of the 3 bits is 1
               b    mjincr
     mjzero    mn   @0@, maj&x1       * majority of the 3 bits is 0
     mjincr    a    +1, x1
               mz   @0@, x1
               c    @032@, x1
               bu   mjl

     * Compute temp2: S0 + maj
               za   +0, temp2+31
               a    s0+31, temp2+31
               a    maj+31, temp2+31
     * Convert bit sum to 32-bit sum
               mcw  +temp2+31, x1      * x1 = right end of temp1
               b    sum
     
               mcw  g+31, h+31         * h := g
               mcw  f+31, g+31         * g := f
               mcw  e+31, f+31         * f := e
               za   +0, e+31           * e := d + temp1
               a    d+31, e+31
               a    temp1+31, e+31
               mcw  +e+31, x1          * Convert sum to 32-bit sum
               b    sum
               mcw  c+31, d+31         * d := c
               mcw  b+31, c+31         * c := b
               mcw  a+31, b+31         * b := a
               za   +0, a+31           * a := temp1 + temp2
               a    temp1+31, a+31
               a    temp2+31, a+31
               mcw  +a+31, x1          * Convert sum to 32-bit sum
               b    sum

               a    @8@, kidx          * Increment kidx by 8 chars
               mz   @0@, kidx
               ma   @032@, bitidx      * Increment bitidx by 32 bits
               c    @!48@, bitidx      * Compare to 2048
               bu   mainlp

     * Add a-h to h0-h7
               cs   299
               mcw  @00000@, x1tmp  
     add1      mcw  x1tmp, x1
               a    a+31&x1, h0+31&x1
               ma   +h0+31, x1          * Convert sum to 32-bit sum
               b    sum     
               ma   @032@, x1tmp
               c    @00256@, x1tmp
               bu   add1
               mcw  @201@, x3
               mcw  +h0, x1
               mcw  @064@, tobinc
               b    tohex
               w
               mcw  280, 180
               p
               p

     finis     h
               b    finis

      
     * Converts sum of bits to xor
     * X1 is right end of word
     * X2 is bit count    
     * Note: clears word marks
     xor       sbr  xorx&3
     xorl      c    @000@, x2
               be   xorx
     xorfix    mz   @0@, 0&x1          * Clear zone
               c    0&x1, @2@
               bh   xorok
               sw   0&x1               * Subtract 2 and loop
               s    +2, 0&x1
               cw   0&x1
               b    xorfix
     xorok     ma   @I9I@, x1         * x1 -= 1
               s    +1, x2             * x2 -= 1
               mz   @0@, x2
               b    xorl               * loop
     
     xorx      b    @000@
     
     * Converts sum of bits to sum (i.e. propagate carries if digit > 1)
     * X1 is right end of word
     * Ends at word mark
     sum       sbr  sumx&3
     suml      mz   @0@, 0&x1          * Clear zone
               c    0&x1, @2@          * If digit is <2, then ok
               bh   sumok
               s    +2, 0&x1           * Subtract 2 from digit
               bwz  suml, 0&x1, 1      * Skip carry if at wordmark
               a    @1@, 15999&x1      * Add 1 to previous position
               b    suml               * Loop
     sumok     bwz  sumx,0&x1,1        * Quit if at wordmark
               ma   @I9I@, x1          * x1 -= 1
               b    suml               * loop
     sumx      b    @000@              * return
     
     * Converts binary to string of hex digits
     * X1 points to start (left) of binary
     * X3 points to start (left) of hex buffer
     * X1, X2, X3 destroyed
     * tobinc holds count (# of hex digits)
     tohex     sbr  tohexx&3
     tohexl    c    @000@, tobinc      * check counter
               be   tohexx
               s    @1@, tobinc        * decrement counter
               mz   @0@, tobinc
               b    tohex4
               mcw  hexchr, 0&x3
               ma   @004@, X1
               ma   @001@, X3
               b    tohexl             * loop
     tohexx    b    @000@ 
     

     
     * X1 points to 4 bits
     * Convert to hex char and write into hexchr
     * X2 destroyed

     tohex4    sbr  tohx4x&3
               mcw  @000@, x2
               c    3&X1, @1@
               bu   tohx1
               a    +1, x2
     tohx1     c    2&X1, @1@
               bu   tohx2
               a    +2, x2
     tohx2     c    1&x1, @1@
               bu   tohx4
               a    +4, x2
     tohx4     c    0&x1, @1@
               bu   tohx8
               a    +8, x2
     tohx8     mz   @0@, x2
               mcw  hextab-15&x2, hexchr
     tohx4x    b    @000@
     
     * Converts string of hex digits to binary
     * X3 points to start (left) of hex digits
     * X1 points to start (left) of binary digits
     * tobinc holds count (# of hex digits)
     * X1, X3 destroyed
     tobin     sbr  tobinx&3
     tobinl    c    @000@, tobinc      * check counter
               be   tobinx
               s    @1@, tobinc        * decrement counter
               mz   @0@, tobinc
               mcw  0&X3, hexchr
               b    tobin4             * convert 1 char
               ma   @004@, X1
               ma   @001@, X3
               b    tobinl             * loop
     tobinx    b    @000@
               
     
     tobinc    dcw  @000@
     * Convert hex digit to binary
     * Digit in hexchr (destroyed)
     * Bits written to x1, ..., x1+3
     tobin4    sbr  tobn4x&3
               mcw  @0000@, 3+x1   * Start with zero bits
               bwz  norm,hexchr,2  * Branch if no zone
              
               mcw  @1@, 0&X1
               a    @1@, hexchr    * Convert letter to value: A (1) -> 2, F (6) -> 7
               mz   @0@, hexchr
               b    tob4
     norm      c    @8@, hexchr
               bl   tob4
               mcw  @1@, 0&X1
               s    @8@, hexchr
               mz   @0@, hexchr
     tob4      c    @4@, hexchr
               bl   tob2
               mcw  @1@, 1&X1
               s    @4@, hexchr
               mz   @0@, hexchr
     tob2      c    @2@, hexchr
               bl   tob1
               mcw  @1@, 2&X1
               s    @2@, hexchr
               mz   @0@, hexchr
     tob1      c    @1@, hexchr
               bl   tobn4x
               mcw  @1@, 3&X1
     tobn4x    b    @000@          


     
     * Message schedule array is 64 entries of 32 bits = 2048 bits.
               org  3000
     warr      equ  3000
     
     s0        equ  warr+2047                *32 bits
     s1        equ  s0+32 
     ch        equ  s1+32              *32 bits

     temp1     equ  ch+32               *32 bits
     
     temp2     equ  temp1+32                *32 bits
     
     maj       equ  temp2+32                *32 bits
     
     a         equ  maj+32
     b         equ  a+32
     c         equ  b+32
     d         equ  c+32
     e         equ  d+32
     f         equ  e+32
     g         equ  f+32
     h         equ  g+32
     h0        equ  h+32
     h1        equ  h0+32
     h2        equ  h1+32
     h3        equ  h2+32
     h4        equ  h3+32
     h5        equ  h4+32
     h6        equ  h5+32
     h7        equ  h6+32
               org  h7+32
 
     hexchr    dcw  @0@
     hextab    dcw  @0123456789abcdef@    
     i         dcw  @00@               * Loop counter for w computation
     bitidx    dcw  #3
     kidx      dcw  #3         
     
     * 64 round constants for SHA-256
     k         dcw  @428a2f98@
               dcw  @71374491@
               dcw  @b5c0fbcf@
               dcw  @e9b5dba5@
               dcw  @3956c25b@
               dcw  @59f111f1@
               dcw  @923f82a4@
               dcw  @ab1c5ed5@
               dcw  @d807aa98@
               dcw  @12835b01@
               dcw  @243185be@
               dcw  @550c7dc3@
               dcw  @72be5d74@
               dcw  @80deb1fe@
               dcw  @9bdc06a7@
               dcw  @c19bf174@
               dcw  @e49b69c1@
               dcw  @efbe4786@
               dcw  @0fc19dc6@
               dcw  @240ca1cc@
               dcw  @2de92c6f@
               dcw  @4a7484aa@
               dcw  @5cb0a9dc@
               dcw  @76f988da@
               dcw  @983e5152@
               dcw  @a831c66d@
               dcw  @b00327c8@
               dcw  @bf597fc7@
               dcw  @c6e00bf3@
               dcw  @d5a79147@
               dcw  @06ca6351@
               dcw  @14292967@
               dcw  @27b70a85@
               dcw  @2e1b2138@
               dcw  @4d2c6dfc@
               dcw  @53380d13@
               dcw  @650a7354@
               dcw  @766a0abb@
               dcw  @81c2c92e@
               dcw  @92722c85@
               dcw  @a2bfe8a1@
               dcw  @a81a664b@
               dcw  @c24b8b70@
               dcw  @c76c51a3@
               dcw  @d192e819@
               dcw  @d6990624@
               dcw  @f40e3585@
               dcw  @106aa070@
               dcw  @19a4c116@
               dcw  @1e376c08@
               dcw  @2748774c@
               dcw  @34b0bcb5@
               dcw  @391c0cb3@
               dcw  @4ed8aa4a@
               dcw  @5b9cca4f@
               dcw  @682e6ff3@
               dcw  @748f82ee@
               dcw  @78a5636f@
               dcw  @84c87814@
               dcw  @8cc70208@
               dcw  @90befffa@
               dcw  @a4506ceb@
               dcw  @bef9a3f7@
               dcw  @c67178f2@
     * 8 initial hash values for SHA-256
     h0init    dcw  @6a09e667@
     h1init    dcw  @bb67ae85@
     h2init    dcw  @3c6ef372@
     h3init    dcw  @a54ff53a@
     h4init    dcw  @510e527f@
     h5init    dcw  @9b05688c@
     h6init    dcw  @1f83d9ab@
     h7init    dcw  @5be0cd19@


     input0    equ  h7init+64
               org  h7init+65

               dc   @80000000000000000000000000000000@
     input     dc   @00000000000000000000000000000100@      * 512 bits with the mostly-zero padding

               end  start

该可执行程序已应用于85张打孔卡(您已在本文开头看到了它们)。我还用哈希算法制作了打孔卡。为了运行该程序,我必须将打孔的卡加载到读卡器中,然后单击“加载”按钮。读卡器每分钟处理800张卡。因此,只花了几秒钟就下载了该程序。在程序执行过程中,计算机控制台(请参见下图)发狂地闪烁40秒钟。最终,打印机为我打印了最后的哈希值(您也可以在文章的开头看到打印结果),然后将结果应用于新的打孔卡。由于比特币挖掘使用SHA-256双重哈希,因此挖掘哈希过程花费了两倍的时间(80秒)。


计算SHA-256哈希值时IBM 1401控制台的辛苦工作

性能比较


IBM 1401计算机可以在80秒内计算SHA-256双哈希值。为了完成此任务,计算机消耗的功率约为3,000瓦,与电炉或干衣机的功率大致相同。一次,基本的IBM 1401系统成本为125,600美元。在2015年的现实中,这大约是一百万美元。同时,现在您可以花50美元购买一个USB闪存驱动器用于采矿,该驱动器具有专用集成电路(ASIC USB采矿器)。这款USB采矿机每秒执行36亿次哈希运算,而功耗约为4瓦。
如此重要的性能指标归因于以下几个因素:根据摩尔定律,过去50年中计算机性能急剧提高;由于计算机中使用小数运算来解决商业问题而导致的性能损失;忙于计算二进制哈希码;以及传统比特币采矿硬件的两面。

总结一下。要考虑该流程的当前要求,要开采该区块,IBM 1401计算机将需要大约5x10 ^ 14年(这是当前宇宙年龄的40,000倍)。耗电成本约为10 ^ 18美元。结果,您将获得25个比特币,其货币价值约为6,000美元。因此,在IBM 1401大型机上开采比特币不能被称为盈利业务。下图比较了上世纪60年代的计算机芯片和现代选项,清楚地展示了技术进步。


: SMS , IBM 1401. . . : Bitfury ASIC 2-3 . : zeptobars (CC BY 3.0)


由于缺乏通过网络传输数据的能力,您可能会认为比特币与上世纪60年代的技术不兼容。有人需要将带有区块链的打孔卡发送到其他计算机吗?通过网络进行计算机之间的通信是很久以前出现的。早在1941年,IBM就支持所谓的遥测(远程)数据处理过程。在60年代,IBM 1401可以连接到IBM 1009数据传输设备(IBM 1009数据传输单元)-调制解调器大小与洗碗机相同,可使计算机通过电话线以每秒300个字符的速度相互交换数据。也就是说,从理论上讲,基于上世纪60年代的技术构建比特币网络是完全可能的。不幸的是,我无法获得用于远程处理数据的设备并测试该理论。


IBM 1009数据传输设备,1960年出现了具有洗碗机大小的调制解调器。有了它,就可以通过电话线每秒最多传输300个字符。图片来源:IBM数据处理系统简介)

发现


在古代大型机的汇编语言中使用SHA-256已成为一种困难而有趣的体验。我期望有更好的性能(即使与我在12分钟内设置的Mandelbrot相比)。对于像SHA-256这样的二进制算法,商用计算机的十进制算术并不是最佳选择。但是,即使在没有集成电路的计算机上也可以执行比特币挖掘算法。因此,如果突然的某种暂时性崩溃将我带到1960年,我可以建立一个比特币网络。

山景计算机历史博物馆在每周三和周六展示正在运行的IBM 1401,如果您碰巧在附近,则一定要检查时间表以了解一下工作。而且,如果您告诉展示我正在运行IBM 1401的博物馆工作人员,他们甚至可能启动我的Pi程序

我要感谢计算机历史博物馆和1401年计算机恢复小组的成员:Robert Garner,Ed Thelen,Van Snyder,尤其是Stan Paddock。ibm-1401.info团队网站上有许多有关1401计算机以及如何还原它的有趣信息。

说明


值得注意的是,我并没有破坏IBM 1401上的实际功能块-计算机历史博物馆不希望这样做。就像我说的那样,拥有工作的IBM 1401,您将无法在采矿上赚钱。但是,我设法在IBM 1401机器上实现并执行SHA-256算法,因此证明了理论上的挖掘是可能的。而且,我将揭示找到有效哈希的秘密-我只是使用了已经开采的代码块

希望您喜欢我们的翻译

Source: https://habr.com/ru/post/zh-CN380635/


All Articles