コード例 #1
0
    def handle_ADDR(self, addr):
        try:
            nodes = utils.read_message(addr)['nodes']
            utils.logg(" [<] Recieved addr list from peer %s" %
                       self.remote_nodeid)
            #for node in filter(lambda n: nodes[n][1] == "SEND", nodes):
            for node in nodes:
                utils.logg(" [*] %s %s" % (node[0], node[1]))

                if node[0] == self.nodeid:
                    utils.logg("[!] Not connecting to %s thats me!" % node[0])
                    return
                if node[1] != "SPEAKER":
                    utils.logg("[!] Not connecting to %s is %s" %
                               (node[0], node[1]))
                    return
                if node[0] in self.factory.peers:
                    utils.logg("[!] Not connecting to %s already connected" %
                               node[0])
                    return
                _print(" [ ] Trying to connect to peer " + node[0] + " " +
                       node[1])
                # TODO: Use [2] and a time limit to not connect to "old" peers
                host, port = node[0].split(":")
                point = TCP4ClientEndpoint(reactor, host, int(port))
                d = connectProtocol(
                    point, NCProtocol(ncfactory, "SENDHELLO", "SPEAKER"))
                d.addCallback(gotProtocol)
        except utils.InvalidSignatureError:
            _print(" [!] ERROR: Invalid addr sign ", self.remote_ip)
            self.transport.loseConnection()
コード例 #2
0
 def dataReceived(self, data):
     for line in data.splitlines():
         line = line.strip()
         envelope = utils.read_envelope(line)
         if self.state in ["GETHELLO", "SENTHELLO"]:
             # Force first message to be HELLO or crash
             if envelope['msgtype'] == 'hello':
                 self.handle_HELLO(line)
             else:
                 utils.logg(
                     f" [!] Ignoring {envelope['msgtype']}  in {self.state}"
                 )
         else:
             if envelope['msgtype'] == 'ping':
                 self.handle_PING(line)
             elif envelope['msgtype'] == 'pong':
                 self.handle_PONG(line)
             elif envelope['msgtype'] == 'addr':
                 pass
             elif envelope['msgtype'] == 'sync':
                 self.handle_SYNC(line)
             elif envelope['msgtype'] == 'givemeblocks':
                 self.handle_SENDBLOCKS(line)
             elif envelope['msgtype'] == 'getblock':
                 self.handleRECEIVEDBLOCK(line)
コード例 #3
0
    def handle_HELLO(self, hello):
        try:
            hello = utils.read_message(hello)
            self.remote_nodeid = hello['nodeid']
            self.remote_node_protocol_version = hello["protocol"]

            if self.remote_nodeid == self.nodeid:
                utils.logg("[!] Found myself at %s" % self.host_ip)
                self.transport.loseConnection()
            else:
                if self.state == "GETHELLO":
                    my_hello = utils.create_hello(self.nodeid, self.VERSION,
                                                  self.ProtocolVersion)
                    self.transport.write(my_hello + "\n")
                self.add_peer()
                self.state = "READY"
                self.print_peers()
                #self.write(utils.create_ping(self.nodeid))
                if self.kind == "LISTENER":
                    # The listener pings it's audience
                    utils.logg("[ ] Starting pinger to %s" % self.remote_ip)
                    self.lc_ping.start(PING_INTERVAL, now=False)
                    # Tell new audience about my peers
                    self.send_ADDR()
                self.lc_sync.start(SYNC_INTERVAL, now=True)
        except utils.InvalidSignatureError:
            _print(" [!] ERROR: Invalid hello sign ", self.remote_ip)
            self.transport.loseConnection()
