def sign(self,tx_num_str,keys): if self.marked_signed(): die(1,'Transaction is already signed!') self.die_if_incorrect_chain() if (self.has_segwit_inputs() or self.has_segwit_outputs()) and not g.proto.cap('segwit'): die(2,yellow("TX has Segwit inputs or outputs, but {} doesn't support Segwit!".format(g.coin))) qmsg('Passing {} key{} to {}'.format(len(keys),suf(keys,'s'),g.proto.daemon_name)) if self.has_segwit_inputs(): from mmgen.addr import KeyGenerator,AddrGenerator kg = KeyGenerator('std') ag = AddrGenerator('segwit') keydict = MMGenDict([(d.addr,d.sec) for d in keys]) sig_data = [] for d in self.inputs: e = dict([(k,getattr(d,k)) for k in ('txid','vout','scriptPubKey','amt')]) e['amount'] = e['amt'] del e['amt'] if d.mmid and d.mmid.mmtype == 'S': e['redeemScript'] = ag.to_segwit_redeem_script(kg.to_pubhex(keydict[d.addr])) sig_data.append(e) msg_r('Signing transaction{}...'.format(tx_num_str)) wifs = [d.sec.wif for d in keys] ret = g.rpch.signrawtransaction(self.hex,sig_data,wifs,g.proto.sighash_type,on_fail='return') from mmgen.rpc import rpc_error,rpc_errmsg if rpc_error(ret): errmsg = rpc_errmsg(ret) if 'Invalid sighash param' in errmsg: m = 'This is not the BCH chain.' m += "\nRe-run the script without the --coin=bch option." else: m = errmsg msg(yellow(m)) return False else: if ret['complete']: # Msg(pretty_hexdump(unhexlify(self.hex),cols=16)) # DEBUG # pmsg(make_chksum_6(unhexlify(self.hex)).upper()) self.hex = ret['hex'] self.compare_size_and_estimated_size() dt = DeserializedTX(self.hex) self.check_hex_tx_matches_mmgen_tx(dt) self.coin_txid = CoinTxID(dt['txid'],on_fail='return') self.check_sigs(dt) assert self.coin_txid == g.rpch.decoderawtransaction(self.hex)['txid'],( 'txid mismatch (after signing)') msg('OK') return True else: msg('failed\n{} returned the following errors:'.format(g.proto.daemon_name.capitalize())) msg(repr(ret['errors'])) return False
def sign(self, c, tx_num_str, keys): self.die_if_incorrect_chain() if g.coin == 'BCH' and (self.has_segwit_inputs() or self.has_segwit_outputs()): die( 2, yellow( "Segwit inputs cannot be spent or spent to on the BCH chain!" )) qmsg('Passing {} key{} to bitcoind'.format(len(keys), suf(keys, 's'))) if self.has_segwit_inputs(): from mmgen.addr import KeyGenerator, AddrGenerator kg = KeyGenerator() ag = AddrGenerator('segwit') keydict = MMGenDict([(d.addr, d.sec) for d in keys]) sig_data = [] for d in self.inputs: e = dict([(k, getattr(d, k)) for k in ('txid', 'vout', 'scriptPubKey', 'amt')]) e['amount'] = e['amt'] del e['amt'] if d.mmid and d.mmid.mmtype == 'S': e['redeemScript'] = ag.to_segwit_redeem_script( kg.to_pubhex(keydict[d.addr])) sig_data.append(e) msg_r('Signing transaction{}...'.format(tx_num_str)) ht = ('ALL', 'ALL|FORKID')[g.coin == 'BCH'] # sighashtype defaults to 'ALL' wifs = [d.sec.wif for d in keys] # keys.pmsg() # pmsg(wifs) ret = c.signrawtransaction(self.hex, sig_data, wifs, ht, on_fail='return') from mmgen.rpc import rpc_error, rpc_errmsg if rpc_error(ret): errmsg = rpc_errmsg(ret) if 'Invalid sighash param' in errmsg: m = 'This is not the BCH chain.' m += "\nRe-run the script without the --aug1hf or --coin=bch option." else: m = errmsg msg(yellow(m)) return False else: if ret['complete']: self.hex = ret['hex'] vmsg('Signed transaction size: {}'.format(len(self.hex) / 2)) dt = DeserializedTX(self.hex) txid = dt['txid'] self.check_sigs(dt) assert txid == c.decoderawtransaction( self.hex)['txid'], 'txid mismatch (after signing)' self.btc_txid = BitcoinTxID(txid, on_fail='return') msg('OK') return True else: msg('failed\nBitcoind returned the following errors:') msg(repr(ret['errors'])) return False
ag = AddrGenerator(('p2pkh', 'segwit')[bool(opt.segwit)]) if a and b: m = "Comparing address generators '{}' and '{}'" qmsg(green(m.format(g.key_generators[a - 1], g.key_generators[b - 1]))) last_t = time.time() kg_a = KeyGenerator(a) kg_b = KeyGenerator(b) for i in range(rounds): if time.time() - last_t >= 0.1: qmsg_r('\rRound %s/%s ' % (i + 1, rounds)) last_t = time.time() sec = PrivKey(os.urandom(32), compressed) a_addr = ag.to_addr(kg_a.to_pubhex(sec)) b_addr = ag.to_addr(kg_b.to_pubhex(sec)) vmsg('\nkey: %s\naddr: %s\n' % (sec.wif, a_addr)) if a_addr != b_addr: match_error(sec, sec.wif, a_addr, b_addr, a, b) if not opt.segwit: compressed = not compressed qmsg_r('\rRound %s/%s ' % (i + 1, rounds)) qmsg(green(('\n', '')[bool(opt.verbose)] + 'OK')) elif a and not fh: m = "Testing speed of address generator '{}'" qmsg(green(m.format(g.key_generators[a - 1]))) from struct import pack, unpack seed = os.urandom(28) print 'Incrementing key with each round'