#!/usr/bin/env python import codecs from bitcoin.rpc import Proxy if __name__ == '__main__': url = raw_input('Please enter the RPC url: ') username = raw_input('Please enter the RPC username: '******'Please enter the RPC password: '******'out.csv', 'w', 'utf-8') for idx in xrange(numblocks): blockinfo = proxy.getblock(proxy.getblockhash(idx)) fp.write(','.join( map(str, [ blockinfo['height'], blockinfo['time'], blockinfo['difficulty'], ])) + '\n') fp.close()
def _sync_block(self): p = Proxy() blockcount = p.getblockcount() print("sync blockcount = " + str(blockcount)) with closing(sqlite3.connect(self.dbname)) as connection: cursor = connection.cursor() checkedcount = self._get_checked_count(cursor) print("sync checkedcount = " + str(checkedcount)) if checkedcount < CHECKPOINT: checkedcount = CHECKPOINT lastblock = blockcount - CONFIRMATIONS if lastblock <= 0: return for i in range(checkedcount + 1, blockcount - CONFIRMATIONS): if self.stopped: break print("sync blockheight = " + str(i)) block = p.getblockbynumber(i) if block is None: continue if BLOCK_KEY_TX not in block.keys(): continue for transactionid in block[BLOCK_KEY_TX]: transaction = p.gettransaction(transactionid) if transaction is None: continue if TRANSACTION_KEY_AMOUNT not in transaction.keys(): continue amount = transaction[TRANSACTION_KEY_AMOUNT] if amount <= 0: print("sync amount div") continue amount = CWalletSyncher._str_round_down8(amount) print("sync amount = " + amount) if TRANSACTION_KEY_DETAILS not in transaction.keys(): print("sync dont have details!!") continue print("sync found receive!!") details = transaction[TRANSACTION_KEY_DETAILS] for detail in details: category = detail[TRANSACTION_KEY_CATEGORY] if (category != TRANSACTION_VALUE_CATEGORY_RECEIVE): continue address = detail[TRANSACTION_KEY_ADDRESS] print("sync receive address = " + address) with self.dblock: row = self.dbaccessor.get_user_by_address( cursor, address) if row is not None: height = row[ walletdb.WalletNum.LASTSYNCBLOCK.value] print("sync receive username = "******" balance = " + row[walletdb.WalletNum.BALANCE.value] + " height = " + str(row[walletdb.WalletNum.LASTSYNCBLOCK. value])) src_balance = CWalletSyncher._round_down8( str(row[walletdb.WalletNum.BALANCE.value])) dst_balance = src_balance + \ CWalletSyncher._round_down8(amount) if dst_balance < CWalletSyncher._round_down8( "0.0"): dst_balance = CWalletSyncher._round_down8( "0.0") print("sync update balance = " + str(dst_balance) + " amount = " + amount) if not self.dbaccessor.update_balance_with_blockheight( cursor, row[walletdb.WalletNum.ID.value], dst_balance, i): print("sync update faild.") return self.logger.debug( "username="******" before=" + CWalletSyncher._str_round_down8( src_balance) + " after=" + CWalletSyncher._str_round_down8( dst_balance) + " height=" + str(i)) break pass self._update_checked_count(cursor, i) connection.commit()
class TX(object): def __init__(self, logger=None, test=False): self.logger = logger or logging.getLogger(__name__) # Setup logging file handler self.logger.setLevel(logging.DEBUG) self.handler = logging.FileHandler(__name__ + '.log') self.handler.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(name)s - ' + '%(levelname)s:\n\t %(message)s') self.handler.setFormatter(formatter) self.logger.addHandler(self.handler) self.test = test # if test: # SelectParams('testnet') if not test: self.proxy = Proxy() def __del__(self): self.handler.close() ########################################################################### ## General TX Functions ########################################################################### def get_tx(self, redeem_script, address, amount, funding_tx, lock_time=0, vout=0): ''' Returns a raw transaction and it's signature hash that pays to address from funding_tx Options: vout -> which vout of funding_tx nLockTime -> set's transaction locktime ''' # Set P2SH funding tx in little-endian fx = lx(funding_tx) if lock_time > 0: nlock_time = lock_time else: nlock_time = 0 # nSequence must be any number less than 0xffffffff to enable nLockTime if (nlock_time != 0): txin = CMutableTxIn(COutPoint(fx, vout), nSequence=0) else: txin = CMutableTxIn(COutPoint(fx, vout)) # Convert amount to Satoshi's amount *= COIN # Create the txout to address script_pubkey = CBitcoinAddress(address).to_scriptPubKey() txout = CMutableTxOut(amount, script_pubkey) # Create the unsigned transaction. tx = CMutableTransaction([txin], [txout], nLockTime=nlock_time) # Calculte TX sig hash sighash = SignatureHash(CScript(redeem_script), tx, 0, SIGHASH_ALL) self.logger.info("get_tx: TX SIGHASH is %s", b2x(sighash)) return (tx.serialize(), sighash) def refund_tx(self, payer_sig, serial_tx, redeem_script): ''' Sends a transaction refunding the funder of the P2SH address. ''' # Read in transaction temp_tx = CTransaction.deserialize(serial_tx) tx = CMutableTransaction.from_tx(temp_tx) txin = tx.vin[0] # Set script sig txin.scriptSig = CScript([payer_sig + '\x01', OP_FALSE, redeem_script]) # Verify script redeem_script = CScript(redeem_script) VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx, 0, [SCRIPT_VERIFY_P2SH]) serial_tx = tx.serialize() if not self.test: # txid = self.self.proxy.sendrawtransaction(tx) txid = b2lx(Hash(serial_tx)) else: txid = b2lx(Hash(serial_tx)) self.logger.info("refund_tx: TXID is %s", txid) self.logger.info("refund_tx: RAW TX is %s", b2x(serial_tx)) return serial_tx ########################################################################### ## Serialization related ########################################################################### def serialize_list(self, l): ''' Serializes a python list ''' serial = "" for i in range(len(l)): serial += l[i] return serial def get_keys_from_tx(self, serial_tx, n_keys=15): '''Extracts n_keys from tx in serial form''' # Read in transaction temp_tx = CTransaction.deserialize(serial_tx) tx = CMutableTransaction.from_tx(temp_tx) # Keys are in txin.scriptSig txin = tx.vin[0] script = txin.scriptSig # Extract keys from script keys = [] for i, op in enumerate(script): if i in range(1, n_keys + 1): keys += [op] # Serialize keys in correct order serial_keys = "" for op in reversed(keys): serial_keys += op return serial_keys def get_keys_from_serial(self, serial, n_keys=15, key_len=16): ''' Returns a list of n_keys of key_len extracted from serial''' expected = (n_keys * key_len) if len(serial) != expected: self.logger.error( "get_keys_from_serial: serial len is %d " + "expected %d", len(serial), expected) return [] keys = [] for i in range(n_keys): keys += [serial[i * key_len:key_len * (i + 1)]] return keys def get_hashes_from_serial(self, serial, n_hashes, hash_len): ''' Returns a list of n_hashes of hash_len extracted from serial''' expected = (n_hashes * hash_len) if len(serial) != expected: self.logger.error( "get_hashes_from_serial: serial len is %d " + "expected %d", len(serial), expected) return [] hashes = [] for i in range(n_hashes): hashes += [serial[i * hash_len:hash_len * (i + 1)]] return hashes ########################################################################### ## Preimage P2SH wth Refund ########################################################################### def create_hash_script(self, redeemer_pubkey, hashes): ''' Creates part of the redeem script that deals with the hashes ''' script = [] for h in hashes: script += [OP_RIPEMD160, h, OP_EQUALVERIFY] script += [redeemer_pubkey, OP_CHECKSIG] return script def setup_preimage(self, payer_pubkey, redeemer_pubkey, hashes, amount, lock_time): ''' Setups a P2SH that can only be redeemed if the redeemer is able to provide the hash preimages. Also, sends a tx funding the escrow (Assumes payer calls the setup) ''' # Set locktime relative to current block if not self.test: lock = self.proxy.getblockcount() + lock_time else: lock = lock_time script = self.create_hash_script(redeemer_pubkey, hashes) redeem_script = CScript([OP_IF] + script + [ OP_ELSE, lock, OP_CHECKLOCKTIMEVERIFY, OP_DROP, payer_pubkey, OP_CHECKSIG, OP_ENDIF ]) redeem = b2x(redeem_script) self.logger.info("setup_preimage: Redeem script is %s", redeem) # Get P2SH address # 1. Get public key script_pub_key = redeem_script.to_p2sh_scriptPubKey() # 2. Get bitcoin address p2sh_address = CBitcoinAddress.from_scriptPubKey(script_pub_key) self.logger.info("setup_preimage: P2SH is %s", str(p2sh_address)) # 3. Fund address if not self.test: # funding_tx = self.proxy.call("sendtoaddress", str(p2sh_address), # amount) funding_tx = FUNDING_TX self.logger.info("setup_preimage: P2SH Fund TX is %s", funding_tx) else: funding_tx = FUNDING_TX return (redeem_script, str(funding_tx), str(p2sh_address), str(lock)) def spend_preimage(self, preimages, redeemer_sig, serial_tx, redeem_script): ''' Sends a transaction fulfilling the redeem script of the preimage P2SH ''' # Read in transaction temp_tx = CTransaction.deserialize(serial_tx) tx = CMutableTransaction.from_tx(temp_tx) txin = tx.vin[0] # Setup preimages in reverse order script = [] for p in reversed(preimages): script += [p] # Create script sig txin.scriptSig = CScript([redeemer_sig + '\x01'] + script + [OP_TRUE, redeem_script]) # Verify script redeem_script = CScript(redeem_script) VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx, 0, [SCRIPT_VERIFY_P2SH]) serial_tx = tx.serialize() if not self.test: # txid = self.proxy.sendrawtransaction(tx) txid = b2lx(Hash(serial_tx)) else: txid = b2lx(Hash(serial_tx)) self.logger.info("spend_preimage: TXID is %s", txid) self.logger.info("spend_preimage: RAW TX is %s", b2x(serial_tx)) return serial_tx ########################################################################### ## Two Party Escrow with Refund ########################################################################### def setup_escrow(self, payer_pubkey, redeemer_pubkey, amount, lock_time): ''' Setups a 2of2 escrow with payer and redeemer Also, sends a tx funding the escrow (Assumes payer calls the setup) ''' # Set locktime relative to current block if not self.test: lock = self.proxy.getblockcount() + lock_time self.logger.info("setup_escrow: Locktime is %d", lock) else: lock = lock_time redeem_script = CScript([ OP_IF, OP_2, payer_pubkey, redeemer_pubkey, OP_2, OP_CHECKMULTISIG, OP_ELSE, lock, OP_CHECKLOCKTIMEVERIFY, OP_DROP, payer_pubkey, OP_CHECKSIG, OP_ENDIF ]) redeem = b2x(redeem_script) self.logger.info("setup_escrow: Redeem script is %s", redeem) # Get P2SH address # 1. Get public key script_pub_key = redeem_script.to_p2sh_scriptPubKey() # 2. Get bitcoin address p2sh_address = CBitcoinAddress.from_scriptPubKey(script_pub_key) self.logger.info("setup_escrow: P2SH is %s", str(p2sh_address)) # 3. Fund address if not self.test: funding_tx = self.proxy.call("sendtoaddress", str(p2sh_address), amount) self.logger.info("setup_escrow: P2SH Fund TX is %s", funding_tx) else: funding_tx = FUNDING_TX return (redeem_script, str(funding_tx), str(p2sh_address), str(lock)) def spend_escrow(self, payer_sig, redeemer_sig, serial_tx, redeem_script): ''' Sends a transaction fulfilling the redeem script of escrow tx ''' # Read in transaction temp_tx = CTransaction.deserialize(serial_tx) tx = CMutableTransaction.from_tx(temp_tx) txin = tx.vin[0] # Set script sig txin.scriptSig = CScript([ OP_FALSE, payer_sig + '\x01', redeemer_sig + '\x01', OP_TRUE, redeem_script ]) # Verify script redeem_script = CScript(redeem_script) serial_tx = tx.serialize() VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx, 0, [SCRIPT_VERIFY_P2SH]) serial_tx = tx.serialize() if not self.test: # txid = self.proxy.sendrawtransaction(tx) txid = b2lx(Hash(serial_tx)) else: txid = b2lx(Hash(serial_tx)) self.logger.info("spend_escrow: TXID is %s", txid) self.logger.info("spend_escrow: RAW TX is %s", b2x(serial_tx)) return serial_tx
#!/usr/bin/env python import codecs from bitcoin.rpc import Proxy if __name__ == '__main__': url = raw_input('Please enter the RPC url: ') username = raw_input('Please enter the RPC username: '******'Please enter the RPC password: '******'out.csv', 'w', 'utf-8') for idx in xrange(numblocks): blockinfo = proxy.getblock(proxy.getblockhash(idx)) fp.write(','.join(map(str, [ blockinfo['height'], blockinfo['time'], blockinfo['difficulty'], ]))+'\n') fp.close()
# else: # # print("unknown") # self.unknowns.append([txid, b2x(spk)]) self.type = type self.found |= self.type.value if self.printed & self.type.value: pass elif self.type.value: self.process(g1, g2, g3, k) else: #unknown type self.process('', '', '', k) if __name__ == "__main__": make_addresses() latest = proxy.getblockcount() i = -1 txn = Transaction() while True: i += 1 j = -1 if txn.found == 255: break bhash = proxy.getblockhash(latest - i) block = proxy.getblock(bhash) bhash = b2lx(bhash) for tx in block.vtx: j += 1 if txn.found == 255: break txid = b2lx(tx.GetTxid()) txn.gettxn(txid)
class Blockchain: def __init__(self): self.proxy = Proxy('http://*****:*****@blockchain.infnote.com:8962') @staticmethod def deserialize_transaction(raw_tx): return CTransaction.deserialize(unhexlify(raw_tx.encode('utf8'))) def decode_transaction(self, tx): contents = [] for out in tx.vout: if out.nValue > 0: continue data = self.get_data_from_vout(out) if data: contents.append(data) return contents def send_transaction(self, raw_tx): transaction = self.deserialize_transaction(raw_tx) txid = self.proxy.sendrawtransaction(transaction) return txid @staticmethod def get_data_from_vout(vout): i = iter(vout.scriptPubKey) flag = next(i) # TODO: 需要区分类型,以填充至不同的模型 if flag == script.OP_RETURN or flag == script.OP_NOP8: data = next(i).decode('utf8') return json.loads(data) return None def get_transaction(self, txid): return self.proxy.getrawtransaction(txid) def get_block_count(self): return self.proxy.getblockcount() def get_block_by_height(self, height: int): return self.proxy.getblock(self.proxy.getblockhash(height)) def server_unspent(self): return self.proxy.listunspent() @staticmethod def freeze_coins_in_tx(tx: CTransaction): for vin in tx.vin: coin = Coin.objects.get(txid=b2lx(vin.prevout.hash), vout=vin.prevout.n) coin.frozen = True coin.save() def send_coin_to(self, address, coin: Coin): txin = CMutableTxIn(COutPoint(lx(coin.txid), coin.vout)) txout = CMutableTxOut(coin.value - 1e5, CBitcoinAddress(address).to_scriptPubKey()) tx = CMutableTransaction([txin], [txout]) tx = self.proxy.signrawtransaction(tx)['tx'] # sig_hash = SignatureHash(txin_script_pubkey, tx, 0, SIGHASH_ALL) # sig = seckey.sign(sig_hash) + bytes([SIGHASH_ALL]) # txin.scriptSig = CScript([sig, seckey.pub]) # VerifyScript(txin.scriptSig, txin_script_pubkey, tx, 0, (SCRIPT_VERIFY_P2SH,)) # print(b2x(tx.serialize())) self.proxy.sendrawtransaction(tx) coin.frozen = True coin.save()