コード例 #4
0
ファイル: transaction.py プロジェクト: cvsae/blockchain-py
    def verify(self, prev_txs):
        for vin in self.vin:
            if not prev_txs[vin.tx_id].ID:
                # log.error("Previous transaction is not correct")
                utils.logg("Previous transaction is not correct")

        tx_copy = self._trimmed_copy()

        for in_id, vin in enumerate(self.vin):
            prev_tx = prev_txs[vin.tx_id]
            tx_copy.vin[in_id].signature = None
            tx_copy.vin[in_id].public_key = prev_tx.vout[vin.vout].public_key_hash
            tx_copy.ID = tx_copy.hash()
            tx_copy.vin[in_id].public_key = None

            sig = self.vin[in_id].signature

            # vk = ecdsa.VerifyingKey.from_string(
            #     vin.public_key[2:], curve=ecdsa.SECP256k1)
            vk = utils.pubkey_to_verifykey(vin.public_key)

            if not vk.verify(sig, utils.encode(tx_copy.ID)):
                return False

        return True
コード例 #5
0
 def send_ADDR(self):
     utils.logg(" [>] Telling to %s about my peers" % self.remote_nodeid)
     # Shouldn't this be a list and not a dict?
     peers = self.factory.peers
     listeners = [(n, peers[n][0], peers[n][1], peers[n][2]) for n in peers]
     addr = utils.create_addr(self.nodeid, listeners)
     self.write(addr)
コード例 #6
0
    def handle_SENDBLOCKS(self, line):
        # A peer ask us top send him blocks
        utils.logg("[>] Got sendblocks message from %s" % self.remote_nodeid)

        # read peer message
        data = utils.read_message(line)
        # extract remote peer besthash from message
        peer_best = data["besthash"]

        # be sure that we have peer besthash block
        if peer_best in ctx.mapBlockIndex:
            # find the next block hash
            next_hash = next_block(peer_best)
            # access the block object of the next hash
            block = ctx.mapBlockIndex[next_hash]
            # serialize the block object
            ret = block.serialize()
            # build a sent block message containing serialized block
            message = utils.create_send_block(self.nodeid, ret)
            # send the block to peer
            self.write(message)
            # logg :P
            utils.logg("block %s send to %s" %
                       (thisHeight + 1, self.remote_nodeid))
        else:
            pass
コード例 #7
0
 def send_SYNC(self):
     # Send a sync message to remote peer
     utils.logg("[>] Asking %s if we need sync" % self.remote_nodeid)
     # Build a sync message, contains our best height and our besthash
     sync = utils.create_sync(self.nodeid, ctx.BestHeight,
                              ctx.bestBlockHash)
     # send the sync message
     self.write(sync)
コード例 #8
0
 def send_PING(self):
     # Send a pig message to remote peer
     utils.logg(" [>] PING   to %s %s" %
                (self.remote_nodeid, self.remote_ip))
     # Build a ping message
     ping = utils.create_ping(self.nodeid)
     # send the ping message
     self.write(ping)
コード例 #9
0
 def add_peer(self):
     entry = (self.remote_ip, self.kind, self.remote_node_protocol_version,
              time())
     self.factory.peers[self.remote_nodeid] = entry
     utils.logg(
         "[] peer %s at %s with protocol version %d added to peers list" %
         (self.remote_nodeid, self.remote_ip,
          self.remote_node_protocol_version))
コード例 #10
0
 def handle_PONG(self, pong):
     # Receive a pong message
     pong = utils.read_message(pong)
     # loggig
     utils.logg("[<] PONG from %s at %s" %
                (self.remote_nodeid, self.remote_ip))
     # hacky
     addr, kind = self.factory.peers[self.remote_nodeid][:2]
     self.factory.peers[self.remote_nodeid] = (addr, kind, time())
