예제 #1
0
 def __init__(self):
     super(Wallet, self).__init__()
     self.current_height = 0
     self.isrunning = True
     self.isclosed = False
     self.indexeddb = IndexedDBWallet()
     self.node = RemoteNode(url='http://10.84.136.112:20332')
예제 #2
0
 def get_last_height(net):
     assert net in ['testnet', 'mainnet'], 'Wrong Net'
     netPortDit = {'testnet': '20332', 'mainnet': '10332'}
     seeds = ['seed' + '%s' % i for i in range(1, 6)]
     heights = []
     for seed in seeds:
         rn = RemoteNode('http://' + seed + '.neo.org:' + netPortDit[net])
         try:
             height = rn.getBlockCount()
         except:
             height = 0
         heights.append(height)
     print 'heights:%s' % heights
     return max(heights)
예제 #3
0
 def send_transaction_to_node(cls, regtx, tran, net, node=RPC_NODE):
     try:
         url = 'http://' + node + (':20332'
                                   if 'testnet' == net else ':10332')
         RN = RemoteNode(url)
         r = RN.sendRawTransaction(regtx)
         if r.has_key('error') and r['error']:
             #print '-'*5,'raw:',regtx
             return False, r['error']['message'] + 'regtx:%s' % regtx
         if r['result']:
             txid = cls.compute_txid(tran)
             #print '-'*5,'txid:',txid
             return True, txid
         else:
             #print '-'*5,'raw:',regtx
             return False, 'broadcast falure'
     except Exception as e:
         #print '*'*5,'Exception','*'*5,e
         return False, 'Exception:%s' % e
예제 #4
0
def pay(payer_id, payees, asset):
    wallet_db = IndexedDBWallet()
    # step 1: get payer account
    payer = wallet_db.queryAccount(work_id=payer_id)
    if payer == None:
        print '%s : not exist payer block chain account' % payer_id
        return 2

    payer_acc = Account(payer['pri_key'])
    contract = Contract()
    contract.createSignatureContract(payer_acc.publicKey)

    # step 2: load payer available coins
    coins = wallet_db.loadCoins(address=payer['address'], asset=asset)

    # step 3: select coins
    wallet = Wallet()
    selected_coins = wallet.selectCoins(coins, payees)
    if len(selected_coins) == 0:
        print 'no enough coins'
        return 5
    change = sum([int(c.value) for c in selected_coins]) - sum(
        [int(p['amount']) for p in payees])

    # step 4: construct outputs
    outputs = []
    payee_accs = {}
    for p in payees:
        payee = wallet_db.queryAccount(work_id=p['work_id'])
        if payee == None:
            print '%s : not exist payee block chain account' % payer_id
            return 3
        acc = Account(payee['pri_key'])
        output = TransactionOutput(AssetId=asset,
                                   Value=p['amount'],
                                   ScriptHash=acc.scriptHash)
        outputs.append(output)
        payee_accs[acc.scriptHash] = acc

    # add change output
    if change > 0:
        outputs.append(
            TransactionOutput(AssetId=asset,
                              Value=change,
                              ScriptHash=payer_acc.scriptHash))
        payee_accs[payer_acc.scriptHash] = payer_acc

    # step 5: construct inputs
    inputs = [
        TransactionInput(prevHash=c.txid, prevIndex=c.idx)
        for c in selected_coins
    ]

    # step 6: make transaction
    tx = Transaction(inputs, outputs)
    stream = MemoryStream()
    writer = BinaryWriter(stream)
    tx.serializeUnsigned(writer)
    reg_tx = stream.toArray()
    txid = tx.ensureHash()
    print 'TX ->', repr(reg_tx)
    print 'TXID ->', txid

    # step 7: Signature
    Redeem_script = contract.redeemScript
    sk = SigningKey.from_string(binascii.unhexlify(payer_acc.privateKey),
                                curve=NIST256p,
                                hashfunc=hashlib.sha256)
    signature = binascii.hexlify(
        sk.sign(binascii.unhexlify(reg_tx), hashfunc=hashlib.sha256))
    regtx = reg_tx + '014140' + signature + '23' + Redeem_script

    # step 8: sendRawTransaction
    node = RemoteNode(url='http://10.84.136.112:20332')
    response = node.sendRawTransaction(regtx)

    # step 9: update coin status
    if response['result'] == True:
        incoming = []
        for i in range(len(outputs)):
            coin = Coin(txid=txid,
                        idx=i,
                        value=outputs[i].Value,
                        asset=asset,
                        address=payee_accs[outputs[i].ScriptHash].address,
                        status=CoinState.Unconfirmed)
            incoming.append(coin)
        wallet_db.onSendTransaction(spending=selected_coins, incoming=incoming)
        return 0
    else:
        return 6
예제 #5
0
    try:
        result = DB.blocks.insert_one({'_id':num},mongo_block)
        print '->', num, 'at %f seconds' % (time.time() - start_time)
    except DuplicateKeyError:
        print 'duplicate block %s' % num

