├── .gitignore ├── ext ├── spu │ ├── spu_slih.h │ ├── worker.h │ ├── util.h │ ├── sha256.h │ ├── test.c │ ├── params.h │ ├── Makefile │ ├── util.c │ ├── spu_slih.c │ ├── worker.c │ ├── main.c │ ├── spu_flih.s │ └── sha256.c ├── extconf.rb ├── cellminer.c ├── ppu │ ├── util.h │ ├── params.h │ ├── sha256.h │ ├── test.c │ ├── Makefile │ ├── util.c │ ├── worker.c │ └── sha256.c ├── depend ├── ppu_miner.c └── spu_miner.c ├── COPYRIGHT ├── cellminer ├── README ├── Makefile ├── bitcoin.rb ├── sha256.rb ├── cellminer.rb └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | *.elf 4 | *.a 5 | *.log 6 | depend.auto 7 | ext/Makefile 8 | core 9 | -------------------------------------------------------------------------------- /ext/spu/spu_slih.h: -------------------------------------------------------------------------------- 1 | 2 | # ifndef SPU_SLIH_H 3 | # define SPU_SLIH_H 4 | 5 | typedef unsigned int (*spu_slih_func)(unsigned int); 6 | 7 | void spu_slih_register(unsigned int mask, spu_slih_func func); 8 | 9 | # endif 10 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | 2 | cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | Copyright © 2011 Robert Leslie 4 | 5 | This program is free software; you can redistribute it and/or modify it 6 | under the terms of the GNU General Public License (version 2) as 7 | published by the Free Software Foundation. 8 | 9 | This program is distributed in the hope that it will be useful, but 10 | WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License along 15 | with this program; if not, write to the Free Software Foundation, Inc., 16 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | 18 | -------------------------------------------------------------------------------- /ext/spu/worker.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # ifndef WORKER_H 20 | # define WORKER_H 21 | 22 | # include "params.h" 23 | 24 | int work_on(struct worker_params *); 25 | 26 | # endif 27 | -------------------------------------------------------------------------------- /cellminer: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby1.9.1 2 | # -*- mode: ruby -*- 3 | # 4 | # cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 5 | # Copyright © 2011 Robert Leslie 6 | # 7 | # This program is free software; you can redistribute it and/or modify it 8 | # under the terms of the GNU General Public License (version 2) as 9 | # published by the Free Software Foundation. 10 | # 11 | # This program is distributed in the hope that it will be useful, but 12 | # WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along 17 | # with this program; if not, write to the Free Software Foundation, Inc., 18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | # 20 | 21 | require_relative 'cellminer.rb' 22 | 23 | begin 24 | CellMiner.new(ARGV).main 25 | rescue Interrupt 26 | $stderr.puts 27 | $stderr.puts "Interrupt" 28 | end 29 | -------------------------------------------------------------------------------- /ext/extconf.rb: -------------------------------------------------------------------------------- 1 | # 2 | # cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | # Copyright © 2011 Robert Leslie 4 | # 5 | # This program is free software; you can redistribute it and/or modify it 6 | # under the terms of the GNU General Public License (version 2) as 7 | # published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, but 10 | # WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along 15 | # with this program; if not, write to the Free Software Foundation, Inc., 16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | # 18 | 19 | require 'mkmf' 20 | 21 | $objs = ['cellminer.o', 22 | 'spu_miner.o', 'spu_worker.o', 23 | 'ppu_miner.o', 'ppu/worker.a'] 24 | 25 | $CFLAGS << ' -Wall' 26 | 27 | raise "missing libspe2" unless have_library('spe2', 'spe_context_run') 28 | 29 | create_makefile 'cellminer' 30 | -------------------------------------------------------------------------------- /ext/cellminer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # include 20 | 21 | extern void Init_spu_miner(VALUE); 22 | extern void Init_ppu_miner(VALUE); 23 | 24 | void Init_cellminer(void) 25 | { 26 | VALUE mBitcoin; 27 | 28 | mBitcoin = rb_define_module("Bitcoin"); 29 | 30 | Init_spu_miner(mBitcoin); 31 | Init_ppu_miner(mBitcoin); 32 | } 33 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | This is a Bitcoin miner for the Cell Broadband Engine Architecture (CBEA). It 3 | was developed on a PS3 using Debian GNU/Linux 6.0.1. 4 | 5 | Bitcoin donations accepted: 18xDLQsJ94ihhx5YovqAhVY2b9SC5b81h 6 | 7 | Requirements 8 | ============ 9 | 10 | Debian Packages [aptitude install ...] 11 | --------------- 12 | * make 13 | * gcc 14 | * binutils-spu 15 | * ruby1.9.1-dev 16 | * libspe2-dev 17 | > gcc-spu 18 | > binutils 19 | > ruby1.9.1 20 | > libspe2-2 21 | 22 | (packages marked > should be included automatically as dependencies of 23 | packages marked *) 24 | 25 | Ruby Gems [gem1.9.1 install ...] 26 | --------- 27 | * net-http-persistent 28 | 29 | System 30 | ------ 31 | 32 | In order to make use of your SPEs under Linux, you must have spufs mounted on 33 | /spu. For example: 34 | 35 | # mount -t spufs spufs /spu 36 | 37 | Or equivalently, ensure /etc/fstab contains a line similar to the following: 38 | 39 | spufs /spu spufs defaults 0 0 40 | 41 | Building 42 | ======== 43 | 44 | $ make 45 | 46 | Running 47 | ======= 48 | 49 | $ ./cellminer --help 50 | 51 | RPC username and password will default to those found in 52 | ~/.bitcoin/bitcoin.conf. 53 | 54 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | # Copyright © 2011 Robert Leslie 4 | # 5 | # This program is free software; you can redistribute it and/or modify it 6 | # under the terms of the GNU General Public License (version 2) as 7 | # published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, but 10 | # WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along 15 | # with this program; if not, write to the Free Software Foundation, Inc., 16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | # 18 | 19 | RUBY = ruby1.9.1 20 | 21 | ext/cellminer.so: ext/Makefile ext/*.[ch] \ 22 | ext/spu/Makefile ext/spu/*.[chs] \ 23 | ext/ppu/Makefile ext/ppu/*.[chs] 24 | $(MAKE) -C ext 25 | 26 | ext/Makefile: ext/extconf.rb ext/depend 27 | $(RUBY) -C ext -E ascii-8bit extconf.rb 28 | 29 | .PHONY: clean 30 | clean: 31 | $(MAKE) -C ext $@ 32 | 33 | .PHONY: again 34 | again: clean 35 | $(MAKE) 36 | -------------------------------------------------------------------------------- /ext/ppu/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # ifndef UTIL_H 20 | # define UTIL_H 21 | 22 | # include 23 | 24 | # include "sha256.h" 25 | 26 | # define likely(expr) __builtin_expect((expr), 1) 27 | # define unlikely(expr) __builtin_expect((expr), 0) 28 | 29 | extern int debugging; 30 | 31 | void hex(char *, const char *, uint32_t); 32 | 33 | void debug(const char *, ...); 34 | void debug_hash(const hash_t *, const char *); 35 | 36 | # endif 37 | -------------------------------------------------------------------------------- /ext/spu/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # ifndef UTIL_H 20 | # define UTIL_H 21 | 22 | # include 23 | 24 | # include "sha256.h" 25 | 26 | # define likely(expr) __builtin_expect((expr), 1) 27 | # define unlikely(expr) __builtin_expect((expr), 0) 28 | 29 | extern uint64_t spu_id; 30 | extern int debugging; 31 | 32 | void hex(char *, const char *, uint32_t); 33 | 34 | void debug(const char *, ...); 35 | void debug_hash(const hash_t *, const char *); 36 | 37 | # endif 38 | -------------------------------------------------------------------------------- /ext/depend: -------------------------------------------------------------------------------- 1 | # -*- mode: makefile -*- 2 | # 3 | # cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 4 | # Copyright © 2011 Robert Leslie 5 | # 6 | # This program is free software; you can redistribute it and/or modify it 7 | # under the terms of the GNU General Public License (version 2) as 8 | # published by the Free Software Foundation. 9 | # 10 | # This program is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along 16 | # with this program; if not, write to the Free Software Foundation, Inc., 17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 | # 19 | 20 | spu_worker.o: spu/worker.elf 21 | embedspu spu_worker $< $@ 22 | 23 | spu/worker.elf: spu/Makefile spu/*.[chs] 24 | $(MAKE) -C spu 25 | 26 | ppu/worker.a: ppu/Makefile ppu/*.[chs] 27 | $(MAKE) -C ppu 28 | 29 | clean: spu/clean ppu/clean 30 | 31 | .PHONY: spu/clean 32 | spu/clean: 33 | $(MAKE) -C spu clean 34 | 35 | .PHONY: ppu/clean 36 | ppu/clean: 37 | $(MAKE) -C ppu clean 38 | 39 | depend.auto: *.[ch] 40 | @$(CC) -MM *.c >$@ 41 | 42 | *.o: Makefile 43 | include depend.auto 44 | -------------------------------------------------------------------------------- /ext/ppu/params.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # ifndef PARAMS_H 20 | # define PARAMS_H 21 | 22 | # include 23 | 24 | struct worker_params { 25 | char data[128]; 26 | char target[32]; 27 | char midstate[32]; 28 | 29 | uint32_t start_nonce; 30 | uint32_t range; 31 | 32 | unsigned int flags; 33 | }; 34 | 35 | /* parameter flags */ 36 | enum { 37 | WORKER_FLAG_DEBUG = 0x0001 38 | }; 39 | 40 | /* return values */ 41 | enum { 42 | WORKER_FOUND_NOTHING = 0, 43 | WORKER_FOUND_SOMETHING, 44 | 45 | WORKER_VERIFY_ERROR 46 | }; 47 | 48 | # endif 49 | -------------------------------------------------------------------------------- /ext/ppu/sha256.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # ifndef SHA256_H 20 | # define SHA256_H 21 | 22 | # include 23 | 24 | typedef struct { 25 | uint32_t words[8] __attribute__ ((aligned (16))); 26 | } hash_t; 27 | 28 | typedef struct { 29 | uint32_t words[16] __attribute__ ((aligned (16))); 30 | } message_t; 31 | 32 | extern const hash_t H0; 33 | 34 | hash_t sha256_update(const message_t M, const hash_t init); 35 | int64_t sha256_search(const message_t data, 36 | const hash_t target, const hash_t midstate, 37 | uint32_t start_nonce, uint32_t range); 38 | 39 | # endif 40 | -------------------------------------------------------------------------------- /ext/spu/sha256.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # ifndef SHA256_H 20 | # define SHA256_H 21 | 22 | # include 23 | 24 | typedef struct { 25 | uint32_t words[8] __attribute__ ((aligned (16))); 26 | } hash_t; 27 | 28 | typedef struct { 29 | uint32_t words[16] __attribute__ ((aligned (16))); 30 | } message_t; 31 | 32 | extern const hash_t H0; 33 | 34 | hash_t sha256_update(const message_t M, const hash_t init); 35 | int64_t sha256_search(const message_t data, 36 | const hash_t target, const hash_t midstate, 37 | uint32_t start_nonce, uint32_t range); 38 | 39 | # endif 40 | -------------------------------------------------------------------------------- /ext/ppu/test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # include 20 | # include 21 | 22 | # include "sha256.h" 23 | # include "util.h" 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | hash_t hash; 28 | const message_t abc = { { 29 | 0x61626380, 0x00000000, 0x00000000, 0x00000000, 30 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 31 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 32 | 0x00000000, 0x00000000, 0x00000000, 0x00000018 33 | } }; 34 | 35 | debugging = 1; 36 | 37 | hash = sha256_update(abc, H0); 38 | debug_hash(&hash, "abc"); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /ext/spu/test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # include 20 | 21 | # include "sha256.h" 22 | # include "util.h" 23 | 24 | int main(uint64_t speid, uint64_t argp, uint64_t envp) 25 | { 26 | hash_t hash; 27 | const message_t abc = { { 28 | 0x61626380, 0x00000000, 0x00000000, 0x00000000, 29 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 30 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 31 | 0x00000000, 0x00000000, 0x00000000, 0x00000018 32 | } }; 33 | 34 | spu_id = speid; 35 | debugging = 1; 36 | 37 | hash = sha256_update(abc, H0); 38 | debug_hash(&hash, "abc"); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /ext/spu/params.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # ifndef PARAMS_H 20 | # define PARAMS_H 21 | 22 | # include 23 | 24 | struct worker_params { 25 | char data[128]; 26 | char target[32]; 27 | char midstate[32]; 28 | 29 | uint32_t start_nonce; 30 | uint32_t range; 31 | 32 | unsigned int flags; 33 | 34 | char padding[127]; /* required for proper DMA */ 35 | }; 36 | 37 | /* parameter flags */ 38 | enum { 39 | WORKER_FLAG_DEBUG = 0x0001 40 | }; 41 | 42 | /* stop and signal values */ 43 | enum { 44 | WORKER_FOUND_NOTHING = 0, 45 | WORKER_FOUND_SOMETHING, 46 | 47 | WORKER_VERIFY_ERROR, 48 | WORKER_IRQ_SIGNAL 49 | }; 50 | 51 | /* exit values */ 52 | enum { 53 | WORKER_DMA_ERROR = 1 54 | }; 55 | 56 | # endif 57 | -------------------------------------------------------------------------------- /ext/ppu/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | # Copyright © 2011 Robert Leslie 4 | # 5 | # This program is free software; you can redistribute it and/or modify it 6 | # under the terms of the GNU General Public License (version 2) as 7 | # published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, but 10 | # WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along 15 | # with this program; if not, write to the Free Software Foundation, Inc., 16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | # 18 | 19 | DEFINE = -DUNROLL_SHA256 20 | DEFINE += -Dinline="inline __attribute__((always_inline))" 21 | #DEFINE += -DDEBUG 22 | OPTIMIZE = -O3 -fno-strict-aliasing -funroll-loops 23 | MACHINE = -mcpu=cell #-maltivec 24 | DEBUG = -Wall -Werror 25 | 26 | CFLAGS = $(DEFINE) $(OPTIMIZE) $(MACHINE) $(DEBUG) $(INCLUDEPATH) 27 | LDFLAGS = $(LIBPATH) 28 | 29 | CC = gcc 30 | 31 | worker.a: worker.o sha256.o util.o 32 | $(AR) rc $@ $? 33 | 34 | test: test.o sha256.o util.o 35 | $(CC) -o $@ $(LDFLAGS) $^ 36 | 37 | %.s: %.c Makefile 38 | $(CC) -o $@ $(CFLAGS) -c $< -S 39 | 40 | %-debug.s: %.c Makefile 41 | $(CC) -o $@ $(CFLAGS) -c $< -S -g 42 | 43 | .PHONY: clean 44 | clean: 45 | -rm -f *.a *.o test 46 | 47 | depend.auto: *.[ch] 48 | @$(CC) $(MACHINE) -MM *.c >$@ 49 | 50 | *.o: Makefile 51 | include depend.auto 52 | -------------------------------------------------------------------------------- /ext/ppu/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # ifdef DEBUG 20 | # include 21 | # include 22 | # endif 23 | 24 | # include "util.h" 25 | # include "sha256.h" 26 | 27 | int debugging; 28 | 29 | # define HEXDIGITS "0123456789abcdef" 30 | 31 | void hex(char *buf, const char *ptr, uint32_t len) 32 | { 33 | while (len--) { 34 | *buf++ = HEXDIGITS[*ptr / 16]; 35 | *buf++ = HEXDIGITS[*ptr++ % 16]; 36 | } 37 | 38 | *buf = 0; 39 | } 40 | 41 | void debug(const char *fmt, ...) 42 | { 43 | # ifdef DEBUG 44 | va_list args; 45 | 46 | if (!debugging) 47 | return; 48 | 49 | va_start(args, fmt); 50 | fprintf(stderr, "PPU: "); 51 | vfprintf(stderr, fmt, args); 52 | fputc('\n', stderr); 53 | va_end(args); 54 | # endif 55 | } 56 | 57 | void debug_hash(const hash_t *hash, const char *desc) 58 | { 59 | # ifdef DEBUG 60 | char buf[65]; 61 | 62 | if (!debugging) 63 | return; 64 | 65 | hex(buf, (const char *) hash, 32); 66 | debug("%s = %s", desc, buf); 67 | # endif 68 | } 69 | -------------------------------------------------------------------------------- /ext/spu/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | # Copyright © 2011 Robert Leslie 4 | # 5 | # This program is free software; you can redistribute it and/or modify it 6 | # under the terms of the GNU General Public License (version 2) as 7 | # published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, but 10 | # WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along 15 | # with this program; if not, write to the Free Software Foundation, Inc., 16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | # 18 | 19 | DEFINE = -DUNROLL_SHA256 20 | DEFINE += -Dinline="inline __attribute__((always_inline))" 21 | #DEFINE += -DDEBUG 22 | #OPTIMIZE = -O2 -fno-strict-aliasing -funroll-loops -ftree-vectorize 23 | OPTIMIZE = -O3 -fno-strict-aliasing -funroll-loops 24 | #OPTIMIZE += -fmodulo-sched -fmodulo-sched-allow-regmoves 25 | MACHINE = -mno-safe-hints 26 | WARN = -Wall -Werror 27 | #WARN += -Wstrict-aliasing=0 28 | 29 | CFLAGS = $(DEFINE) $(OPTIMIZE) $(MACHINE) $(WARN) $(INCLUDEPATH) 30 | LDFLAGS = $(LIBPATH) 31 | 32 | CC = spu-gcc 33 | AS = spu-as 34 | 35 | worker.elf: main.o worker.o sha256.o util.o spu_slih.o spu_flih.o 36 | $(CC) -o $@ $(LDFLAGS) $^ 37 | 38 | test.elf: test.o sha256.o util.o 39 | $(CC) -o $@ $(LDFLAGS) $^ 40 | 41 | %.s: %.c Makefile 42 | $(CC) -o $@ $(CFLAGS) -c $< -S 43 | 44 | %-debug.s: %.c Makefile 45 | $(CC) -o $@ $(CFLAGS) -c $< -S -g 46 | 47 | .PHONY: clean 48 | clean: 49 | -rm -f *.elf *.o 50 | 51 | depend.auto: *.[ch] 52 | @$(CC) -MM *.c >$@ 53 | 54 | *.o: Makefile 55 | include depend.auto 56 | -------------------------------------------------------------------------------- /ext/spu/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # ifdef DEBUG 20 | # include 21 | # include 22 | # endif 23 | 24 | # include "util.h" 25 | # include "sha256.h" 26 | 27 | uint64_t spu_id; 28 | int debugging; 29 | 30 | # define HEXDIGITS "0123456789abcdef" 31 | 32 | void hex(char *buf, const char *ptr, uint32_t len) 33 | { 34 | while (len--) { 35 | *buf++ = HEXDIGITS[*ptr / 16]; 36 | *buf++ = HEXDIGITS[*ptr++ % 16]; 37 | } 38 | 39 | *buf = 0; 40 | } 41 | 42 | void debug(const char *fmt, ...) 43 | { 44 | # ifdef DEBUG 45 | va_list args; 46 | 47 | if (!debugging) 48 | return; 49 | 50 | va_start(args, fmt); 51 | fprintf(stderr, "SPU(%08llx): ", spu_id); 52 | vfprintf(stderr, fmt, args); 53 | fputc('\n', stderr); 54 | va_end(args); 55 | # endif 56 | } 57 | 58 | void debug_hash(const hash_t *hash, const char *desc) 59 | { 60 | # ifdef DEBUG 61 | char buf[65]; 62 | 63 | if (!debugging) 64 | return; 65 | 66 | hex(buf, (const char *) hash, 32); 67 | debug("%s = %s", desc, buf); 68 | # endif 69 | } 70 | -------------------------------------------------------------------------------- /ext/spu/spu_slih.c: -------------------------------------------------------------------------------- 1 | 2 | # include 3 | 4 | # include "spu_slih.h" 5 | 6 | # define SPU_EVENT_ID(_mask) (spu_extract(spu_cntlz(spu_promote(_mask, 0)), 0)) 7 | 8 | static 9 | unsigned int default_slih(unsigned int events) 10 | { 11 | unsigned int mse; 12 | 13 | /* get my (left-most) event number */ 14 | mse = 0x80000000 >> SPU_EVENT_ID(events); 15 | 16 | /* return updated event bits */ 17 | return events & ~mse; 18 | } 19 | 20 | spu_slih_func spu_slih_handlers[33] __attribute__ ((aligned (16))) = { 21 | default_slih, 22 | default_slih, 23 | default_slih, 24 | default_slih, 25 | default_slih, 26 | default_slih, 27 | default_slih, 28 | default_slih, 29 | 30 | default_slih, 31 | default_slih, 32 | default_slih, 33 | default_slih, 34 | default_slih, 35 | default_slih, 36 | default_slih, 37 | default_slih, 38 | 39 | default_slih, 40 | default_slih, 41 | default_slih, 42 | default_slih, /* event bit 19: Multisource Sync */ 43 | default_slih, /* event bit 20: Privilege attention */ 44 | default_slih, /* event bit 21: Lock-line reservation-lost */ 45 | default_slih, /* event bit 22: Signal-notification 1 */ 46 | default_slih, /* event bit 23: Signal-notification 2 */ 47 | 48 | default_slih, /* event bit 24: SPU Write Outbound Mailbox available */ 49 | default_slih, /* event bit 25: SPU Write Outbound IRQ Mailbox avail. */ 50 | default_slih, /* event bit 26: Decrementer */ 51 | default_slih, /* event bit 27: SPE mailbox */ 52 | default_slih, /* event bit 28: DMA-queue */ 53 | default_slih, /* reserved */ 54 | default_slih, /* extra bit 30: DMA list command stall-and-notify */ 55 | default_slih, /* extra bit 31: SPE tag-status update */ 56 | 57 | default_slih /* extra slih table entry for phantom events */ 58 | }; 59 | 60 | void spu_slih_register(unsigned int mask, spu_slih_func func) 61 | { 62 | unsigned int id; 63 | 64 | while (mask) { 65 | id = SPU_EVENT_ID(mask); /* get next (left-most) event */ 66 | spu_slih_handlers[id] = func; /* put function ptr into slih table */ 67 | mask &= ~(0x80000000 >> id); /* clear that event bit */ 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ext/spu/worker.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # include 20 | # include 21 | # include 22 | 23 | # include "worker.h" 24 | # include "sha256.h" 25 | # include "util.h" 26 | 27 | /* 28 | * NAME: verify_midstate() 29 | * DESCRIPTION: check that the midstate received is correct 30 | */ 31 | static 32 | int verify_midstate(const hash_t midstate, const message_t data) 33 | { 34 | hash_t hash; 35 | 36 | hash = sha256_update(data, H0); 37 | 38 | return memcmp(&hash, &midstate, sizeof(hash_t)) == 0; 39 | } 40 | 41 | /* 42 | * NAME: work_on() 43 | * DESCRIPTION: search for a solution and return 1 if found, 0 otherwise 44 | */ 45 | int work_on(struct worker_params *params) 46 | { 47 | uint32_t *data = (uint32_t *) params->data; 48 | char buf[257]; 49 | int64_t nonce; 50 | 51 | hex(buf, params->data, 128); 52 | debug("data = %s", buf); 53 | 54 | debug_hash((const hash_t *) params->target, "target "); 55 | debug_hash((const hash_t *) params->midstate, "midstate"); 56 | 57 | if (!verify_midstate(*(const hash_t *) params->midstate, 58 | ((const message_t *) data)[0])) { 59 | debug("midstate verification failed"); 60 | return -1; 61 | } 62 | 63 | debug("start_nonce = %08lx, range = %08lx", 64 | params->start_nonce, params->range); 65 | 66 | nonce = sha256_search(((const message_t *) params->data)[1], 67 | *(const hash_t *) params->target, 68 | *(const hash_t *) params->midstate, 69 | params->start_nonce, 70 | params->range); 71 | if (nonce < 0) 72 | return 0; 73 | 74 | /* store the found nonce */ 75 | data[19] = nonce; 76 | 77 | return 1; 78 | } 79 | -------------------------------------------------------------------------------- /ext/ppu/worker.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # include 20 | # include 21 | 22 | # include "params.h" 23 | # include "sha256.h" 24 | # include "util.h" 25 | 26 | /* 27 | * NAME: verify_midstate() 28 | * DESCRIPTION: check that the midstate received is correct 29 | */ 30 | static 31 | int verify_midstate(const hash_t midstate, const message_t data) 32 | { 33 | hash_t hash; 34 | 35 | hash = sha256_update(data, H0); 36 | 37 | return memcmp(&hash, &midstate, sizeof(hash_t)) == 0; 38 | } 39 | 40 | /* 41 | * NAME: PPU->mine() 42 | * DESCRIPTION: search for a solution and return 1 if found, 0 otherwise 43 | */ 44 | int ppu_mine(struct worker_params *params) 45 | { 46 | uint32_t *data = (uint32_t *) params->data; 47 | char buf[257]; 48 | int64_t nonce; 49 | 50 | debugging = params->flags & WORKER_FLAG_DEBUG; 51 | 52 | hex(buf, params->data, 128); 53 | debug("data = %s", buf); 54 | 55 | debug_hash((const hash_t *) params->target, "target "); 56 | debug_hash((const hash_t *) params->midstate, "midstate"); 57 | 58 | if (!verify_midstate(*(const hash_t *) params->midstate, 59 | ((const message_t *) data)[0])) { 60 | debug("midstate verification failed"); 61 | return WORKER_VERIFY_ERROR; 62 | } 63 | 64 | debug("start_nonce = %08lx, range = %08lx", 65 | params->start_nonce, params->range); 66 | 67 | nonce = sha256_search(((const message_t *) params->data)[1], 68 | *(const hash_t *) params->target, 69 | *(const hash_t *) params->midstate, 70 | params->start_nonce, 71 | params->range); 72 | if (nonce < 0) 73 | return WORKER_FOUND_NOTHING; 74 | 75 | /* store the found nonce */ 76 | data[19] = nonce; 77 | 78 | return WORKER_FOUND_SOMETHING; 79 | } 80 | -------------------------------------------------------------------------------- /ext/spu/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # include 20 | # include 21 | # include 22 | # include 23 | 24 | # include "spu_slih.h" 25 | # include "params.h" 26 | # include "worker.h" 27 | # include "util.h" 28 | 29 | /* 30 | * NAME: dma_get() 31 | * DESCRIPTION: initiate DMA transfer from main memory to LS 32 | */ 33 | static 34 | void dma_get(volatile void *ls, uint64_t ea, uint32_t size, uint32_t tag) 35 | { 36 | mfc_get(ls, ea, size, tag, 0, 0); 37 | } 38 | 39 | /* 40 | * NAME: dma_put() 41 | * DESCRIPTION: initiate DMA transfer from LS to main memory 42 | */ 43 | static 44 | void dma_put(volatile void *ls, uint64_t ea, uint32_t size, uint32_t tag) 45 | { 46 | mfc_put(ls, ea, size, tag, 0, 0); 47 | } 48 | 49 | /* 50 | * NAME: dma_params() 51 | * DESCRIPTION: transfer work parameters between LS and main memory 52 | */ 53 | static 54 | int dma_params(struct worker_params *params, uint64_t ea, 55 | void (*dma)(volatile void *, uint64_t, uint32_t, uint32_t)) 56 | { 57 | uint32_t tag, size; 58 | 59 | tag = mfc_tag_reserve(); 60 | if (tag == MFC_TAG_INVALID) 61 | return -1; 62 | 63 | size = (offsetof(struct worker_params, padding) + 127) & ~127; 64 | 65 | dma(params, ea, size, tag); 66 | 67 | mfc_write_tag_mask(1 << tag); 68 | mfc_read_tag_status_all(); 69 | 70 | mfc_tag_release(tag); 71 | 72 | return 0; 73 | } 74 | 75 | /* 76 | * NAME: signal_handler() 77 | * DESCRIPTION: IRQ handler for signal notification 78 | */ 79 | static 80 | unsigned int signal_handler(unsigned int events) 81 | { 82 | if (spu_stat_signal1() && 83 | spu_read_signal1()) 84 | spu_stop(WORKER_IRQ_SIGNAL); 85 | 86 | return events & ~MFC_SIGNAL_NOTIFY_1_EVENT; 87 | } 88 | 89 | /* 90 | * NAME: main() 91 | * DESCRIPTION: entry point for SPU program 92 | */ 93 | int main(uint64_t speid, uint64_t argp, uint64_t envp) 94 | { 95 | spu_id = speid; 96 | 97 | /* set up interrupt handler and enable interrupts */ 98 | 99 | spu_slih_register(MFC_SIGNAL_NOTIFY_1_EVENT, signal_handler); 100 | 101 | spu_write_event_mask(MFC_SIGNAL_NOTIFY_1_EVENT); 102 | spu_ienable(); 103 | 104 | /* loop forever loading parameters and doing work */ 105 | 106 | while (1) { 107 | struct worker_params params __attribute__ ((aligned (128))); 108 | int result; 109 | 110 | /* load parameters */ 111 | 112 | if (unlikely(dma_params(¶ms, argp, dma_get))) 113 | return WORKER_DMA_ERROR; 114 | 115 | debugging = params.flags & WORKER_FLAG_DEBUG; 116 | 117 | /* do work */ 118 | 119 | if (unlikely(result = work_on(¶ms))) { 120 | if (result < 0) 121 | spu_stop(WORKER_VERIFY_ERROR); 122 | else { 123 | /* we found something? */ 124 | if (dma_params(¶ms, argp, dma_put)) 125 | return WORKER_DMA_ERROR; 126 | 127 | spu_stop(WORKER_FOUND_SOMETHING); 128 | } 129 | } 130 | else 131 | spu_stop(WORKER_FOUND_NOTHING); 132 | } 133 | 134 | /* not reached */ 135 | 136 | return 0; 137 | } 138 | -------------------------------------------------------------------------------- /bitcoin.rb: -------------------------------------------------------------------------------- 1 | # 2 | # cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | # Copyright © 2011 Robert Leslie 4 | # 5 | # This program is free software; you can redistribute it and/or modify it 6 | # under the terms of the GNU General Public License (version 2) as 7 | # published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, but 10 | # WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along 15 | # with this program; if not, write to the Free Software Foundation, Inc., 16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | # 18 | 19 | require 'uri' 20 | require 'json' 21 | require 'net/http/persistent' 22 | 23 | module Bitcoin 24 | CONFFILE = File.join(ENV['HOME'], '.bitcoin', 'bitcoin.conf') 25 | 26 | def self.conf 27 | parms = File.read(CONFFILE).split("\n") 28 | parms.inject(Hash.new) {|h, p| h.merge! Hash[*p.split("=")] } 29 | end 30 | 31 | def self.rpc_proxy(server = {}, user_agent = nil) 32 | conf = self.conf rescue Hash.new 33 | 34 | username = server.delete(:username) || conf['rpcuser'] 35 | password = server.delete(:password) || conf['rpcpassword'] 36 | 37 | default = { 38 | :host => 'localhost', 39 | :port => 8332, 40 | :path => '/' 41 | } 42 | 43 | uri = URI::HTTP.build(default.merge(server)) 44 | 45 | # This is a workaround; URI needs escaped username and password 46 | if username 47 | uri.user = URI.escape username, /[^#{URI::PATTERN::UNRESERVED}]/ 48 | uri.password = URI.escape password, /[^#{URI::PATTERN::UNRESERVED}]/ 49 | end 50 | 51 | RPCProxy.new(uri, user_agent) 52 | end 53 | 54 | class RPCProxy 55 | LONG_POLL_TIMEOUT = 60 * 60 * 12 56 | 57 | class JSONRPCError < StandardError 58 | attr_reader :code 59 | 60 | def initialize(json) 61 | super json['message'] 62 | @code = json['code'] 63 | end 64 | end 65 | 66 | def initialize(uri, user_agent = nil, timeout = nil) 67 | case uri 68 | when URI 69 | when String 70 | uri = URI.parse(uri) 71 | else 72 | raise ArgumentError, "bad URI given" 73 | end 74 | 75 | @uri = uri 76 | @user_agent = user_agent 77 | 78 | @session = Net::HTTP::Persistent.new 79 | @session.read_timeout = timeout if timeout 80 | 81 | def @session.idempotent? req 82 | # All of the RPC methods we use are idempotent 83 | true 84 | end 85 | end 86 | 87 | def method_missing(method, *params) 88 | request = Net::HTTP::Post.new(@uri.path) 89 | request['User-Agent'] = @user_agent if @user_agent 90 | 91 | # This is a workaround; URI needs escaped username and password 92 | # strings but Net:HTTP requires them unescaped (credentials get 93 | # base64-encoded anyway) 94 | request.basic_auth(URI.unescape(@uri.user), 95 | URI.unescape(@uri.password)) if @uri.user 96 | 97 | request.content_type = 'application/json' 98 | request.body = { 99 | id: 'jsonrpc', 100 | method: method, 101 | params: params 102 | }.to_json 103 | 104 | begin 105 | response = @session.request(@uri, request) 106 | response.value # raises error on all non-success responses 107 | rescue Errno::EINTR 108 | retry 109 | end 110 | 111 | json = JSON.parse(response.body) 112 | raise JSONRPCError.new(json['error']) if json['error'] 113 | 114 | if block_given? and poll_path = response['X-Long-Polling'] 115 | poll_uri = URI.parse(poll_path) 116 | poll_uri = @uri.merge(poll_uri) if poll_uri.kind_of?(URI::Generic) 117 | poll_uri.path = "/" if poll_uri.path.empty? 118 | if @uri.user 119 | poll_uri.user = @uri.user 120 | poll_uri.password = @uri.password 121 | end 122 | yield self.class.new(poll_uri, @user_agent, LONG_POLL_TIMEOUT) 123 | end 124 | 125 | json['result'] 126 | end 127 | end 128 | end 129 | -------------------------------------------------------------------------------- /ext/ppu_miner.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # include 20 | # include 21 | # include 22 | # include 23 | # include 24 | 25 | # include "ppu/params.h" 26 | 27 | extern int ppu_mine(volatile struct worker_params *); 28 | 29 | struct ppu_miner { 30 | volatile struct worker_params params; 31 | 32 | pthread_t thread; 33 | }; 34 | 35 | static 36 | VALUE m_initialize(int argc, VALUE *argv, VALUE self) 37 | { 38 | struct ppu_miner *miner; 39 | 40 | if (argc < 0 || argc > 1) 41 | rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc); 42 | 43 | Data_Get_Struct(self, struct ppu_miner, miner); 44 | 45 | if (argc > 0 && RTEST(argv[0])) 46 | miner->params.flags |= WORKER_FLAG_DEBUG; 47 | 48 | return self; 49 | } 50 | 51 | static 52 | void *run_miner(void *data) 53 | { 54 | struct ppu_miner *miner = data; 55 | int oldvalue; 56 | 57 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldvalue); 58 | pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldvalue); 59 | 60 | switch (ppu_mine(&miner->params)) { 61 | case WORKER_VERIFY_ERROR: 62 | return (void *) Qnil; 63 | 64 | case WORKER_FOUND_NOTHING: 65 | return (void *) Qfalse; 66 | 67 | case WORKER_FOUND_SOMETHING: 68 | return (void *) Qtrue; 69 | } 70 | 71 | return (void *) Qundef; 72 | } 73 | 74 | static 75 | VALUE wait_miner(void *data) 76 | { 77 | struct ppu_miner *miner = data; 78 | void *retval; 79 | 80 | if (pthread_join(miner->thread, &retval)) 81 | return Qundef; 82 | 83 | if (retval == PTHREAD_CANCELED) 84 | return Qfalse; 85 | 86 | return (VALUE) retval; 87 | } 88 | 89 | static 90 | void unblock_miner(void *data) 91 | { 92 | struct ppu_miner *miner = data; 93 | 94 | pthread_cancel(miner->thread); 95 | } 96 | 97 | static 98 | VALUE m_run(VALUE self, VALUE data, VALUE target, VALUE midstate, 99 | VALUE start_nonce, VALUE range) 100 | { 101 | struct ppu_miner *miner; 102 | VALUE retval; 103 | 104 | Data_Get_Struct(self, struct ppu_miner, miner); 105 | 106 | /* prepare parameters */ 107 | 108 | StringValue(data); 109 | StringValue(target); 110 | StringValue(midstate); 111 | 112 | if (RSTRING_LEN(data) != 128) 113 | rb_raise(rb_eArgError, "data must be 128 bytes"); 114 | if (RSTRING_LEN(target) != 32) 115 | rb_raise(rb_eArgError, "target must be 32 bytes"); 116 | if (RSTRING_LEN(midstate) != 32) 117 | rb_raise(rb_eArgError, "midstate must be 32 bytes"); 118 | 119 | memcpy((void *) miner->params.data, RSTRING_PTR(data), 128); 120 | memcpy((void *) miner->params.target, RSTRING_PTR(target), 32); 121 | memcpy((void *) miner->params.midstate, RSTRING_PTR(midstate), 32); 122 | 123 | miner->params.start_nonce = NUM2ULONG(start_nonce); 124 | miner->params.range = NUM2ULONG(range); 125 | 126 | /* start a mining thread and unlock the Global Interpreter Lock */ 127 | 128 | if (pthread_create(&miner->thread, 0, run_miner, miner)) 129 | rb_raise(rb_eRuntimeError, "failed to create PPU thread"); 130 | 131 | retval = rb_thread_blocking_region(wait_miner, miner, 132 | unblock_miner, miner); 133 | 134 | switch (retval) { 135 | case Qtrue: 136 | retval = rb_str_new((const char *) miner->params.data, 128); 137 | break; 138 | 139 | case Qnil: 140 | rb_raise(rb_eArgError, "midstate verification failed"); 141 | break; 142 | 143 | case Qundef: 144 | rb_raise(rb_eRuntimeError, "PPU thread error"); 145 | break; 146 | } 147 | 148 | return retval; 149 | } 150 | 151 | static 152 | VALUE i_allocate(VALUE klass) 153 | { 154 | struct ppu_miner *miner; 155 | 156 | if (posix_memalign((void **) &miner, 128, sizeof(*miner))) 157 | rb_raise(rb_eRuntimeError, "unable to allocate aligned memory"); 158 | 159 | miner->params.flags = 0; 160 | 161 | return Data_Wrap_Struct(klass, 0, free, miner); 162 | } 163 | 164 | void Init_ppu_miner(VALUE container) 165 | { 166 | VALUE cPPUMiner; 167 | 168 | cPPUMiner = rb_define_class_under(container, "PPUMiner", rb_cObject); 169 | rb_define_alloc_func(cPPUMiner, i_allocate); 170 | 171 | rb_define_method(cPPUMiner, "initialize", m_initialize, -1); 172 | rb_define_method(cPPUMiner, "run", m_run, 5); 173 | } 174 | -------------------------------------------------------------------------------- /ext/spu/spu_flih.s: -------------------------------------------------------------------------------- 1 | /* max. size needed to protect unallocated stack space */ 2 | .set STACK_SKIP, 125 3 | 4 | .section .interrupt, "ax", @progbits 5 | .align 3 6 | 7 | .global spu_flih 8 | 9 | spu_flih: 10 | /* save back-chain pointer */ 11 | stqd $SP, -(STACK_SKIP+82)*16($SP) 12 | 13 | /* save volatile registers 0, 2-79 */ 14 | stqd $0, -(STACK_SKIP+80)*16($SP) 15 | stqd $2, -(STACK_SKIP+ 2)*16($SP) 16 | stqd $3, -(STACK_SKIP+ 3)*16($SP) 17 | stqd $4, -(STACK_SKIP+ 4)*16($SP) 18 | stqd $5, -(STACK_SKIP+ 5)*16($SP) 19 | stqd $6, -(STACK_SKIP+ 6)*16($SP) 20 | stqd $7, -(STACK_SKIP+ 7)*16($SP) 21 | stqd $8, -(STACK_SKIP+ 8)*16($SP) 22 | stqd $9, -(STACK_SKIP+ 9)*16($SP) 23 | stqd $10, -(STACK_SKIP+10)*16($SP) 24 | stqd $11, -(STACK_SKIP+11)*16($SP) 25 | stqd $12, -(STACK_SKIP+12)*16($SP) 26 | stqd $13, -(STACK_SKIP+13)*16($SP) 27 | stqd $14, -(STACK_SKIP+14)*16($SP) 28 | stqd $15, -(STACK_SKIP+15)*16($SP) 29 | stqd $16, -(STACK_SKIP+16)*16($SP) 30 | stqd $17, -(STACK_SKIP+17)*16($SP) 31 | stqd $18, -(STACK_SKIP+18)*16($SP) 32 | stqd $19, -(STACK_SKIP+19)*16($SP) 33 | stqd $20, -(STACK_SKIP+20)*16($SP) 34 | stqd $21, -(STACK_SKIP+21)*16($SP) 35 | stqd $22, -(STACK_SKIP+22)*16($SP) 36 | stqd $23, -(STACK_SKIP+23)*16($SP) 37 | stqd $24, -(STACK_SKIP+24)*16($SP) 38 | stqd $25, -(STACK_SKIP+25)*16($SP) 39 | stqd $26, -(STACK_SKIP+26)*16($SP) 40 | stqd $27, -(STACK_SKIP+27)*16($SP) 41 | stqd $28, -(STACK_SKIP+28)*16($SP) 42 | stqd $29, -(STACK_SKIP+29)*16($SP) 43 | stqd $30, -(STACK_SKIP+30)*16($SP) 44 | stqd $31, -(STACK_SKIP+31)*16($SP) 45 | stqd $32, -(STACK_SKIP+32)*16($SP) 46 | stqd $33, -(STACK_SKIP+33)*16($SP) 47 | stqd $34, -(STACK_SKIP+34)*16($SP) 48 | stqd $35, -(STACK_SKIP+35)*16($SP) 49 | stqd $36, -(STACK_SKIP+36)*16($SP) 50 | stqd $37, -(STACK_SKIP+37)*16($SP) 51 | stqd $38, -(STACK_SKIP+38)*16($SP) 52 | stqd $39, -(STACK_SKIP+39)*16($SP) 53 | stqd $40, -(STACK_SKIP+40)*16($SP) 54 | stqd $41, -(STACK_SKIP+41)*16($SP) 55 | stqd $42, -(STACK_SKIP+42)*16($SP) 56 | stqd $43, -(STACK_SKIP+43)*16($SP) 57 | stqd $44, -(STACK_SKIP+44)*16($SP) 58 | stqd $45, -(STACK_SKIP+45)*16($SP) 59 | stqd $46, -(STACK_SKIP+46)*16($SP) 60 | stqd $47, -(STACK_SKIP+47)*16($SP) 61 | stqd $48, -(STACK_SKIP+48)*16($SP) 62 | stqd $49, -(STACK_SKIP+49)*16($SP) 63 | stqd $50, -(STACK_SKIP+50)*16($SP) 64 | stqd $51, -(STACK_SKIP+51)*16($SP) 65 | stqd $52, -(STACK_SKIP+52)*16($SP) 66 | stqd $53, -(STACK_SKIP+53)*16($SP) 67 | stqd $54, -(STACK_SKIP+54)*16($SP) 68 | stqd $55, -(STACK_SKIP+55)*16($SP) 69 | stqd $56, -(STACK_SKIP+56)*16($SP) 70 | stqd $57, -(STACK_SKIP+57)*16($SP) 71 | stqd $58, -(STACK_SKIP+58)*16($SP) 72 | stqd $59, -(STACK_SKIP+59)*16($SP) 73 | stqd $60, -(STACK_SKIP+60)*16($SP) 74 | stqd $61, -(STACK_SKIP+61)*16($SP) 75 | stqd $62, -(STACK_SKIP+62)*16($SP) 76 | stqd $63, -(STACK_SKIP+63)*16($SP) 77 | stqd $64, -(STACK_SKIP+64)*16($SP) 78 | stqd $65, -(STACK_SKIP+65)*16($SP) 79 | stqd $66, -(STACK_SKIP+66)*16($SP) 80 | stqd $67, -(STACK_SKIP+67)*16($SP) 81 | stqd $68, -(STACK_SKIP+68)*16($SP) 82 | stqd $69, -(STACK_SKIP+69)*16($SP) 83 | stqd $70, -(STACK_SKIP+70)*16($SP) 84 | stqd $71, -(STACK_SKIP+71)*16($SP) 85 | stqd $72, -(STACK_SKIP+72)*16($SP) 86 | stqd $73, -(STACK_SKIP+73)*16($SP) 87 | stqd $74, -(STACK_SKIP+74)*16($SP) 88 | stqd $75, -(STACK_SKIP+75)*16($SP) 89 | stqd $76, -(STACK_SKIP+76)*16($SP) 90 | stqd $77, -(STACK_SKIP+77)*16($SP) 91 | stqd $78, -(STACK_SKIP+78)*16($SP) 92 | stqd $79, -(STACK_SKIP+79)*16($SP) 93 | 94 | /* save event mask on the stack */ 95 | rdch $6, $SPU_RdEventMask 96 | stqd $6, -(STACK_SKIP+ 1)*16($SP) 97 | 98 | /* disable and acknowledge current pending events */ 99 | rdch $3, $SPU_RdEventStat 100 | andc $7, $6, $3 101 | wrch $SPU_WrEventMask, $7 102 | wrch $SPU_WrEventAck, $3 103 | 104 | /* instantiate flih stack frame */ 105 | il $2, -(STACK_SKIP+82)*16 106 | a $SP, $SP, $2 107 | 108 | next_event: 109 | clz $4, $3 # determine next (left-most) event 110 | ila $5, spu_slih_handlers # address of slih function table 111 | shli $4, $4, 2 # make event number a word offset 112 | lqx $5, $4, $5 # load four slih function pointers 113 | rotqby $5, $5, $4 # rotate slih pointer to preferred slot 114 | bisl $0, $5 # branch-and-link to slih function 115 | brnz $3, next_event # more events? ($3 is slih return value) 116 | 117 | /* re-establish previous event mask */ 118 | lqd $6, 81*16($SP) 119 | wrch $SPU_WrEventMask, $6 120 | 121 | /* restore volatile registers 79-2, 0 */ 122 | lqd $79, 3*16($SP) 123 | lqd $78, 4*16($SP) 124 | lqd $77, 5*16($SP) 125 | lqd $76, 6*16($SP) 126 | lqd $75, 7*16($SP) 127 | lqd $74, 8*16($SP) 128 | lqd $73, 9*16($SP) 129 | lqd $72, 10*16($SP) 130 | lqd $71, 11*16($SP) 131 | lqd $70, 12*16($SP) 132 | lqd $69, 13*16($SP) 133 | lqd $68, 14*16($SP) 134 | lqd $67, 15*16($SP) 135 | lqd $66, 16*16($SP) 136 | lqd $65, 17*16($SP) 137 | lqd $64, 18*16($SP) 138 | lqd $63, 19*16($SP) 139 | lqd $62, 20*16($SP) 140 | lqd $61, 21*16($SP) 141 | lqd $60, 22*16($SP) 142 | lqd $59, 23*16($SP) 143 | lqd $58, 24*16($SP) 144 | lqd $57, 25*16($SP) 145 | lqd $56, 26*16($SP) 146 | lqd $55, 27*16($SP) 147 | lqd $54, 28*16($SP) 148 | lqd $53, 29*16($SP) 149 | lqd $52, 30*16($SP) 150 | lqd $51, 31*16($SP) 151 | lqd $50, 32*16($SP) 152 | lqd $49, 33*16($SP) 153 | lqd $48, 34*16($SP) 154 | lqd $47, 35*16($SP) 155 | lqd $46, 36*16($SP) 156 | lqd $45, 37*16($SP) 157 | lqd $44, 38*16($SP) 158 | lqd $43, 39*16($SP) 159 | lqd $42, 40*16($SP) 160 | lqd $41, 41*16($SP) 161 | lqd $40, 42*16($SP) 162 | lqd $39, 43*16($SP) 163 | lqd $38, 44*16($SP) 164 | lqd $37, 45*16($SP) 165 | lqd $36, 46*16($SP) 166 | lqd $35, 47*16($SP) 167 | lqd $34, 48*16($SP) 168 | lqd $33, 49*16($SP) 169 | lqd $32, 50*16($SP) 170 | lqd $31, 51*16($SP) 171 | lqd $30, 52*16($SP) 172 | lqd $29, 53*16($SP) 173 | lqd $28, 54*16($SP) 174 | lqd $27, 55*16($SP) 175 | lqd $26, 56*16($SP) 176 | lqd $25, 57*16($SP) 177 | lqd $24, 58*16($SP) 178 | lqd $23, 59*16($SP) 179 | lqd $22, 60*16($SP) 180 | lqd $21, 61*16($SP) 181 | lqd $20, 62*16($SP) 182 | lqd $19, 63*16($SP) 183 | lqd $18, 64*16($SP) 184 | lqd $17, 65*16($SP) 185 | lqd $16, 66*16($SP) 186 | lqd $15, 67*16($SP) 187 | lqd $14, 68*16($SP) 188 | lqd $13, 69*16($SP) 189 | lqd $12, 70*16($SP) 190 | lqd $11, 71*16($SP) 191 | lqd $10, 72*16($SP) 192 | lqd $9, 73*16($SP) 193 | lqd $8, 74*16($SP) 194 | lqd $7, 75*16($SP) 195 | lqd $6, 76*16($SP) 196 | lqd $5, 77*16($SP) 197 | lqd $4, 78*16($SP) 198 | lqd $3, 79*16($SP) 199 | lqd $2, 80*16($SP) 200 | lqd $0, 2*16($SP) 201 | 202 | /* restore stack pointer from back-chain pointer */ 203 | lqd $SP, 0*16($SP) 204 | 205 | /* return through SRR0, re-enable interrupts */ 206 | irete 207 | -------------------------------------------------------------------------------- /sha256.rb: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | # 3 | # cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 4 | # Copyright © 2011 Robert Leslie 5 | # 6 | # This program is free software; you can redistribute it and/or modify it 7 | # under the terms of the GNU General Public License (version 2) as 8 | # published by the Free Software Foundation. 9 | # 10 | # This program is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along 16 | # with this program; if not, write to the Free Software Foundation, Inc., 17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 | # 19 | 20 | class SHA256 21 | K = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 22 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 23 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 24 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 25 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 26 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 27 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 28 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 29 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 30 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 31 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 32 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 33 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 34 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 35 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 36 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2] 37 | 38 | H0 = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 39 | 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19] 40 | 41 | module Operations 42 | def SHR(n) 43 | self >> n 44 | end 45 | 46 | def ROTR(n) 47 | (self >> n) | (self << (32 - n)) 48 | end 49 | end 50 | 51 | module Functions 52 | include Operations 53 | 54 | def Ch(y, z) 55 | (self & y) ^ (~self & z) 56 | end 57 | 58 | def Maj(y, z) 59 | (self & y) ^ (self & z) ^ (y & z) 60 | end 61 | 62 | def Σ₀ 63 | ROTR(2) ^ ROTR(13) ^ ROTR(22) 64 | end 65 | 66 | def Σ₁ 67 | ROTR(6) ^ ROTR(11) ^ ROTR(25) 68 | end 69 | 70 | def σ₀ 71 | ROTR(7) ^ ROTR(18) ^ SHR(3) 72 | end 73 | 74 | def σ₁ 75 | ROTR(17) ^ ROTR(19) ^ SHR(10) 76 | end 77 | end 78 | 79 | def initialize(wrap = UInt32, init = H0) 80 | @wrap = wrap.dup.class_exec { include Functions } 81 | 82 | @H = init.map {|v| @wrap.new(v) } 83 | @K = K.map {|v| @wrap.new(v) } 84 | end 85 | 86 | def hash_block(m) 87 | w = m.map {|v| @wrap.new(v) } 88 | a, b, c, d, e, f, g, h = @H 89 | 90 | round = Proc.new do |t| 91 | t₁ = h + e.Σ₁ + e.Ch(f, g) + @K[t] + w[t % 16] 92 | t₂ = a.Σ₀ + a.Maj(b, c) 93 | 94 | h = g 95 | g = f 96 | f = e 97 | e = d + t₁ 98 | d = c 99 | c = b 100 | b = a 101 | a = t₁ + t₂ 102 | end 103 | 104 | 0.upto(15) do |t| 105 | round.(t) 106 | end 107 | 108 | 16.upto(63) do |t| 109 | w[t % 16] = w[(t - 2) % 16].σ₁ + 110 | w[(t - 7) % 16] + 111 | w[(t - 15) % 16].σ₀ + 112 | w[(t - 16) % 16] 113 | round.(t) 114 | end 115 | 116 | @H = [a + @H[0], b + @H[1], c + @H[2], d + @H[3], 117 | e + @H[4], f + @H[5], g + @H[6], h + @H[7]] 118 | 119 | self 120 | end 121 | 122 | def update(bytes) 123 | bytes.unpack('N*').each_slice(16) {|b| hash_block(b) } 124 | self 125 | end 126 | 127 | def value 128 | @H.map(&:value) 129 | end 130 | 131 | def digest 132 | value.pack('N*') 133 | end 134 | 135 | def hexdigest 136 | value.map {|v| "%08x" % v }.join 137 | end 138 | end 139 | 140 | class UInt32 141 | attr_reader :value 142 | 143 | def initialize(value) 144 | @value = value & 0xffffffff 145 | end 146 | 147 | def to_s 148 | "%08x" % @value 149 | end 150 | 151 | def +(other) 152 | self.class.new(@value + other.value) 153 | end 154 | 155 | def ^(other) 156 | self.class.new(@value ^ other.value) 157 | end 158 | 159 | def &(other) 160 | self.class.new(@value & other.value) 161 | end 162 | 163 | def |(other) 164 | self.class.new(@value | other.value) 165 | end 166 | 167 | def ~@ 168 | self.class.new(~@value) 169 | end 170 | 171 | def >>(bits) 172 | self.class.new(@value >> bits) 173 | end 174 | 175 | def <<(bits) 176 | self.class.new(@value << bits) 177 | end 178 | end 179 | 180 | # Unit tests 181 | if __FILE__ == $0 182 | require 'test/unit' 183 | 184 | class TestSHA256 < Test::Unit::TestCase 185 | def setup 186 | @sha256 = SHA256.new 187 | end 188 | 189 | def test_one_block_message 190 | @sha256.hash_block([0b01100001011000100110001110000000, 191 | 0, 0, 0, 0, 0, 0, 0, 192 | 0, 0, 0, 0, 0, 0, 0, 0x18]) 193 | assert_equal(@sha256.value, 194 | [0xba7816bf, 0x8f01cfea, 0x414140de, 0x5dae2223, 195 | 0xb00361a3, 0x96177a9c, 0xb410ff61, 0xf20015ad]) 196 | end 197 | 198 | def test_multi_block_message 199 | m = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 200 | padded = m.unpack('N*') + [0x80000000] + [0] * 15 + [0, 0x1c0] 201 | 202 | @sha256.hash_block(padded[0, 16]) 203 | assert_equal(@sha256.digest, 204 | [0x85e655d6, 0x417a1795, 0x3363376a, 0x624cde5c, 205 | 0x76e09589, 0xcac5f811, 0xcc4b32c1, 0xf20e533a].pack('N*')) 206 | 207 | @sha256.hash_block(padded[16, 16]) 208 | assert_equal(@sha256.hexdigest, 209 | "248d6a61" "d20638b8" "e5c02693" "0c3e6039" \ 210 | "a33ce459" "64ff2167" "f6ecedd4" "19db06c1") 211 | end 212 | 213 | def test_long_message 214 | skip "Time-consuming long message test not run (use arg 'long')" unless 215 | ARGV.include? "long" 216 | 217 | m = "a" * 1_000_000 218 | padded = m.unpack('N*') << 0x80000000 219 | padded += [0] * (15 - padded.length % 16) + [m.length * 8] 220 | 221 | assert_equal(padded.length % 16, 0) 222 | 223 | padded.each_slice(16) do |block| 224 | @sha256.hash_block(block) 225 | end 226 | 227 | assert_equal(@sha256.value, 228 | [0xcdc76e5c, 0x9914fb92, 0x81a1c7e2, 0x84d73e67, 229 | 0xf1809a48, 0xa497200e, 0x046d39cc, 0xc7112cd0]) 230 | end 231 | end 232 | end 233 | -------------------------------------------------------------------------------- /ext/spu_miner.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # include 20 | # include 21 | # include 22 | # include 23 | # include 24 | 25 | # include "spu/params.h" 26 | 27 | struct spu_miner { 28 | /* must be first for proper alignment */ 29 | volatile struct worker_params params; 30 | 31 | spe_context_ptr_t spe_context; 32 | uint32_t spe_entry; 33 | spe_stop_info_t stop_info; 34 | }; 35 | 36 | static 37 | VALUE m_initialize(int argc, VALUE *argv, VALUE self) 38 | { 39 | struct spu_miner *miner; 40 | 41 | if (argc < 0 || argc > 1) 42 | rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc); 43 | 44 | Data_Get_Struct(self, struct spu_miner, miner); 45 | 46 | if (argc > 0 && RTEST(argv[0])) 47 | miner->params.flags |= WORKER_FLAG_DEBUG; 48 | 49 | return self; 50 | } 51 | 52 | static 53 | VALUE run_miner(void *data) 54 | { 55 | struct spu_miner *miner = data; 56 | VALUE retval = Qnil; 57 | 58 | spe_context_run(miner->spe_context, &miner->spe_entry, 0, 59 | (void *) &miner->params, 0, &miner->stop_info); 60 | 61 | if (miner->stop_info.stop_reason != SPE_STOP_AND_SIGNAL) 62 | /* restart on next run */ 63 | miner->spe_entry = SPE_DEFAULT_ENTRY; 64 | else { 65 | switch (miner->stop_info.result.spe_signal_code) { 66 | case WORKER_IRQ_SIGNAL: 67 | /* SPE is responding to our stop signal; restart on next run */ 68 | miner->spe_entry = SPE_DEFAULT_ENTRY; 69 | 70 | /* fall through */ 71 | 72 | case WORKER_FOUND_NOTHING: 73 | retval = Qfalse; 74 | break; 75 | 76 | case WORKER_FOUND_SOMETHING: 77 | retval = Qtrue; 78 | break; 79 | } 80 | } 81 | 82 | return retval; 83 | } 84 | 85 | static 86 | void unblock_miner(void *data) 87 | { 88 | struct spu_miner *miner = data; 89 | 90 | /* signal SPE worker to stop */ 91 | spe_signal_write(miner->spe_context, SPE_SIG_NOTIFY_REG_1, 1); 92 | } 93 | 94 | static 95 | void get_stop_reason(const spe_stop_info_t *stop_info, 96 | const char **reason, int *code) 97 | { 98 | switch (stop_info->stop_reason) { 99 | case SPE_EXIT: 100 | *reason = "SPE_EXIT"; 101 | *code = stop_info->result.spe_exit_code; 102 | break; 103 | 104 | case SPE_STOP_AND_SIGNAL: 105 | *reason = "SPE_STOP_AND_SIGNAL"; 106 | *code = stop_info->result.spe_signal_code; 107 | break; 108 | 109 | case SPE_RUNTIME_ERROR: 110 | *reason = "SPE_RUNTIME_ERROR"; 111 | *code = stop_info->result.spe_runtime_error; 112 | break; 113 | 114 | case SPE_RUNTIME_EXCEPTION: 115 | *reason = "SPE_RUNTIME_EXCEPTION"; 116 | *code = stop_info->result.spe_runtime_exception; 117 | break; 118 | 119 | case SPE_RUNTIME_FATAL: 120 | *reason = "SPE_RUNTIME_FATAL"; 121 | *code = stop_info->result.spe_runtime_fatal; 122 | break; 123 | 124 | case SPE_CALLBACK_ERROR: 125 | *reason = "SPE_CALLBACK_ERROR"; 126 | *code = stop_info->result.spe_callback_error; 127 | break; 128 | 129 | case SPE_ISOLATION_ERROR: 130 | *reason = "SPE_ISOLATION_ERROR"; 131 | *code = stop_info->result.spe_isolation_error; 132 | break; 133 | 134 | default: 135 | *reason = "unknown reason"; 136 | *code = -1; 137 | } 138 | } 139 | 140 | static 141 | VALUE m_run(VALUE self, VALUE data, VALUE target, VALUE midstate, 142 | VALUE start_nonce, VALUE range) 143 | { 144 | struct spu_miner *miner; 145 | VALUE retval; 146 | 147 | Data_Get_Struct(self, struct spu_miner, miner); 148 | 149 | /* prepare parameters */ 150 | 151 | StringValue(data); 152 | StringValue(target); 153 | StringValue(midstate); 154 | 155 | if (RSTRING_LEN(data) != 128) 156 | rb_raise(rb_eArgError, "data must be 128 bytes"); 157 | if (RSTRING_LEN(target) != 32) 158 | rb_raise(rb_eArgError, "target must be 32 bytes"); 159 | if (RSTRING_LEN(midstate) != 32) 160 | rb_raise(rb_eArgError, "midstate must be 32 bytes"); 161 | 162 | memcpy((void *) miner->params.data, RSTRING_PTR(data), 128); 163 | memcpy((void *) miner->params.target, RSTRING_PTR(target), 32); 164 | memcpy((void *) miner->params.midstate, RSTRING_PTR(midstate), 32); 165 | 166 | miner->params.start_nonce = NUM2ULONG(start_nonce); 167 | miner->params.range = NUM2ULONG(range); 168 | 169 | /* unlock the Global Interpreter Lock and run the SPE context */ 170 | 171 | retval = rb_thread_blocking_region(run_miner, miner, 172 | unblock_miner, miner); 173 | 174 | switch (retval) { 175 | const char *reason; 176 | int code; 177 | 178 | case Qtrue: 179 | retval = rb_str_new((const char *) miner->params.data, 128); 180 | break; 181 | 182 | case Qnil: 183 | get_stop_reason(&miner->stop_info, &reason, &code); 184 | 185 | if (miner->stop_info.stop_reason == SPE_STOP_AND_SIGNAL && 186 | code == WORKER_VERIFY_ERROR) 187 | rb_raise(rb_eArgError, "midstate verification failed"); 188 | 189 | if (miner->stop_info.stop_reason == SPE_EXIT && 190 | code == WORKER_DMA_ERROR) 191 | rb_raise(rb_eRuntimeError, "SPE encountered DMA error"); 192 | 193 | rb_raise(rb_eRuntimeError, 194 | "SPE worker stopped with %s (0x%08x)", reason, code); 195 | } 196 | 197 | return retval; 198 | } 199 | 200 | static 201 | void i_free(struct spu_miner *miner) 202 | { 203 | spe_context_destroy(miner->spe_context); 204 | 205 | free(miner); 206 | } 207 | 208 | static 209 | VALUE i_allocate(VALUE klass) 210 | { 211 | struct spu_miner *miner; 212 | extern spe_program_handle_t spu_worker; 213 | 214 | if (posix_memalign((void **) &miner, 128, sizeof(*miner))) 215 | rb_raise(rb_eRuntimeError, "unable to allocate aligned memory"); 216 | 217 | miner->spe_context = spe_context_create(0, 0); 218 | if (miner->spe_context == 0) { 219 | free(miner); 220 | 221 | rb_raise(rb_eRuntimeError, "failed to create SPE context"); 222 | } 223 | 224 | if (spe_program_load(miner->spe_context, &spu_worker)) { 225 | spe_context_destroy(miner->spe_context); 226 | free(miner); 227 | 228 | rb_raise(rb_eRuntimeError, "failed to load SPE program"); 229 | } 230 | 231 | miner->spe_entry = SPE_DEFAULT_ENTRY; 232 | 233 | miner->params.flags = 0; 234 | 235 | return Data_Wrap_Struct(klass, 0, i_free, miner); 236 | } 237 | 238 | void Init_spu_miner(VALUE container) 239 | { 240 | VALUE cSPUMiner; 241 | int info; 242 | 243 | cSPUMiner = rb_define_class_under(container, "SPUMiner", rb_cObject); 244 | rb_define_alloc_func(cSPUMiner, i_allocate); 245 | 246 | rb_define_method(cSPUMiner, "initialize", m_initialize, -1); 247 | rb_define_method(cSPUMiner, "run", m_run, 5); 248 | 249 | info = spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, -1); 250 | if (info > 0) 251 | rb_define_const(cSPUMiner, "PHYSICAL_SPES", INT2NUM(info)); 252 | 253 | info = spe_cpu_info_get(SPE_COUNT_USABLE_SPES, -1); 254 | if (info > 0) 255 | rb_define_const(cSPUMiner, "USABLE_SPES", INT2NUM(info)); 256 | } 257 | -------------------------------------------------------------------------------- /cellminer.rb: -------------------------------------------------------------------------------- 1 | # 2 | # cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | # Copyright © 2011 Robert Leslie 4 | # 5 | # This program is free software; you can redistribute it and/or modify it 6 | # under the terms of the GNU General Public License (version 2) as 7 | # published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, but 10 | # WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along 15 | # with this program; if not, write to the Free Software Foundation, Inc., 16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | # 18 | 19 | require 'optparse' 20 | require 'uri' 21 | require 'thread' 22 | 23 | require_relative 'bitcoin.rb' 24 | require_relative 'ext/cellminer.so' 25 | 26 | require_relative 'sha256.rb' 27 | 28 | class CellMiner 29 | attr_accessor :options 30 | attr_reader :rpc 31 | 32 | class AbortMining < StandardError; end 33 | 34 | USER_AGENT = "Cell Miner" 35 | 36 | NSLICES = 128 37 | QUANTUM = 0x100000000 / NSLICES 38 | 39 | QUEUE_MAX = 384 40 | 41 | RETRY_INTERVAL = 30 42 | 43 | def initialize(argv = []) 44 | @options = Hash.new 45 | 46 | options[:num_spe] = Bitcoin::SPUMiner::USABLE_SPES 47 | options[:num_ppe] = 0 48 | options[:interval] = 60 49 | options[:debug] = $DEBUG 50 | 51 | OptionParser.new do |opts| 52 | opts.banner = "Usage: #{$0} [options] [server]" 53 | 54 | opts.on("-u", "--username USER", String, 55 | "RPC Username") do |username| 56 | options[:username] = username 57 | end 58 | 59 | opts.on("-p", "--password PASS", String, 60 | "RPC Password") do |password| 61 | options[:password] = password 62 | end 63 | 64 | opts.on("--spe N", Integer, 65 | "Number of SPEs to use (default %d)" % 66 | options[:num_spe]) do |opt| 67 | options[:num_spe] = opt 68 | end 69 | 70 | opts.on("--ppe N", Integer, 71 | "Number of PPE threads to use (default %d)" % 72 | options[:num_ppe]) do |opt| 73 | options[:num_ppe] = opt 74 | end 75 | 76 | opts.on("-i", "--interval SECS", Integer, 77 | "Work polling interval (default %d)" % 78 | options[:interval]) do |opt| 79 | options[:interval] = opt 80 | end 81 | 82 | opts.on("-b", "--balance", 83 | "Show balance and exit") do |opt| 84 | options[:balance] = opt 85 | end 86 | 87 | opts.on("--test", 88 | "Use known testing data") do |opt| 89 | options[:test] = opt 90 | end 91 | 92 | opts.on("-d", "--debug", 93 | "Show debugging output") do |opt| 94 | options[:debug] = opt 95 | end 96 | end.parse!(argv) 97 | 98 | server = argv.shift || ENV['BITCOIN_SERVER'] || 99 | begin 100 | warn "Warning: using default server localhost" 101 | 'localhost' 102 | end 103 | 104 | params = {} 105 | 106 | uri = URI.parse(server) rescue nil 107 | if uri.kind_of? URI::HTTP 108 | host, port = uri.host, uri.port 109 | params[:path] = uri.path unless uri.path.empty? 110 | else 111 | host, port = server.split(':') 112 | end 113 | 114 | params[:host] = host 115 | params[:port] = port.to_i if port 116 | 117 | params[:username] = options[:username] if options[:username] 118 | params[:password] = options[:password] if options[:password] 119 | 120 | @rpc = Bitcoin.rpc_proxy(params, USER_AGENT) 121 | @mutex = Mutex.new 122 | end 123 | 124 | def main 125 | if options[:balance] 126 | puts "Current balance = #{rpc.getbalance} BTC" 127 | exit 128 | end 129 | 130 | say "%s starting" % USER_AGENT 131 | 132 | work_queue = Queue.new 133 | solved_queue = Queue.new 134 | 135 | miner_proc = lambda do |miner_class| 136 | miner = miner_class.new(options[:debug]) 137 | 138 | loop do 139 | begin 140 | start = Time.now 141 | work = work_queue.shift 142 | debug "#{miner} Mining %08x..%08x" % 143 | [work[:start_nonce], work[:start_nonce] + work[:range] - 1] 144 | if solution = miner.run(work[:data], work[:target], work[:midstate], 145 | work[:start_nonce], work[:range]) 146 | debug "#{miner} Found solution" 147 | solved_queue << solution 148 | else 149 | Thread.current[:rate] = work[:range] / (Time.now - start) 150 | end 151 | rescue AbortMining 152 | end 153 | end 154 | end 155 | 156 | Thread.abort_on_exception = true 157 | 158 | miners = ThreadGroup.new 159 | class << miners 160 | include Enumerable 161 | 162 | alias << add 163 | 164 | def empty? 165 | list.empty? 166 | end 167 | 168 | def each(&block) 169 | list.each(&block) 170 | end 171 | 172 | def rate 173 | inject(0.0) {|sum, thread| sum + (thread[:rate] || 0) } 174 | end 175 | 176 | def abort 177 | each {|thread| thread.raise AbortMining } 178 | end 179 | end 180 | 181 | if options[:num_spe] > 0 182 | say "Creating %d SPU miner(s)" % options[:num_spe] 183 | options[:num_spe].times do 184 | miners << Thread.new(Bitcoin::SPUMiner, &miner_proc) 185 | end 186 | end 187 | 188 | if options[:num_ppe] > 0 189 | say "Creating %d PPU miner(s)" % options[:num_ppe] 190 | options[:num_ppe].times do 191 | miners << Thread.new(Bitcoin::PPUMiner, &miner_proc) 192 | end 193 | end 194 | 195 | if miners.empty? 196 | $stderr.puts "No miners!" 197 | exit 1 198 | end 199 | 200 | getwork_queue = Queue.new 201 | 202 | # work processing thread 203 | Thread.new do 204 | last_block = nil 205 | last_target = nil 206 | 207 | loop do 208 | work = getwork_queue.shift 209 | 210 | prev_block = work[:data][4..35].reverse.unpack('H*').first 211 | target = work[:target].unpack('H*').first 212 | 213 | msg = "Got work... %.3f Mhash/s, %d backlogged work items" % 214 | [miners.rate / 1_000_000, work_queue.length] 215 | 216 | if target != last_target 217 | last_target = target 218 | msg << "\n target = %s" % target 219 | end 220 | 221 | if prev_block != last_block 222 | last_block = prev_block 223 | msg << "\n prev = %s" % prev_block 224 | 225 | work_queue.clear 226 | miners.abort 227 | solved_queue.clear 228 | end 229 | 230 | say msg 231 | 232 | work[:range] = QUANTUM 233 | NSLICES.times do |i| 234 | work[:start_nonce] = i * QUANTUM 235 | work_queue << work.dup 236 | end 237 | 238 | # trim excess work 239 | work_queue.shift(true) while work_queue.length > QUEUE_MAX 240 | end 241 | end 242 | 243 | # work gathering thread 244 | getwork_thread = Thread.new do 245 | loop do 246 | getwork_queue << getwork do |poll_rpc| 247 | unless @long_polling 248 | @long_polling = true 249 | say "Starting long poll" 250 | 251 | # long polling thread 252 | Thread.new do 253 | loop do 254 | work = getwork(poll_rpc) 255 | say "Long poll returned" 256 | getwork_queue << work 257 | end 258 | end 259 | end 260 | end 261 | 262 | sleep options[:interval] 263 | end 264 | end 265 | 266 | # solution gathering thread 267 | loop do 268 | solution = solved_queue.shift 269 | 270 | # send back to server... 271 | response = sendwork(solution) 272 | 273 | say "Solved? (%s)\n %s hash = %s" % 274 | [response, response == true ? '*' : ' ', block_hash(solution)] 275 | 276 | return if options[:test] 277 | 278 | getwork_thread.run if response == false 279 | end 280 | end 281 | 282 | private 283 | 284 | def say(info) 285 | @mutex.synchronize do 286 | puts "[%s] %s" % [Time.now.strftime("%Y-%m-%d %H:%M:%S"), info] 287 | end 288 | end 289 | 290 | def debug(info) 291 | say(info) if options[:debug] 292 | end 293 | 294 | def getwork(rpc = rpc, &block) 295 | begin 296 | work = options[:test] ? testwork : rpc.getwork(&block) 297 | rescue => err 298 | say "RPC (getwork) error: %s" % err 299 | sleep RETRY_INTERVAL 300 | retry 301 | end 302 | 303 | # unpack hex strings and fix byte ordering 304 | work = work.map do |k, v| 305 | k = k.to_sym 306 | v = [v.to_s].pack('H*') 307 | v = (k == :target) ? v.reverse : v.unpack('V*').pack('N*') 308 | [k, v] 309 | end 310 | Hash[work] 311 | end 312 | 313 | def sendwork(solution) 314 | data = solution.unpack('N*').pack('V*').unpack('H*').first 315 | 316 | begin 317 | rpc.getwork(data) 318 | rescue => err 319 | say "RPC (sendwork) error: %s" % err 320 | sleep RETRY_INTERVAL 321 | retry 322 | end 323 | end 324 | 325 | def block_hash(data) 326 | hash0 = SHA256.new.update(data) 327 | hash1 = [UInt256.new(hash0.hexdigest).byte_string, 328 | 0x80000000, 0, 0, 0, 0, 0, 0, 0x100].pack('a32N8') 329 | hash1 = SHA256.new.update(hash1) 330 | hash1.digest.reverse.unpack('H*').first 331 | end 332 | 333 | def testwork 334 | say "Using test data" 335 | 336 | # Test data for known block (#115558) 337 | hash = UInt256.new("000000000000bd26aaf867f23a7b66b6" \ 338 | "2ffe1e402f79a424ef8b3e4e84c68f32") 339 | version = 1 340 | prev_block = UInt256.new("00000000000090b0cae8c5fea2fffac9" \ 341 | "f909c097f0402637c59647b91bbd896f") 342 | merkle_root = UInt256.new("15fbf39fd7120dd06950467fbdf9d226" \ 343 | "9ed3f63796b0acab93d89e2888e2b10a") 344 | time = 1301376879 345 | bits = 453047097 346 | nonce = 3406758657 347 | 348 | datav = [version, 349 | prev_block.reverse_endian.byte_string, 350 | merkle_root.reverse_endian.byte_string, 351 | time, bits, nonce, 352 | 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0280] 353 | 354 | check = SHA256.new.update(datav.pack('Va32a32V3N12')) 355 | 356 | hash1 = [UInt256.new(check.hexdigest).byte_string, 357 | 0x80000000, 0, 0, 0, 0, 0, 0, 0x100].pack('a32N8') 358 | 359 | check = SHA256.new.update(hash1) 360 | 361 | debug "Supposed hash\n = %s" % hash 362 | debug "Calculated hash\n = %s" % 363 | UInt256.new(check.hexdigest).reverse_endian 364 | 365 | # zero nonce 366 | datav[5] = 0 367 | data = datav.pack('Va32a32V3N12') 368 | midstate = UInt256.new(SHA256.new.update(data[0..63]).hexdigest) 369 | 370 | target = UInt256.new((bits & 0x00ffffff) * 2**(8 * ((bits >> 24) - 3))) 371 | 372 | # reverse-endian crap 373 | data = data.unpack('V*').pack('N*') 374 | target = target.reverse_endian.byte_string 375 | midstate = midstate.byte_string.unpack('V*').pack('N*') 376 | hash1 = hash1.unpack('V*').pack('N*') 377 | 378 | { 379 | :data => data.unpack('H*').first, 380 | :target => target.unpack('H*').first, 381 | :midstate => midstate.unpack('H*').first, 382 | :hash1 => hash1.unpack('H*').first 383 | } 384 | end 385 | end 386 | 387 | class UInt256 388 | attr_accessor :value 389 | 390 | def initialize(value) 391 | case value 392 | when Integer 393 | when String 394 | value = pack_chars [value].pack('H*').unpack('C*') 395 | else 396 | raise TypeError, "can't cast #{value.class} as #{self.class}" 397 | end 398 | 399 | @value = value 400 | end 401 | 402 | def to_s 403 | "%064x" % value 404 | end 405 | 406 | def byte_string 407 | [to_s].pack('H*') 408 | end 409 | 410 | def reverse_endian 411 | self.class.new(pack_chars byte_string.unpack('C*').reverse) 412 | end 413 | 414 | private 415 | 416 | def pack_chars(chars) 417 | chars.inject(0) {|v, ch| (v << 8) + ch } 418 | end 419 | end 420 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /ext/spu/sha256.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # include 20 | # include 21 | 22 | # include "sha256.h" 23 | # include "util.h" 24 | 25 | const hash_t H0 = { 26 | { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 27 | 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 } 28 | }; 29 | 30 | static 31 | const uint32_t K[64] = { 32 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 33 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 34 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 35 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 36 | 37 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 38 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 39 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 40 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 41 | 42 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 43 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 44 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 45 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 46 | 47 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 48 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 49 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 50 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 51 | }; 52 | 53 | static inline 54 | uint32_t SHR(unsigned int n, uint32_t x) 55 | { 56 | return x >> n; 57 | } 58 | 59 | static inline 60 | vec_uint4 vec_SHR(unsigned int n, vec_uint4 x) 61 | { 62 | return spu_sr(x, n); 63 | } 64 | 65 | static inline 66 | uint32_t ROTR(unsigned int n, uint32_t x) 67 | { 68 | return (x >> n) | (x << (32 - n)); 69 | } 70 | 71 | static inline 72 | vec_uint4 vec_ROTR(unsigned int n, vec_uint4 x) 73 | { 74 | return spu_rl(x, 32 - n); 75 | } 76 | 77 | static inline 78 | uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) 79 | { 80 | return (x & y) ^ (~x & z); 81 | } 82 | 83 | static inline 84 | vec_uint4 vec_Ch(vec_uint4 x, vec_uint4 y, vec_uint4 z) 85 | { 86 | return spu_sel(z, y, x); 87 | } 88 | 89 | static inline 90 | uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) 91 | { 92 | return (x & y) ^ (x & z) ^ (y & z); 93 | } 94 | 95 | static inline 96 | vec_uint4 vec_Maj(vec_uint4 x, vec_uint4 y, vec_uint4 z) 97 | { 98 | return spu_sel(x, y, spu_xor(x, z)); 99 | } 100 | 101 | static inline 102 | uint32_t Sigma0(uint32_t x) 103 | { 104 | return ROTR(2, x) ^ ROTR(13, x) ^ ROTR(22, x); 105 | } 106 | 107 | static inline 108 | vec_uint4 vec_Sigma0(vec_uint4 x) 109 | { 110 | return spu_xor(spu_xor(vec_ROTR( 2, x), 111 | vec_ROTR(13, x)), 112 | vec_ROTR(22, x)); 113 | } 114 | 115 | static inline 116 | uint32_t Sigma1(uint32_t x) 117 | { 118 | return ROTR(6, x) ^ ROTR(11, x) ^ ROTR(25, x); 119 | } 120 | 121 | static inline 122 | vec_uint4 vec_Sigma1(vec_uint4 x) 123 | { 124 | return spu_xor(spu_xor(vec_ROTR( 6, x), 125 | vec_ROTR(11, x)), 126 | vec_ROTR(25, x)); 127 | } 128 | 129 | static inline 130 | uint32_t sigma0(uint32_t x) 131 | { 132 | return ROTR(7, x) ^ ROTR(18, x) ^ SHR(3, x); 133 | } 134 | 135 | static inline 136 | vec_uint4 vec_sigma0(vec_uint4 x) 137 | { 138 | return spu_xor(spu_xor(vec_ROTR( 7, x), 139 | vec_ROTR(18, x)), 140 | vec_SHR(3, x)); 141 | } 142 | 143 | static inline 144 | uint32_t sigma1(uint32_t x) 145 | { 146 | return ROTR(17, x) ^ ROTR(19, x) ^ SHR(10, x); 147 | } 148 | 149 | static inline 150 | vec_uint4 vec_sigma1(vec_uint4 x) 151 | { 152 | return spu_xor(spu_xor(vec_ROTR(17, x), 153 | vec_ROTR(19, x)), 154 | vec_SHR(10, x)); 155 | } 156 | 157 | # define ADD(a, b) (a + b) 158 | 159 | # define W(t) \ 160 | ADD(sigma1(W[(t - 2) % 16]), \ 161 | ADD(W[(t - 7) % 16], \ 162 | ADD(sigma0(W[(t - 15) % 16]), \ 163 | W[t % 16]))) 164 | 165 | # define T1(t, e, f, g, h) \ 166 | ADD(h, \ 167 | ADD(Sigma1(e), \ 168 | ADD(Ch(e, f, g), \ 169 | ADD(W[t % 16], \ 170 | K[t])))) 171 | 172 | # define T2(a, b, c) \ 173 | ADD(Sigma0(a), Maj(a, b, c)) 174 | 175 | # define ROUND(t) \ 176 | do { \ 177 | T1 = T1(t, e, f, g, h); \ 178 | T2 = T2(a, b, c); \ 179 | h = g; \ 180 | g = f; \ 181 | f = e; \ 182 | e = ADD(d, T1); \ 183 | d = c; \ 184 | c = b; \ 185 | b = a; \ 186 | a = ADD(T1, T2); \ 187 | } while (0) 188 | 189 | /* 190 | * NAME: sha256->update() 191 | * DESCRIPTION: update SHA-256 digest with a single message block 192 | */ 193 | hash_t sha256_update(const message_t M, const hash_t init) 194 | { 195 | hash_t digest; 196 | # if !defined(UNROLL_SHA256) 197 | int t; 198 | # endif 199 | uint32_t W[16], a, b, c, d, e, f, g, h, T1, T2; 200 | 201 | a = init.words[0]; 202 | b = init.words[1]; 203 | c = init.words[2]; 204 | d = init.words[3]; 205 | e = init.words[4]; 206 | f = init.words[5]; 207 | g = init.words[6]; 208 | h = init.words[7]; 209 | 210 | # ifdef UNROLL_SHA256 211 | W[ 0] = M.words[ 0]; ROUND( 0); 212 | W[ 1] = M.words[ 1]; ROUND( 1); 213 | W[ 2] = M.words[ 2]; ROUND( 2); 214 | W[ 3] = M.words[ 3]; ROUND( 3); 215 | W[ 4] = M.words[ 4]; ROUND( 4); 216 | W[ 5] = M.words[ 5]; ROUND( 5); 217 | W[ 6] = M.words[ 6]; ROUND( 6); 218 | W[ 7] = M.words[ 7]; ROUND( 7); 219 | 220 | W[ 8] = M.words[ 8]; ROUND( 8); 221 | W[ 9] = M.words[ 9]; ROUND( 9); 222 | W[10] = M.words[10]; ROUND(10); 223 | W[11] = M.words[11]; ROUND(11); 224 | W[12] = M.words[12]; ROUND(12); 225 | W[13] = M.words[13]; ROUND(13); 226 | W[14] = M.words[14]; ROUND(14); 227 | W[15] = M.words[15]; ROUND(15); 228 | # else 229 | for (t = 0; t < 16; ++t) { 230 | W[t] = M.words[t]; 231 | ROUND(t); 232 | } 233 | # endif 234 | 235 | # ifdef UNROLL_SHA256 236 | W[16 % 16] = W(16); ROUND(16); 237 | W[17 % 16] = W(17); ROUND(17); 238 | W[18 % 16] = W(18); ROUND(18); 239 | W[19 % 16] = W(19); ROUND(19); 240 | W[20 % 16] = W(20); ROUND(20); 241 | W[21 % 16] = W(21); ROUND(21); 242 | W[22 % 16] = W(22); ROUND(22); 243 | W[23 % 16] = W(23); ROUND(23); 244 | 245 | W[24 % 16] = W(24); ROUND(24); 246 | W[25 % 16] = W(25); ROUND(25); 247 | W[26 % 16] = W(26); ROUND(26); 248 | W[27 % 16] = W(27); ROUND(27); 249 | W[28 % 16] = W(28); ROUND(28); 250 | W[29 % 16] = W(29); ROUND(29); 251 | W[30 % 16] = W(30); ROUND(30); 252 | W[31 % 16] = W(31); ROUND(31); 253 | 254 | W[32 % 16] = W(32); ROUND(32); 255 | W[33 % 16] = W(33); ROUND(33); 256 | W[34 % 16] = W(34); ROUND(34); 257 | W[35 % 16] = W(35); ROUND(35); 258 | W[36 % 16] = W(36); ROUND(36); 259 | W[37 % 16] = W(37); ROUND(37); 260 | W[38 % 16] = W(38); ROUND(38); 261 | W[39 % 16] = W(39); ROUND(39); 262 | 263 | W[40 % 16] = W(40); ROUND(40); 264 | W[41 % 16] = W(41); ROUND(41); 265 | W[42 % 16] = W(42); ROUND(42); 266 | W[43 % 16] = W(43); ROUND(43); 267 | W[44 % 16] = W(44); ROUND(44); 268 | W[45 % 16] = W(45); ROUND(45); 269 | W[46 % 16] = W(46); ROUND(46); 270 | W[47 % 16] = W(47); ROUND(47); 271 | 272 | W[48 % 16] = W(48); ROUND(48); 273 | W[49 % 16] = W(49); ROUND(49); 274 | W[50 % 16] = W(50); ROUND(50); 275 | W[51 % 16] = W(51); ROUND(51); 276 | W[52 % 16] = W(52); ROUND(52); 277 | W[53 % 16] = W(53); ROUND(53); 278 | W[54 % 16] = W(54); ROUND(54); 279 | W[55 % 16] = W(55); ROUND(55); 280 | 281 | W[56 % 16] = W(56); ROUND(56); 282 | W[57 % 16] = W(57); ROUND(57); 283 | W[58 % 16] = W(58); ROUND(58); 284 | W[59 % 16] = W(59); ROUND(59); 285 | W[60 % 16] = W(60); ROUND(60); 286 | W[61 % 16] = W(61); ROUND(61); 287 | W[62 % 16] = W(62); ROUND(62); 288 | W[63 % 16] = W(63); ROUND(63); 289 | # else 290 | for (t = 16; t < 64; ++t) { 291 | W[t % 16] = W(t); 292 | ROUND(t); 293 | } 294 | # endif 295 | 296 | digest.words[0] = ADD(a, init.words[0]); 297 | digest.words[1] = ADD(b, init.words[1]); 298 | digest.words[2] = ADD(c, init.words[2]); 299 | digest.words[3] = ADD(d, init.words[3]); 300 | digest.words[4] = ADD(e, init.words[4]); 301 | digest.words[5] = ADD(f, init.words[5]); 302 | digest.words[6] = ADD(g, init.words[6]); 303 | digest.words[7] = ADD(h, init.words[7]); 304 | 305 | return digest; 306 | } 307 | 308 | # define Ch vec_Ch 309 | # define Maj vec_Maj 310 | # define Sigma0 vec_Sigma0 311 | # define Sigma1 vec_Sigma1 312 | # define sigma0 vec_sigma0 313 | # define sigma1 vec_sigma1 314 | 315 | # undef ADD 316 | # define ADD(a, b) spu_add(a, b) 317 | 318 | # define SPLAT(x) spu_splats(x) 319 | 320 | /* 321 | * NAME: sha256->search() 322 | * DESCRIPTION: try to find a nonce which satisfies a target hash 323 | */ 324 | int64_t sha256_search(const message_t M, 325 | const hash_t target, const hash_t midstate, 326 | uint32_t start_nonce, uint32_t range) 327 | { 328 | uint32_t nonce, stop_nonce = start_nonce + range + (4 - (range % 4)) % 4; 329 | uint32_t answer; 330 | # if !defined(UNROLL_SHA256) 331 | int t; 332 | # endif 333 | vec_uint4 W0[3], a0, b0, c0, d0, e0, f0, g0, h0; 334 | vec_uint4 W[16], a, b, c, d, e, f, g, h, T1, T2; 335 | vec_uint4 borrow, solution; 336 | const vec_uchar16 reverse_endian = { 337 | 3, 2, 1, 0, 338 | 7, 6, 5, 4, 339 | 11, 10, 9, 8, 340 | 15, 14, 13, 12 341 | }; 342 | 343 | /* precompute first three rounds */ 344 | 345 | a = SPLAT(midstate.words[0]); 346 | b = SPLAT(midstate.words[1]); 347 | c = SPLAT(midstate.words[2]); 348 | d = SPLAT(midstate.words[3]); 349 | e = SPLAT(midstate.words[4]); 350 | f = SPLAT(midstate.words[5]); 351 | g = SPLAT(midstate.words[6]); 352 | h = SPLAT(midstate.words[7]); 353 | 354 | # ifdef UNROLL_SHA256 355 | W[0] = SPLAT(M.words[0]); ROUND(0); 356 | W[1] = SPLAT(M.words[1]); ROUND(1); 357 | W[2] = SPLAT(M.words[2]); ROUND(2); 358 | # else 359 | for (t = 0; t < 3; ++t) { 360 | W[t] = SPLAT(M.words[t]); 361 | ROUND(t); 362 | } 363 | # endif 364 | 365 | W0[0] = W[0]; 366 | W0[1] = W[1]; 367 | W0[2] = W[2]; 368 | 369 | a0 = a; 370 | b0 = b; 371 | c0 = c; 372 | d0 = d; 373 | e0 = e; 374 | f0 = f; 375 | g0 = g; 376 | h0 = h; 377 | 378 | /* do the search, four at a time */ 379 | 380 | for (nonce = start_nonce; nonce != stop_nonce; nonce += 4) { 381 | W[0] = W0[0]; 382 | W[1] = W0[1]; 383 | W[2] = W0[2]; 384 | 385 | a = a0; 386 | b = b0; 387 | c = c0; 388 | d = d0; 389 | e = e0; 390 | f = f0; 391 | g = g0; 392 | h = h0; 393 | 394 | /* t = 3 */ 395 | W[3] = (vec_uint4) { nonce + 0, nonce + 1, nonce + 2, nonce + 3 }; 396 | ROUND(3); 397 | 398 | # ifdef UNROLL_SHA256 399 | W[ 4] = SPLAT(M.words[ 4]); ROUND( 4); 400 | W[ 5] = SPLAT(M.words[ 5]); ROUND( 5); 401 | W[ 6] = SPLAT(M.words[ 6]); ROUND( 6); 402 | W[ 7] = SPLAT(M.words[ 7]); ROUND( 7); 403 | 404 | W[ 8] = SPLAT(M.words[ 8]); ROUND( 8); 405 | W[ 9] = SPLAT(M.words[ 9]); ROUND( 9); 406 | W[10] = SPLAT(M.words[10]); ROUND(10); 407 | W[11] = SPLAT(M.words[11]); ROUND(11); 408 | W[12] = SPLAT(M.words[12]); ROUND(12); 409 | W[13] = SPLAT(M.words[13]); ROUND(13); 410 | W[14] = SPLAT(M.words[14]); ROUND(14); 411 | W[15] = SPLAT(M.words[15]); ROUND(15); 412 | # else 413 | for (t = 4; t < 16; ++t) { 414 | W[t] = SPLAT(M.words[t]); 415 | ROUND(t); 416 | } 417 | # endif 418 | 419 | # ifdef UNROLL_SHA256 420 | W[16 % 16] = W(16); ROUND(16); 421 | W[17 % 16] = W(17); ROUND(17); 422 | W[18 % 16] = W(18); ROUND(18); 423 | W[19 % 16] = W(19); ROUND(19); 424 | W[20 % 16] = W(20); ROUND(20); 425 | W[21 % 16] = W(21); ROUND(21); 426 | W[22 % 16] = W(22); ROUND(22); 427 | W[23 % 16] = W(23); ROUND(23); 428 | 429 | W[24 % 16] = W(24); ROUND(24); 430 | W[25 % 16] = W(25); ROUND(25); 431 | W[26 % 16] = W(26); ROUND(26); 432 | W[27 % 16] = W(27); ROUND(27); 433 | W[28 % 16] = W(28); ROUND(28); 434 | W[29 % 16] = W(29); ROUND(29); 435 | W[30 % 16] = W(30); ROUND(30); 436 | W[31 % 16] = W(31); ROUND(31); 437 | 438 | W[32 % 16] = W(32); ROUND(32); 439 | W[33 % 16] = W(33); ROUND(33); 440 | W[34 % 16] = W(34); ROUND(34); 441 | W[35 % 16] = W(35); ROUND(35); 442 | W[36 % 16] = W(36); ROUND(36); 443 | W[37 % 16] = W(37); ROUND(37); 444 | W[38 % 16] = W(38); ROUND(38); 445 | W[39 % 16] = W(39); ROUND(39); 446 | 447 | W[40 % 16] = W(40); ROUND(40); 448 | W[41 % 16] = W(41); ROUND(41); 449 | W[42 % 16] = W(42); ROUND(42); 450 | W[43 % 16] = W(43); ROUND(43); 451 | W[44 % 16] = W(44); ROUND(44); 452 | W[45 % 16] = W(45); ROUND(45); 453 | W[46 % 16] = W(46); ROUND(46); 454 | W[47 % 16] = W(47); ROUND(47); 455 | 456 | W[48 % 16] = W(48); ROUND(48); 457 | W[49 % 16] = W(49); ROUND(49); 458 | W[50 % 16] = W(50); ROUND(50); 459 | W[51 % 16] = W(51); ROUND(51); 460 | W[52 % 16] = W(52); ROUND(52); 461 | W[53 % 16] = W(53); ROUND(53); 462 | W[54 % 16] = W(54); ROUND(54); 463 | W[55 % 16] = W(55); ROUND(55); 464 | 465 | W[56 % 16] = W(56); ROUND(56); 466 | W[57 % 16] = W(57); ROUND(57); 467 | W[58 % 16] = W(58); ROUND(58); 468 | W[59 % 16] = W(59); ROUND(59); 469 | W[60 % 16] = W(60); ROUND(60); 470 | W[61 % 16] = W(61); ROUND(61); 471 | W[62 % 16] = W(62); ROUND(62); 472 | W[63 % 16] = W(63); ROUND(63); 473 | # else 474 | for (t = 16; t < 64; ++t) { 475 | W[t % 16] = W(t); 476 | ROUND(t); 477 | } 478 | # endif 479 | 480 | W[0] = ADD(a, midstate.words[0]); 481 | W[1] = ADD(b, midstate.words[1]); 482 | W[2] = ADD(c, midstate.words[2]); 483 | W[3] = ADD(d, midstate.words[3]); 484 | W[4] = ADD(e, midstate.words[4]); 485 | W[5] = ADD(f, midstate.words[5]); 486 | W[6] = ADD(g, midstate.words[6]); 487 | W[7] = ADD(h, midstate.words[7]); 488 | 489 | /* first SHA-256 complete */ 490 | 491 | a = SPLAT(H0.words[0]); 492 | b = SPLAT(H0.words[1]); 493 | c = SPLAT(H0.words[2]); 494 | d = SPLAT(H0.words[3]); 495 | e = SPLAT(H0.words[4]); 496 | f = SPLAT(H0.words[5]); 497 | g = SPLAT(H0.words[6]); 498 | h = SPLAT(H0.words[7]); 499 | 500 | ROUND(0); 501 | ROUND(1); 502 | ROUND(2); 503 | ROUND(3); 504 | ROUND(4); 505 | ROUND(5); 506 | ROUND(6); 507 | ROUND(7); 508 | 509 | W[ 8] = SPLAT(0x80000000U); ROUND( 8); 510 | 511 | # ifdef UNROLL_SHA256 512 | W[ 9] = SPLAT(0x00000000U); ROUND( 9); 513 | W[10] = SPLAT(0x00000000U); ROUND(10); 514 | W[11] = SPLAT(0x00000000U); ROUND(11); 515 | W[12] = SPLAT(0x00000000U); ROUND(12); 516 | W[13] = SPLAT(0x00000000U); ROUND(13); 517 | W[14] = SPLAT(0x00000000U); ROUND(14); 518 | # else 519 | for (t = 9; t < 15; ++t) { 520 | W[t] = SPLAT(0U); 521 | ROUND(t); 522 | } 523 | # endif 524 | 525 | W[15] = SPLAT(0x00000100U); ROUND(15); 526 | 527 | # ifdef UNROLL_SHA256 528 | W[16 % 16] = W(16); ROUND(16); 529 | W[17 % 16] = W(17); ROUND(17); 530 | W[18 % 16] = W(18); ROUND(18); 531 | W[19 % 16] = W(19); ROUND(19); 532 | W[20 % 16] = W(20); ROUND(20); 533 | W[21 % 16] = W(21); ROUND(21); 534 | W[22 % 16] = W(22); ROUND(22); 535 | W[23 % 16] = W(23); ROUND(23); 536 | 537 | W[24 % 16] = W(24); ROUND(24); 538 | W[25 % 16] = W(25); ROUND(25); 539 | W[26 % 16] = W(26); ROUND(26); 540 | W[27 % 16] = W(27); ROUND(27); 541 | W[28 % 16] = W(28); ROUND(28); 542 | W[29 % 16] = W(29); ROUND(29); 543 | W[30 % 16] = W(30); ROUND(30); 544 | W[31 % 16] = W(31); ROUND(31); 545 | 546 | W[32 % 16] = W(32); ROUND(32); 547 | W[33 % 16] = W(33); ROUND(33); 548 | W[34 % 16] = W(34); ROUND(34); 549 | W[35 % 16] = W(35); ROUND(35); 550 | W[36 % 16] = W(36); ROUND(36); 551 | W[37 % 16] = W(37); ROUND(37); 552 | W[38 % 16] = W(38); ROUND(38); 553 | W[39 % 16] = W(39); ROUND(39); 554 | 555 | W[40 % 16] = W(40); ROUND(40); 556 | W[41 % 16] = W(41); ROUND(41); 557 | W[42 % 16] = W(42); ROUND(42); 558 | W[43 % 16] = W(43); ROUND(43); 559 | W[44 % 16] = W(44); ROUND(44); 560 | W[45 % 16] = W(45); ROUND(45); 561 | W[46 % 16] = W(46); ROUND(46); 562 | W[47 % 16] = W(47); ROUND(47); 563 | 564 | W[48 % 16] = W(48); ROUND(48); 565 | W[49 % 16] = W(49); ROUND(49); 566 | W[50 % 16] = W(50); ROUND(50); 567 | W[51 % 16] = W(51); ROUND(51); 568 | W[52 % 16] = W(52); ROUND(52); 569 | W[53 % 16] = W(53); ROUND(53); 570 | W[54 % 16] = W(54); ROUND(54); 571 | W[55 % 16] = W(55); ROUND(55); 572 | 573 | W[56 % 16] = W(56); ROUND(56); 574 | W[57 % 16] = W(57); ROUND(57); 575 | W[58 % 16] = W(58); ROUND(58); 576 | W[59 % 16] = W(59); ROUND(59); 577 | /* t = 60..63 delayed */ 578 | # else 579 | for (t = 16; t < 60; ++t) { 580 | W[t % 16] = W(t); 581 | ROUND(t); 582 | } 583 | # endif 584 | 585 | W[60 % 16] = W(60); 586 | T1 = T1(60, e, f, g, h); 587 | 588 | T2 = ADD(ADD(d, T1), H0.words[7]); 589 | 590 | /* quick check to see if any element of the last word vector is zero */ 591 | if (likely(spu_extract(spu_gather(spu_cmpeq(T2, 0)), 0) == 0)) 592 | continue; 593 | 594 | /* we have something interesting; finish the SHA-256 */ 595 | 596 | ROUND(60); 597 | 598 | # ifdef UNROLL_SHA256 599 | W[61 % 16] = W(61); ROUND(61); 600 | W[62 % 16] = W(62); ROUND(62); 601 | W[63 % 16] = W(63); ROUND(63); 602 | # else 603 | for (t = 61; t < 64; ++t) { 604 | W[t % 16] = W(t); 605 | ROUND(t); 606 | } 607 | # endif 608 | 609 | a = ADD(a, H0.words[0]); 610 | b = ADD(b, H0.words[1]); 611 | c = ADD(c, H0.words[2]); 612 | d = ADD(d, H0.words[3]); 613 | e = ADD(e, H0.words[4]); 614 | f = ADD(f, H0.words[5]); 615 | g = ADD(g, H0.words[6]); 616 | h = ADD(h, H0.words[7]); 617 | 618 | /* now do the full (reversed-endian) subtraction */ 619 | 620 | borrow = spu_genb(SPLAT(target.words[7]), 621 | spu_shuffle(a, a, reverse_endian)); 622 | borrow = spu_genbx(SPLAT(target.words[6]), 623 | spu_shuffle(b, b, reverse_endian), borrow); 624 | borrow = spu_genbx(SPLAT(target.words[5]), 625 | spu_shuffle(c, c, reverse_endian), borrow); 626 | borrow = spu_genbx(SPLAT(target.words[4]), 627 | spu_shuffle(d, d, reverse_endian), borrow); 628 | borrow = spu_genbx(SPLAT(target.words[3]), 629 | spu_shuffle(e, e, reverse_endian), borrow); 630 | borrow = spu_genbx(SPLAT(target.words[2]), 631 | spu_shuffle(f, f, reverse_endian), borrow); 632 | borrow = spu_genbx(SPLAT(target.words[1]), 633 | spu_shuffle(g, g, reverse_endian), borrow); 634 | borrow = spu_genbx(SPLAT(target.words[0]), 635 | spu_shuffle(h, h, reverse_endian), borrow); 636 | 637 | solution = spu_gather(borrow); 638 | 639 | if (likely(spu_extract(solution, 0) == 0)) 640 | continue; 641 | 642 | /* we have a winner */ 643 | 644 | answer = nonce + (spu_extract(spu_cntlz(solution), 0) - 28); 645 | if (answer - start_nonce < range) 646 | return answer; 647 | } 648 | 649 | return -1; 650 | } 651 | -------------------------------------------------------------------------------- /ext/ppu/sha256.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cellminer - Bitcoin miner for the Cell Broadband Engine Architecture 3 | * Copyright © 2011 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License (version 2) as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | */ 18 | 19 | # include 20 | # include 21 | # include 22 | 23 | # include "sha256.h" 24 | # include "util.h" 25 | 26 | const hash_t H0 = { 27 | { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 28 | 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 } 29 | }; 30 | 31 | static 32 | const uint32_t K[64] = { 33 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 34 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 35 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 36 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 37 | 38 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 39 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 40 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 41 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 42 | 43 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 44 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 45 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 46 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 47 | 48 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 49 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 50 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 51 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 52 | }; 53 | 54 | static inline 55 | uint32_t SHR(unsigned int n, uint32_t x) 56 | { 57 | return x >> n; 58 | } 59 | 60 | static inline 61 | vec_uint4 vec_SHR(unsigned int n, vec_uint4 x) 62 | { 63 | return vec_sr(x, vec_splat_u32(n)); 64 | } 65 | 66 | static inline 67 | uint32_t ROTR(unsigned int n, uint32_t x) 68 | { 69 | return (x >> n) | (x << (32 - n)); 70 | } 71 | 72 | static inline 73 | vec_uint4 vec_ROTR(unsigned int n, vec_uint4 x) 74 | { 75 | return vec_rl(x, vec_splats(32 - n)); 76 | } 77 | 78 | static inline 79 | uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) 80 | { 81 | return (x & y) ^ (~x & z); 82 | } 83 | 84 | static inline 85 | vec_uint4 vec_Ch(vec_uint4 x, vec_uint4 y, vec_uint4 z) 86 | { 87 | return vec_sel(z, y, x); 88 | } 89 | 90 | static inline 91 | uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) 92 | { 93 | return (x & y) ^ (x & z) ^ (y & z); 94 | } 95 | 96 | static inline 97 | vec_uint4 vec_Maj(vec_uint4 x, vec_uint4 y, vec_uint4 z) 98 | { 99 | return vec_sel(x, y, vec_xor(x, z)); 100 | } 101 | 102 | static inline 103 | uint32_t Sigma0(uint32_t x) 104 | { 105 | return ROTR(2, x) ^ ROTR(13, x) ^ ROTR(22, x); 106 | } 107 | 108 | static inline 109 | vec_uint4 vec_Sigma0(vec_uint4 x) 110 | { 111 | return vec_xor(vec_xor(vec_ROTR( 2, x), 112 | vec_ROTR(13, x)), 113 | vec_ROTR(22, x)); 114 | } 115 | 116 | static inline 117 | uint32_t Sigma1(uint32_t x) 118 | { 119 | return ROTR(6, x) ^ ROTR(11, x) ^ ROTR(25, x); 120 | } 121 | 122 | static inline 123 | vec_uint4 vec_Sigma1(vec_uint4 x) 124 | { 125 | return vec_xor(vec_xor(vec_ROTR( 6, x), 126 | vec_ROTR(11, x)), 127 | vec_ROTR(25, x)); 128 | } 129 | 130 | static inline 131 | uint32_t sigma0(uint32_t x) 132 | { 133 | return ROTR(7, x) ^ ROTR(18, x) ^ SHR(3, x); 134 | } 135 | 136 | static inline 137 | vec_uint4 vec_sigma0(vec_uint4 x) 138 | { 139 | return vec_xor(vec_xor(vec_ROTR( 7, x), 140 | vec_ROTR(18, x)), 141 | vec_SHR(3, x)); 142 | } 143 | 144 | static inline 145 | uint32_t sigma1(uint32_t x) 146 | { 147 | return ROTR(17, x) ^ ROTR(19, x) ^ SHR(10, x); 148 | } 149 | 150 | static inline 151 | vec_uint4 vec_sigma1(vec_uint4 x) 152 | { 153 | return vec_xor(vec_xor(vec_ROTR(17, x), 154 | vec_ROTR(19, x)), 155 | vec_SHR(10, x)); 156 | } 157 | 158 | # define ADD(a, b) (a + b) 159 | # define SPLAT(x) (x) 160 | 161 | # define W(t) \ 162 | ADD(sigma1(W[(t - 2) % 16]), \ 163 | ADD(W[(t - 7) % 16], \ 164 | ADD(sigma0(W[(t - 15) % 16]), \ 165 | W[t % 16]))) 166 | 167 | # define T1(t, e, f, g, h) \ 168 | ADD(h, \ 169 | ADD(Sigma1(e), \ 170 | ADD(Ch(e, f, g), \ 171 | ADD(W[t % 16], \ 172 | SPLAT(K[t]))))) 173 | 174 | # define T2(a, b, c) \ 175 | ADD(Sigma0(a), Maj(a, b, c)) 176 | 177 | # define ROUND(t) \ 178 | do { \ 179 | T1 = T1(t, e, f, g, h); \ 180 | T2 = T2(a, b, c); \ 181 | h = g; \ 182 | g = f; \ 183 | f = e; \ 184 | e = ADD(d, T1); \ 185 | d = c; \ 186 | c = b; \ 187 | b = a; \ 188 | a = ADD(T1, T2); \ 189 | } while (0) 190 | 191 | /* 192 | * NAME: sha256->update() 193 | * DESCRIPTION: update SHA-256 digest with a single message block 194 | */ 195 | hash_t sha256_update(const message_t M, const hash_t init) 196 | { 197 | hash_t digest; 198 | # if !defined(UNROLL_SHA256) 199 | int t; 200 | # endif 201 | uint32_t W[16], a, b, c, d, e, f, g, h, T1, T2; 202 | 203 | a = init.words[0]; 204 | b = init.words[1]; 205 | c = init.words[2]; 206 | d = init.words[3]; 207 | e = init.words[4]; 208 | f = init.words[5]; 209 | g = init.words[6]; 210 | h = init.words[7]; 211 | 212 | # ifdef UNROLL_SHA256 213 | W[ 0] = M.words[ 0]; ROUND( 0); 214 | W[ 1] = M.words[ 1]; ROUND( 1); 215 | W[ 2] = M.words[ 2]; ROUND( 2); 216 | W[ 3] = M.words[ 3]; ROUND( 3); 217 | W[ 4] = M.words[ 4]; ROUND( 4); 218 | W[ 5] = M.words[ 5]; ROUND( 5); 219 | W[ 6] = M.words[ 6]; ROUND( 6); 220 | W[ 7] = M.words[ 7]; ROUND( 7); 221 | 222 | W[ 8] = M.words[ 8]; ROUND( 8); 223 | W[ 9] = M.words[ 9]; ROUND( 9); 224 | W[10] = M.words[10]; ROUND(10); 225 | W[11] = M.words[11]; ROUND(11); 226 | W[12] = M.words[12]; ROUND(12); 227 | W[13] = M.words[13]; ROUND(13); 228 | W[14] = M.words[14]; ROUND(14); 229 | W[15] = M.words[15]; ROUND(15); 230 | # else 231 | for (t = 0; t < 16; ++t) { 232 | W[t] = M.words[t]; 233 | ROUND(t); 234 | } 235 | # endif 236 | 237 | # ifdef UNROLL_SHA256 238 | W[16 % 16] = W(16); ROUND(16); 239 | W[17 % 16] = W(17); ROUND(17); 240 | W[18 % 16] = W(18); ROUND(18); 241 | W[19 % 16] = W(19); ROUND(19); 242 | W[20 % 16] = W(20); ROUND(20); 243 | W[21 % 16] = W(21); ROUND(21); 244 | W[22 % 16] = W(22); ROUND(22); 245 | W[23 % 16] = W(23); ROUND(23); 246 | 247 | W[24 % 16] = W(24); ROUND(24); 248 | W[25 % 16] = W(25); ROUND(25); 249 | W[26 % 16] = W(26); ROUND(26); 250 | W[27 % 16] = W(27); ROUND(27); 251 | W[28 % 16] = W(28); ROUND(28); 252 | W[29 % 16] = W(29); ROUND(29); 253 | W[30 % 16] = W(30); ROUND(30); 254 | W[31 % 16] = W(31); ROUND(31); 255 | 256 | W[32 % 16] = W(32); ROUND(32); 257 | W[33 % 16] = W(33); ROUND(33); 258 | W[34 % 16] = W(34); ROUND(34); 259 | W[35 % 16] = W(35); ROUND(35); 260 | W[36 % 16] = W(36); ROUND(36); 261 | W[37 % 16] = W(37); ROUND(37); 262 | W[38 % 16] = W(38); ROUND(38); 263 | W[39 % 16] = W(39); ROUND(39); 264 | 265 | W[40 % 16] = W(40); ROUND(40); 266 | W[41 % 16] = W(41); ROUND(41); 267 | W[42 % 16] = W(42); ROUND(42); 268 | W[43 % 16] = W(43); ROUND(43); 269 | W[44 % 16] = W(44); ROUND(44); 270 | W[45 % 16] = W(45); ROUND(45); 271 | W[46 % 16] = W(46); ROUND(46); 272 | W[47 % 16] = W(47); ROUND(47); 273 | 274 | W[48 % 16] = W(48); ROUND(48); 275 | W[49 % 16] = W(49); ROUND(49); 276 | W[50 % 16] = W(50); ROUND(50); 277 | W[51 % 16] = W(51); ROUND(51); 278 | W[52 % 16] = W(52); ROUND(52); 279 | W[53 % 16] = W(53); ROUND(53); 280 | W[54 % 16] = W(54); ROUND(54); 281 | W[55 % 16] = W(55); ROUND(55); 282 | 283 | W[56 % 16] = W(56); ROUND(56); 284 | W[57 % 16] = W(57); ROUND(57); 285 | W[58 % 16] = W(58); ROUND(58); 286 | W[59 % 16] = W(59); ROUND(59); 287 | W[60 % 16] = W(60); ROUND(60); 288 | W[61 % 16] = W(61); ROUND(61); 289 | W[62 % 16] = W(62); ROUND(62); 290 | W[63 % 16] = W(63); ROUND(63); 291 | # else 292 | for (t = 16; t < 64; ++t) { 293 | W[t % 16] = W(t); 294 | ROUND(t); 295 | } 296 | # endif 297 | 298 | digest.words[0] = ADD(a, init.words[0]); 299 | digest.words[1] = ADD(b, init.words[1]); 300 | digest.words[2] = ADD(c, init.words[2]); 301 | digest.words[3] = ADD(d, init.words[3]); 302 | digest.words[4] = ADD(e, init.words[4]); 303 | digest.words[5] = ADD(f, init.words[5]); 304 | digest.words[6] = ADD(g, init.words[6]); 305 | digest.words[7] = ADD(h, init.words[7]); 306 | 307 | return digest; 308 | } 309 | 310 | # define Ch vec_Ch 311 | # define Maj vec_Maj 312 | # define Sigma0 vec_Sigma0 313 | # define Sigma1 vec_Sigma1 314 | # define sigma0 vec_sigma0 315 | # define sigma1 vec_sigma1 316 | 317 | # undef ADD 318 | # define ADD(a, b) vec_add(a, b) 319 | 320 | # undef SPLAT 321 | # define SPLAT(x) vec_splats(x) 322 | 323 | # define GENB(a, b) vec_subc(a, b) 324 | 325 | static inline 326 | vec_uint4 GENBX(vec_uint4 a, vec_uint4 b, vec_uint4 c) 327 | { 328 | return vec_and(vec_or(vec_cmpgt(a, b), 329 | vec_and(vec_cmpeq(a, b), c)), 330 | vec_splat_u32(1)); 331 | } 332 | 333 | /* 334 | * NAME: sha256->search() 335 | * DESCRIPTION: try to find a nonce which satisfies a target hash 336 | */ 337 | int64_t sha256_search(const message_t M, 338 | const hash_t target, const hash_t midstate, 339 | uint32_t start_nonce, uint32_t range) 340 | { 341 | uint32_t nonce, stop_nonce = start_nonce + range + (4 - (range % 4)) % 4; 342 | uint32_t answer; 343 | # if !defined(UNROLL_SHA256) 344 | int t; 345 | # endif 346 | vec_uint4 W0[3], a0, b0, c0, d0, e0, f0, g0, h0; 347 | vec_uint4 W[16], a, b, c, d, e, f, g, h, T1, T2; 348 | vec_uint4 borrow; 349 | const vec_uchar16 reverse_endian = { 350 | 3, 2, 1, 0, 351 | 7, 6, 5, 4, 352 | 11, 10, 9, 8, 353 | 15, 14, 13, 12 354 | }; 355 | 356 | /* precompute first three rounds */ 357 | 358 | a = SPLAT(midstate.words[0]); 359 | b = SPLAT(midstate.words[1]); 360 | c = SPLAT(midstate.words[2]); 361 | d = SPLAT(midstate.words[3]); 362 | e = SPLAT(midstate.words[4]); 363 | f = SPLAT(midstate.words[5]); 364 | g = SPLAT(midstate.words[6]); 365 | h = SPLAT(midstate.words[7]); 366 | 367 | # ifdef UNROLL_SHA256 368 | W[0] = SPLAT(M.words[0]); ROUND(0); 369 | W[1] = SPLAT(M.words[1]); ROUND(1); 370 | W[2] = SPLAT(M.words[2]); ROUND(2); 371 | # else 372 | for (t = 0; t < 3; ++t) { 373 | W[t] = SPLAT(M.words[t]); 374 | ROUND(t); 375 | } 376 | # endif 377 | 378 | W0[0] = W[0]; 379 | W0[1] = W[1]; 380 | W0[2] = W[2]; 381 | 382 | a0 = a; 383 | b0 = b; 384 | c0 = c; 385 | d0 = d; 386 | e0 = e; 387 | f0 = f; 388 | g0 = g; 389 | h0 = h; 390 | 391 | /* do the search, four at a time */ 392 | 393 | for (nonce = start_nonce; nonce != stop_nonce; nonce += 4) { 394 | W[0] = W0[0]; 395 | W[1] = W0[1]; 396 | W[2] = W0[2]; 397 | 398 | a = a0; 399 | b = b0; 400 | c = c0; 401 | d = d0; 402 | e = e0; 403 | f = f0; 404 | g = g0; 405 | h = h0; 406 | 407 | /* t = 3 */ 408 | W[3] = (vec_uint4) { nonce + 0, nonce + 1, nonce + 2, nonce + 3 }; 409 | ROUND(3); 410 | 411 | # ifdef UNROLL_SHA256 412 | W[ 4] = SPLAT(M.words[ 4]); ROUND( 4); 413 | W[ 5] = SPLAT(M.words[ 5]); ROUND( 5); 414 | W[ 6] = SPLAT(M.words[ 6]); ROUND( 6); 415 | W[ 7] = SPLAT(M.words[ 7]); ROUND( 7); 416 | 417 | W[ 8] = SPLAT(M.words[ 8]); ROUND( 8); 418 | W[ 9] = SPLAT(M.words[ 9]); ROUND( 9); 419 | W[10] = SPLAT(M.words[10]); ROUND(10); 420 | W[11] = SPLAT(M.words[11]); ROUND(11); 421 | W[12] = SPLAT(M.words[12]); ROUND(12); 422 | W[13] = SPLAT(M.words[13]); ROUND(13); 423 | W[14] = SPLAT(M.words[14]); ROUND(14); 424 | W[15] = SPLAT(M.words[15]); ROUND(15); 425 | # else 426 | for (t = 4; t < 16; ++t) { 427 | W[t] = SPLAT(M.words[t]); 428 | ROUND(t); 429 | } 430 | # endif 431 | 432 | # ifdef UNROLL_SHA256 433 | W[16 % 16] = W(16); ROUND(16); 434 | W[17 % 16] = W(17); ROUND(17); 435 | W[18 % 16] = W(18); ROUND(18); 436 | W[19 % 16] = W(19); ROUND(19); 437 | W[20 % 16] = W(20); ROUND(20); 438 | W[21 % 16] = W(21); ROUND(21); 439 | W[22 % 16] = W(22); ROUND(22); 440 | W[23 % 16] = W(23); ROUND(23); 441 | 442 | W[24 % 16] = W(24); ROUND(24); 443 | W[25 % 16] = W(25); ROUND(25); 444 | W[26 % 16] = W(26); ROUND(26); 445 | W[27 % 16] = W(27); ROUND(27); 446 | W[28 % 16] = W(28); ROUND(28); 447 | W[29 % 16] = W(29); ROUND(29); 448 | W[30 % 16] = W(30); ROUND(30); 449 | W[31 % 16] = W(31); ROUND(31); 450 | 451 | W[32 % 16] = W(32); ROUND(32); 452 | W[33 % 16] = W(33); ROUND(33); 453 | W[34 % 16] = W(34); ROUND(34); 454 | W[35 % 16] = W(35); ROUND(35); 455 | W[36 % 16] = W(36); ROUND(36); 456 | W[37 % 16] = W(37); ROUND(37); 457 | W[38 % 16] = W(38); ROUND(38); 458 | W[39 % 16] = W(39); ROUND(39); 459 | 460 | W[40 % 16] = W(40); ROUND(40); 461 | W[41 % 16] = W(41); ROUND(41); 462 | W[42 % 16] = W(42); ROUND(42); 463 | W[43 % 16] = W(43); ROUND(43); 464 | W[44 % 16] = W(44); ROUND(44); 465 | W[45 % 16] = W(45); ROUND(45); 466 | W[46 % 16] = W(46); ROUND(46); 467 | W[47 % 16] = W(47); ROUND(47); 468 | 469 | W[48 % 16] = W(48); ROUND(48); 470 | W[49 % 16] = W(49); ROUND(49); 471 | W[50 % 16] = W(50); ROUND(50); 472 | W[51 % 16] = W(51); ROUND(51); 473 | W[52 % 16] = W(52); ROUND(52); 474 | W[53 % 16] = W(53); ROUND(53); 475 | W[54 % 16] = W(54); ROUND(54); 476 | W[55 % 16] = W(55); ROUND(55); 477 | 478 | W[56 % 16] = W(56); ROUND(56); 479 | W[57 % 16] = W(57); ROUND(57); 480 | W[58 % 16] = W(58); ROUND(58); 481 | W[59 % 16] = W(59); ROUND(59); 482 | W[60 % 16] = W(60); ROUND(60); 483 | W[61 % 16] = W(61); ROUND(61); 484 | W[62 % 16] = W(62); ROUND(62); 485 | W[63 % 16] = W(63); ROUND(63); 486 | # else 487 | for (t = 16; t < 64; ++t) { 488 | W[t % 16] = W(t); 489 | ROUND(t); 490 | } 491 | # endif 492 | 493 | W[0] = ADD(a, SPLAT(midstate.words[0])); 494 | W[1] = ADD(b, SPLAT(midstate.words[1])); 495 | W[2] = ADD(c, SPLAT(midstate.words[2])); 496 | W[3] = ADD(d, SPLAT(midstate.words[3])); 497 | W[4] = ADD(e, SPLAT(midstate.words[4])); 498 | W[5] = ADD(f, SPLAT(midstate.words[5])); 499 | W[6] = ADD(g, SPLAT(midstate.words[6])); 500 | W[7] = ADD(h, SPLAT(midstate.words[7])); 501 | 502 | /* first SHA-256 complete */ 503 | 504 | a = SPLAT(H0.words[0]); 505 | b = SPLAT(H0.words[1]); 506 | c = SPLAT(H0.words[2]); 507 | d = SPLAT(H0.words[3]); 508 | e = SPLAT(H0.words[4]); 509 | f = SPLAT(H0.words[5]); 510 | g = SPLAT(H0.words[6]); 511 | h = SPLAT(H0.words[7]); 512 | 513 | ROUND(0); 514 | ROUND(1); 515 | ROUND(2); 516 | ROUND(3); 517 | ROUND(4); 518 | ROUND(5); 519 | ROUND(6); 520 | ROUND(7); 521 | 522 | W[ 8] = SPLAT(0x80000000U); ROUND( 8); 523 | 524 | # ifdef UNROLL_SHA256 525 | W[ 9] = SPLAT(0x00000000U); ROUND( 9); 526 | W[10] = SPLAT(0x00000000U); ROUND(10); 527 | W[11] = SPLAT(0x00000000U); ROUND(11); 528 | W[12] = SPLAT(0x00000000U); ROUND(12); 529 | W[13] = SPLAT(0x00000000U); ROUND(13); 530 | W[14] = SPLAT(0x00000000U); ROUND(14); 531 | # else 532 | for (t = 9; t < 15; ++t) { 533 | W[t] = SPLAT(0U); 534 | ROUND(t); 535 | } 536 | # endif 537 | 538 | W[15] = SPLAT(0x00000100U); ROUND(15); 539 | 540 | # ifdef UNROLL_SHA256 541 | W[16 % 16] = W(16); ROUND(16); 542 | W[17 % 16] = W(17); ROUND(17); 543 | W[18 % 16] = W(18); ROUND(18); 544 | W[19 % 16] = W(19); ROUND(19); 545 | W[20 % 16] = W(20); ROUND(20); 546 | W[21 % 16] = W(21); ROUND(21); 547 | W[22 % 16] = W(22); ROUND(22); 548 | W[23 % 16] = W(23); ROUND(23); 549 | 550 | W[24 % 16] = W(24); ROUND(24); 551 | W[25 % 16] = W(25); ROUND(25); 552 | W[26 % 16] = W(26); ROUND(26); 553 | W[27 % 16] = W(27); ROUND(27); 554 | W[28 % 16] = W(28); ROUND(28); 555 | W[29 % 16] = W(29); ROUND(29); 556 | W[30 % 16] = W(30); ROUND(30); 557 | W[31 % 16] = W(31); ROUND(31); 558 | 559 | W[32 % 16] = W(32); ROUND(32); 560 | W[33 % 16] = W(33); ROUND(33); 561 | W[34 % 16] = W(34); ROUND(34); 562 | W[35 % 16] = W(35); ROUND(35); 563 | W[36 % 16] = W(36); ROUND(36); 564 | W[37 % 16] = W(37); ROUND(37); 565 | W[38 % 16] = W(38); ROUND(38); 566 | W[39 % 16] = W(39); ROUND(39); 567 | 568 | W[40 % 16] = W(40); ROUND(40); 569 | W[41 % 16] = W(41); ROUND(41); 570 | W[42 % 16] = W(42); ROUND(42); 571 | W[43 % 16] = W(43); ROUND(43); 572 | W[44 % 16] = W(44); ROUND(44); 573 | W[45 % 16] = W(45); ROUND(45); 574 | W[46 % 16] = W(46); ROUND(46); 575 | W[47 % 16] = W(47); ROUND(47); 576 | 577 | W[48 % 16] = W(48); ROUND(48); 578 | W[49 % 16] = W(49); ROUND(49); 579 | W[50 % 16] = W(50); ROUND(50); 580 | W[51 % 16] = W(51); ROUND(51); 581 | W[52 % 16] = W(52); ROUND(52); 582 | W[53 % 16] = W(53); ROUND(53); 583 | W[54 % 16] = W(54); ROUND(54); 584 | W[55 % 16] = W(55); ROUND(55); 585 | 586 | W[56 % 16] = W(56); ROUND(56); 587 | W[57 % 16] = W(57); ROUND(57); 588 | W[58 % 16] = W(58); ROUND(58); 589 | W[59 % 16] = W(59); ROUND(59); 590 | /* t = 60..63 delayed */ 591 | # else 592 | for (t = 16; t < 60; ++t) { 593 | W[t % 16] = W(t); 594 | ROUND(t); 595 | } 596 | # endif 597 | 598 | W[60 % 16] = W(60); 599 | T1 = T1(60, e, f, g, h); 600 | 601 | T2 = ADD(ADD(d, T1), SPLAT(H0.words[7])); 602 | 603 | /* quick check to see if any element of the last word vector is zero */ 604 | if (likely(!vec_any_eq(T2, vec_splat_u32(0)))) 605 | continue; 606 | 607 | /* we have something interesting; finish the SHA-256 */ 608 | 609 | ROUND(60); 610 | 611 | # ifdef UNROLL_SHA256 612 | W[61 % 16] = W(61); ROUND(61); 613 | W[62 % 16] = W(62); ROUND(62); 614 | W[63 % 16] = W(63); ROUND(63); 615 | # else 616 | for (t = 61; t < 64; ++t) { 617 | W[t % 16] = W(t); 618 | ROUND(t); 619 | } 620 | # endif 621 | 622 | a = ADD(a, SPLAT(H0.words[0])); 623 | b = ADD(b, SPLAT(H0.words[1])); 624 | c = ADD(c, SPLAT(H0.words[2])); 625 | d = ADD(d, SPLAT(H0.words[3])); 626 | e = ADD(e, SPLAT(H0.words[4])); 627 | f = ADD(f, SPLAT(H0.words[5])); 628 | g = ADD(g, SPLAT(H0.words[6])); 629 | h = ADD(h, SPLAT(H0.words[7])); 630 | 631 | /* now do the full (reversed-endian) subtraction */ 632 | 633 | borrow = GENB(SPLAT(target.words[7]), 634 | vec_perm(a, a, reverse_endian)); 635 | borrow = GENBX(SPLAT(target.words[6]), 636 | vec_perm(b, b, reverse_endian), borrow); 637 | borrow = GENBX(SPLAT(target.words[5]), 638 | vec_perm(c, c, reverse_endian), borrow); 639 | borrow = GENBX(SPLAT(target.words[4]), 640 | vec_perm(d, d, reverse_endian), borrow); 641 | borrow = GENBX(SPLAT(target.words[3]), 642 | vec_perm(e, e, reverse_endian), borrow); 643 | borrow = GENBX(SPLAT(target.words[2]), 644 | vec_perm(f, f, reverse_endian), borrow); 645 | borrow = GENBX(SPLAT(target.words[1]), 646 | vec_perm(g, g, reverse_endian), borrow); 647 | borrow = GENBX(SPLAT(target.words[0]), 648 | vec_perm(h, h, reverse_endian), borrow); 649 | 650 | if (likely(vec_all_eq(borrow, vec_splat_u32(0)))) 651 | continue; 652 | 653 | /* we have a winner */ 654 | 655 | if (vec_extract(borrow, 0)) 656 | answer = nonce + 0; 657 | else if (vec_extract(borrow, 1)) 658 | answer = nonce + 1; 659 | else if (vec_extract(borrow, 2)) 660 | answer = nonce + 2; 661 | else if (vec_extract(borrow, 3)) 662 | answer = nonce + 3; 663 | else 664 | continue; 665 | 666 | if (answer - start_nonce < range) 667 | return answer; 668 | } 669 | 670 | return -1; 671 | } 672 | --------------------------------------------------------------------------------