コード例 #11
0
def GetNextWorkRequired(pindexLast):

    if pindexLast == None:
        return 10

    # Difficulty will change every 600 seconds or 10 minuntes
    nTargetTimespan = 600
    # We need a new block every 100 seconds
    nTargetSpacing = 50
    # That give us a interval 12 blocks
    nInterval = nTargetTimespan / nTargetSpacing

    # Only change once per interval
    if ((ctx.mapBlockHeight[pindexLast] + 1) % nInterval != 0):
        return ctx.mapBlockIndex[pindexLast].bits

    # A dictionary that allow to access a block hash by height
    heights = dict((v, k) for k, v in ctx.mapBlockHeight.items())

    nActualTimespan = int(
        ctx.mapBlockIndex[pindexLast].timestamp -
        ctx.mapBlockIndex[heights[ctx.mapBlockHeight[pindexLast] - nInterval +
                                  2]].timestamp)

    if nActualTimespan < nTargetTimespan / 4:
        nActualTimespan = nTargetTimespan / 4
    if nActualTimespan > nTargetTimespan * 4:
        nActualTimespan = nTargetTimespan * 4

    bnNew = utils.bits2target(ctx.mapBlockIndex[pindexLast].bits)
    bnNew *= nActualTimespan
    bnNew /= nTargetTimespan

    if bnNew > bnProofOfWorkLimit:
        bnNew = bnProofOfWorkLimit

    utils.logg("\n\n\nGetNextWorkRequired RETARGET *****\n")
    utils.logg("nTargetTimespan = %d    nActualTimespan = %d\n" % (
        nTargetTimespan,
        nActualTimespan,
    ))
    utils.logg("Last %d blocks time average was %d\n" % (
        nInterval,
        nActualTimespan,
    ))
    utils.logg("Before: %08x  %s\n" % (
        ctx.mapBlockIndex[pindexLast].bits,
        nActualTimespan,
    ))
    utils.logg("After:  %08x  %s\n" % (
        utils.GetCompact(int(bnNew)),
        nActualTimespan,
    ))

    return utils.target2bits(bnNew)
コード例 #12
0
ファイル: transaction.py プロジェクト: cvsae/blockchain-py
    def sign(self, priv_key, prev_txs):
        for vin in self.vin:
            if prev_txs[vin.tx_id].isCoinBase():
                # log.error("Previous transaction is not correct")
                utils.logg("Previous transaction is not correct")

        tx_copy = self._trimmed_copy()

        for in_id, vin in enumerate(tx_copy.vin):
            prev_tx = prev_txs[vin.tx_id]
            tx_copy.vin[in_id].signature = None
            tx_copy.vin[in_id].public_key = prev_tx.vout[vin.vout].public_key_hash
            tx_copy.ID = tx_copy.hash()
            tx_copy.vin[in_id].public_key = None

            sk = ecdsa.SigningKey.from_string(
                priv_key, curve=ecdsa.SECP256k1)
            sig = sk.sign(utils.encode(tx_copy.ID))

            self.vin[in_id].signature = sig
コード例 #13
0
ファイル: transaction.py プロジェクト: cvsae/blockchain-py
    def __init__(self, from_addr, to_addr, amount, utxo_set):
        inputs = []
        outputs = []

        # log('UTXOTx')
        wallets = ws.Wallets()
        wallet = wallets.get_wallet(from_addr)
        pubkey_hash = utils.hash_public_key(wallet.public_key)

        acc, valid_outputs = utxo_set.find_spendable_outputs(
            pubkey_hash, amount)
        if acc < amount:
            # log.error('Not enough funds')
            utils.logg('Not enough funds')
            sys.exit()

        # Build a list of inputs
        for tx_id, outs in valid_outputs.items():
            for out in outs:
                ctxin = TXInput()
                ctxin._tx_id = tx_id
                ctxin._vout = out 
                ctxin._signature = None 
                ctxin._public_key = wallet.public_key

                inputs.append(ctxin)

        # Build a list of outputs
        outputs.append(TXOutput(amount, to_addr))
        if acc > amount:
            # A change
            outputs.append(TXOutput(acc-amount, from_addr))

        self._tx = Transaction()
        self._tx.vin = inputs
        self._tx.vout = outputs
        self._tx.set_id()
        
        self._utxo_set = utxo_set
        
        self._sign_utxo(wallet.private_key)