def sync():
    while True:
        current_height = RN.getBlockCount()
        print 'current_height',current_height
        blocks_num = DB.blocks.count()
        if blocks_num <= current_height:
            for i in xrange(blocks_num, current_height+1):
                sync_block(i)


if __name__ == "__main__":
    try:
        parser = argparse.ArgumentParser()
        parser.add_argument("-d", "--db", default='antshares', help="verify database name, default antshares")
        parser.add_argument("-n", "--node", default='http://127.0.0.1:20332', help="remote node to sync blockchain data,default http://127.0.0.1:20332")
        parser.add_argument("-m", "--mongodb", default='127.0.0.1:27017', help="mongodb for store data,default 127.0.0.1:27017")
        args = parser.parse_args()
        RN = RemoteNode(args.node)
        MC = MongoClient('mongodb://' + args.mongodb + '/')
        DB = MC[args.db]
        sync()
    except Exception as e:
        print e
        sys.exit()
예제 #6
0
def pay(payer_id, payees, asset):
    wallet_db = IndexedDBWallet()
    # step 1: get payer account
    payer = wallet_db.queryAccount(work_id=payer_id)
    if payer == None:
        print '%s : not exist payer block chain account' % payer_id
        return 2

    payer_acc = Account(payer['pri_key'])
    contract = Contract()
    contract.createSignatureContract(payer_acc.publicKey)

    # step 2: load payer available coins
    coins = wallet_db.loadCoins(address=payer['address'],asset=asset)

    # step 3: select coins
    wallet = Wallet()
    selected_coins = wallet.selectCoins(coins, payees)
    if len(selected_coins) == 0:
        print 'no enough coins'
        return 5
    change = sum([int(c.value) for c in selected_coins]) - sum([int(p['amount']) for p in payees])

    # step 4: construct outputs
    outputs = []
    payee_accs = {}
    for p in payees:
        payee = wallet_db.queryAccount(work_id=p['work_id'])
        if payee == None:
            print '%s : not exist payee block chain account' % payer_id
            return 3
        acc = Account(payee['pri_key'])
        output = TransactionOutput(AssetId=asset, Value=p['amount'], ScriptHash=acc.scriptHash)
        outputs.append(output)
        payee_accs[acc.scriptHash] = acc

    # add change output
    if change > 0:
        outputs.append(TransactionOutput(AssetId=asset,Value=change,ScriptHash=payer_acc.scriptHash))
        payee_accs[payer_acc.scriptHash] = payer_acc

    # step 5: construct inputs
    inputs = [TransactionInput(prevHash=c.txid, prevIndex=c.idx) for c in selected_coins]

    # step 6: make transaction
    tx = Transaction(inputs, outputs)
    stream = MemoryStream()
    writer = BinaryWriter(stream)
    tx.serializeUnsigned(writer)
    reg_tx = stream.toArray()
    txid = tx.ensureHash()
    print 'TX ->', repr(reg_tx)
    print 'TXID ->',txid

    # step 7: Signature
    Redeem_script = contract.redeemScript
    sk = SigningKey.from_string(binascii.unhexlify(payer_acc.privateKey), curve=NIST256p, hashfunc=hashlib.sha256)
    signature = binascii.hexlify(sk.sign(binascii.unhexlify(reg_tx),hashfunc=hashlib.sha256))
    regtx = reg_tx + '014140' + signature + '23' + Redeem_script

    # step 8: sendRawTransaction
    node = RemoteNode(url='http://10.84.136.112:20332')
    response = node.sendRawTransaction(regtx)

    # step 9: update coin status
    if response['result'] == True:
        incoming = []
        for i in range(len(outputs)):
            coin = Coin(txid=txid, idx=i, value=outputs[i].Value, asset=asset, address=payee_accs[outputs[i].ScriptHash].address,status=CoinState.Unconfirmed)
            incoming.append(coin)
        wallet_db.onSendTransaction(spending=selected_coins,incoming=incoming)
        return 0
    else:
        return 6