コード例 #14
0
    def handle_SYNC(self, line):
        # Got a reply about a sync message
        utils.logg("[>] Got reply about sync message from %s" %
                   self.remote_nodeid)
        # read sync message
        data = utils.read_message(line)
        # peer height
        peerHeight = data["bestheight"]

        # we have missing blocks, we are behind
        if peerHeight > ctx.BestHeight:
            # calculate the diffrence
            diffrence = peerHeight - ctx.BestHeight
            # logging
            utils.logg("We need sync, we are behind %d blocks" % diffrence)
            # set dialog
            self.factory.dialog = "Need sync"
            # build a ask blocks message
            message = utils.create_ask_blocks(self.nodeid, ctx.bestBlockHash)
            # send ask block message to peer
            self.write(message)

        # peer heigfht == our heigh okkk
        elif peerHeight == ctx.BestHeight:
            self.factory.dialog = "Synced"
            utils.logg("we are synced")
コード例 #15
0
 def print_peers(self):
     if len(self.factory.peers) == 0:
         utils.logg(" [!] PEERS: No peers connected.")
     else:
         utils.logg(" [ ] PEERS:")
         for peer in self.factory.peers:
             addr, kind = self.factory.peers[peer][:2]
             utils.logg(" [*] %s at %s %s " % (peer, addr, kind))
コード例 #16
0
def Miner(txs):
    address = GenerateNewAddress()

    # create a coinbase transaction
    txnew = Transaction()
    txnew.vin[0].tx_id = ''
    txnew.vin[
        0].public_key = 'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks'
    txnew.vout[0].value = 50 * COIN
    txnew.vout[0].address = address
    txnew.set_id()

    # create new block and Add our coinbase tx as first transaction
    block = Block([txnew])

    # Collect the latest transactions into the block
    if len(txs) > 0:
        for tx in txs:
            block._tx_lst.append(tx)

    utils.logg('Running Miner with %d txs in block' % len(block._tx_lst))

    block.timestamp = int(time.time())
    block.prev_block_hash = ctx.bestBlockHash
    block.nonce = 0
    block.bits = GetNextWorkRequired(ctx.bestBlockHash)  #

    # target
    target = utils.bits2target(block.bits)

    i = 0

    while 1:
        block.nonce = i
        hash_hex = block.getHash()
        hash_int = int(hash_hex, 16)
        if hash_int < target:
            # proccess this block
            utils.logg('Miner found a block %s' % hash_hex)
            if ProccessBlock(block, block.nonce):
                utils.logg('Miner block accepted:')
                return True
            else:
                utils.logg('Miner block rejected:')
                return False
            break

        i += 1
コード例 #17
0
def AcceptBlock(block):

    bc = Blockchain()
    if bc.haveBlock(block.hash):
        utils.logg('ProccessBlock() Error - Block %s already exists' %
                   block.hash)
        return False

    # Check prev block
    if bc._tip != block.prev_block_hash:
        utils.logg("Proccess().thisBlock : prev block not found")
        return False

    # Check timestamp against prev
    if bc.getBlock(bc._tip).timestamp >= block.timestamp:
        utils.logg("Proccess().thisBlock : block's timestamp is too early")
        return False

    #  Check Proof Of Work
    if block.bits != GetNextWorkRequired(ctx.bestBlockHash):
        utils.logg("Proccess().thisBlock : incorrect proof of work")
        return False

    if not bc._block_put(block):
        utils.logg("AcceptBlock() : WriteToDisk failed")
        return False

    utxo_set = UTXOSet(bc)
    utxo_set.reindex()

    ctx.mapBlockIndex[block.hash] = block
    ctx.BestHeight = ctx.BestHeight + 1
    ctx.mapBlockHeight[block.hash] = ctx.BestHeight
    ctx.bestBlockHash = block.hash

    return True
コード例 #18
0
ファイル: block.py プロジェクト: cvsae/blockchain-py
    def CheckBlock(self):
        # Size limits
        if len(self._tx_lst) == 0 or len(self._tx_lst) > 1000000000:
            utils.logg("CheckBlock() : size limits failed")
            return False

        # First transaction must be coinbase, the rest must not be
        if len(self._tx_lst) == 0 or not self._tx_lst[0].isCoinBase():
            utils.logg("CheckBlock() : first tx is not coinbase")
            return False

        for i in range(1, len(self._tx_lst)):
            if self._tx_lst[i].isCoinBase():
                utils.logg("CheckBlock() : more than one coinbase")
                return False

        # Check transactions
        for tx in self._tx_lst:
            if not tx.CheckTransaction():
                utils.logg("CheckBlock() : CheckTransaction failed")
                return False

        return True
コード例 #19
0
def ProccessBlock(block, nonce):
    blockhash = block.getHash()

    # Check for duplicate
    bc = Blockchain()
    if bc.haveBlock(blockhash):
        utils.logg('ProccessBlock() Error - Block %s already exists' %
                   blockhash)
        return False

    if not block.CheckBlock():
        utils.logg("ProcessBlock() : CheckBlock FAILED")
        return True

    if not ctx.mapBlockIndex[block.prev_block_hash]:
        utils.logg("ProcessBlock: ORPHAN BLOCK, prev=%s\n" %
                   block.prev_block_hash)

    if not AcceptBlock(block):
        utils.logg("ProcessBlock() : AcceptBlock FAILED")
        return False

    return True
コード例 #20
0
ファイル: transaction.py プロジェクト: cvsae/blockchain-py
    def CheckTransaction(self):
        # Basic checks that don't depend on any context
        if len(self.vin) == 0 or len(self.vout) == 0:
            utils.logg("Transaction::CheckTransaction() : vin or vout empty")
            return False

        # Check for negative values
        for txout in self.vout:
            if txout.value < 0:
                utils.logg("CTransaction::CheckTransaction() : txout.nValue negative")
                return False

        if not self.isCoinBase():
            for txin in self.vin:
                if txin.tx_id == 0:
                    utils.logg("CTransaction::CheckTransaction() : prevout is null")
                    return False
        
        return True
コード例 #21
0
    def handleRECEIVEDBLOCK(self, line):
        # We rceive a new block
        utils.logg("Proccesing block from %s" %
                   (ctx.getBestHeight + 1, self.remote_nodeid))
        # read block message
        data = utils.read_message(line)
        # extract block from message
        block = data["block"]

        # check if rceived block* is an instance of the Block object
        if isinstance(block, Block):
            # deserialize the blockk
            pblock = Block([]).deserialize(block)
            # procces this block
            if ProccessBlock(block, block.nonce):
                utils.logg('Miner block accepted:')
            else:
                utils.logg('Miner block rejected:')
        else:
            pass
コード例 #22
0
def Start(factory):

    p2p_host = utils.p2p_host
    p2p_port = utils.p2p_port

    try:
        endpoint = TCP4ServerEndpoint(reactor,
                                      int(p2p_port),
                                      interface=p2p_host)
        utils.logg(" [ ] LISTEN: at %s:%d" % (p2p_host, (int(p2p_port))))
        endpoint.listen(factory)
    except CannotListenError:
        utils.logg("[!] Address in use")
        raise SystemExit

    # connect to bootstrap addresses
    utils.logg(" [ ] Trying to connect to bootstrap hosts:")

    #point = TCP4ClientEndpoint(reactor, p2p_port, int(p2p_port))
    #d = connectProtocol(point, NCProtocol(factory, "SENDHELLO", "LISTENER"))
    #d.addCallback(gotProtocol)

    reactor.run(installSignalHandlers=0)