예제 #7
0
class Wallet(object):
    """docstring for Wallet"""
    def __init__(self):
        super(Wallet, self).__init__()
        self.current_height = 0
        self.isrunning = True
        self.isclosed = False
        self.indexeddb = IndexedDBWallet()
        self.node = RemoteNode(url='http://10.84.136.112:20332')

    def getCoinVersion(self):
        return chr(0x17)

    def getWalletHeight(self):  # Need or Not?
        return self.current_height

    def toAddress(self, scripthash):
        return scripthash_to_address(scripthash)

    def findUnSpentCoins(self, scriptHash):
        """
        :return: Coin[]"""
        return self.indexeddb.findCoins(self.toAddress(scriptHash), status=CoinState.Unspent)

    def makeTransaction(self, tx, account):
        """Make Transaction"""
        if tx.outputs == None:
            raise ValueError, 'Not correct Address, wrong length.'

        if tx.attributes == None:
            tx.attributes = []

        coins = self.findUnSpentCoins(account.scriptHash)
        tx.inputs, tx.outputs = self.selectInputs(tx.outputs, coins, account, tx.systemFee)

        # Make transaction
        stream = MemoryStream()
        writer = BinaryWriter(stream)
        tx.serializeUnsigned(writer)
        reg_tx = stream.toArray()
        tx.ensureHash()
        txid = tx.hash

        # RedeenScript
        contract = Contract()
        contract.createSignatureContract(account.publicKey)
        Redeem_script = contract.redeemScript

        # Add Signature
        sk = SigningKey.from_string(binascii.unhexlify(account.privateKey), curve=NIST256p, hashfunc=hashlib.sha256)
        signature = binascii.hexlify(sk.sign(binascii.unhexlify(reg_tx),hashfunc=hashlib.sha256))
        regtx = reg_tx + '014140' + signature + '23' + Redeem_script
        # sendRawTransaction
        print regtx
        response = self.node.sendRawTransaction(regtx)
        import json
        print response
        return txid

    def selectInputs(self, outputs, coins, account, fee):

        scripthash = account.scriptHash

        if len(outputs) > 1 and len(coins) < 1:
            raise Exception, 'Not Enought Coins'

        # Count the total amount of change
        coin = itertools.groupby(sorted(coins, key=lambda x: x.asset), lambda x: x.asset)
        coin_total = dict([(k, sum(int(x.value) for x in g)) for k,g in coin])

        # Count the pay total
        pays = itertools.groupby(sorted(outputs, key=lambda x: x.AssetId), lambda x: x.AssetId)
        pays_total = dict([(k, sum(int(x.Value) for x in g)) for k,g in pays])

        if int(fee.f) > 0:
            if ANTCOIN in pays_total.iterkeys():
                pays_total[ANTCOIN] += int(fee.f)
            else:
                pays_total[ANTCOIN] = int(fee.f)

        # Check whether there is enough change
        for asset, value in pays_total.iteritems():
            if not coin_total.has_key(asset):
                raise Exception, 'Coins does not contain asset {asset}.'.format(asset=asset)

            if coin_total.get(asset) - value < 0:
                raise Exception, 'Coins does not have enough asset {asset}, need {amount}.'.format(asset=asset, amount=value)

        # res: used Coins
        # change: change in outpus
        res = []
        change = []

        # Copy the parms
        _coins  = coins[:]

        # Find whether have the same value of change
        for asset, value in pays_total.iteritems():
            for _coin in _coins:
                if asset == _coin.asset and value == int(_coin.value):
                    # Find the coin
                    res.append(TransactionInput(prevHash=_coin.txid, prevIndex=_coin.idx))
                    _coins.remove(_coin)
                    break

            else:
                # Find the affordable change

                affordable = sorted([i for i in _coins if i.asset == asset and int(i.value) >= value],
                                    key=lambda x: int(x.value))

                # Use the minimum if exists
                if len(affordable) > 0:
                    res.append(TransactionInput(prevHash=affordable[0].txid, prevIndex=affordable[0].idx))
                    _coins.remove(affordable[0])

                    # If the amout > value, set the change
                    amount = int(affordable[0].value)
                    if amount > value:
                        change.append(TransactionOutput(AssetId=asset, Value=str(amount-value), ScriptHash=scripthash))

                else:
                    # Calculate the rest of coins
                    rest = sorted([i for i in _coins if i.asset == asset],
                                  key=lambda x: int(x.value),
                                  reverse=True)

                    amount = 0
                    for _coin in rest:
                        amount += int(_coin.value)
                        res.append(TransactionInput(prevHash=_coin.txid, prevIndex=_coin.idx))
                        _coins.remove(_coin)
                        if amount == value:
                            break
                        elif amount > value:
                            # If the amout > value, set the change
                            change.append(TransactionOutput(AssetId=asset, Value=str(amount-value), ScriptHash=scripthash))
                            break

        return res, outputs + change

    def selectCoins(self, coins, outputs):
        """the simplest alg of selecting coins"""
        total = sum([int(out['amount']) for out in outputs])
        cs = sorted(coins,key=lambda c:c.value,reverse=True)
        print total
        inputs = []
        # has no enough coins
        if sum([int(c.value) for c in coins]) < total:
            return inputs
        for i in range(len(cs)):
            #step 1: find the coin with value==total
            if cs[i].value == total:
                inputs = [cs[i],]
                break
            #step 2: find the min coin with value>total
            if cs[0].value > total and cs[i].value<total:
                inputs = [cs[i-1],]
                break
            #step 3: find the min(max coins) with sum(coins)>= total
            inputs.append(cs[i])
            if cs[0].value<total and sum([i.value for i in inputs]) >= total:
                break
        return inputs

    def addressToScriptHash(self, address):
        data = b58decode(address)
        if len(data) != 25:
            raise ValueError, 'Not correct Address, wrong length.'
        if data[0] != self.getCoinVersion():
            raise ValueError, 'Not correct CoivVersion'
        scriptHash = binascii.hexlify(data[1:21])
        if self.toAddress(scriptHash) == address:
            return scriptHash
        else:
            raise ValueError, 'Not correct Address, something wrong in Address[-4:].'

    def createAccount(self):
        return Account()

    def getAccount(self, privKey=None):
        return Account(privKey)