コード例 #23
0
        if hash_int < target:
            # proccess this block
            utils.logg('Miner found a block %s' % hash_hex)
            if ProccessBlock(block, block.nonce):
                utils.logg('Miner block accepted:')
                return True
            else:
                utils.logg('Miner block rejected:')
                return False
            break

        i += 1


if loadBlockIndex():
    utils.logg('BlockIndex loaded')


def Mining():
    while 1:
        f = Miner([])


############################################################################################


class NCProtocol(Protocol):
    def __init__(self, factory, state="GETHELLO", kind="LISTENER"):
        self.factory = factory
        self.state = state
        self.VERSION = 0
コード例 #24
0
 def startFactory(self):
     utils.logg("Node started")
コード例 #25
0
def loadBlockIndex():
    blockchain = Blockchain()

    utils.logg('Loading BlockIndex')

    #
    # Load block index
    #

    for block in reversed(list(blockchain.blocks)):
        # add to index
        ctx.mapBlockIndex[block.hash] = block
        ctx.BestHeight = ctx.BestHeight + 1
        ctx.bestBlockHash = block.hash
        ctx.mapBlockHeight[block.hash] = ctx.BestHeight

    #
    # Init with genesis block
    #

    if len(ctx.mapBlockIndex) == 0:
        txnew = Transaction()

        # Transaction

        # inputs
        txnew.vin[0].tx_id = ''
        txnew.vin[0].vout = -1
        txnew.vin[
            0].public_key = 'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks'
        # output
        txnew.vout[0].value = 50 * COIN
        txnew.vout[0].address = '1F6kc25HfrXcn9b4brsNzCiTDWuqsDzAmx'
        txnew.set_id()

        # Transaction(id='12c86ae42baf87e9186cd2fabae575e5534ee0bb82a61a8d0d5616d3ec9bf029',
        # vin=[TXInput(tx_id=b'', vout=-1, signature=None, public_key='The Times 03/Jan/2009 Chancellor on brink of second bailout for banks')],
        # vout=[TXOutput(address='1F6kc25HfrXcn9b4brsNzCiTDWuqsDzAmx', value=5000000000, public_key_hash='9aa83d479c33c697cd727fc87d753d2d7f2daf19')])

        # Block

        block = Block([txnew])
        block.prev_block_hash = ''
        block.timestamp = 1607965519
        block.bits = 0x1e0fffff
        block.nonce = 1484712

        #Block(timestamp=b'1607965519', tx_lst=[Transaction(id='12c86ae42baf87e9186cd2fabae575e5534ee0bb82a61a8d0d5616d3ec9bf029',
        #vin=[TXInput(tx_id=b'', vout=-1, signature=None, public_key='The Times 03/Jan/2009 Chancellor on brink of second bailout for banks')],
        #vout=[TXOutput(address='1F6kc25HfrXcn9b4brsNzCiTDWuqsDzAmx', value=5000000000, public_key_hash='9aa83d479c33c697cd727fc87d753d2d7f2daf19')])],
        #prev_block_hash=b'', hash=None, nonce=1484712, bits=504365055)

        assert (
            block.getHash() ==
            '0000054bd29593ff231e77f7005a9e288e162bbda8cb8962077d57d9be8f87c0')

        blockchain._block_put(block)
        utxo_set = UTXOSet(blockchain)
        utxo_set.reindex()

        utils.logg('Genesis block added to database')

        # add to index
        ctx.mapBlockIndex[block.hash] = block
        ctx.mapBlockHeight[block.hash] = 1
        ctx.BestHeight = ctx.BestHeight + 1
        ctx.bestBlockHash = block.hash

        # Miner
        '''
        target = utils.bits2target(block.bits)

        i = 0 
        while 1:
            block.nonce = i 
            hash_hex = block.getHash()
            hash_int = int(hash_hex, 16)
            if hash_int < target:
                print (hash_hex, block.nonce, block.timestamp)

            i +=1

        '''

    return True