예제 #1
0
def get_blockchain():
    blockchain = Blockchain()
    blockchain_sql = Table("blockchain", "number", "hash", "previous", "data", "signature","time")
    for b in blockchain_sql.getall():
        blockchain.add(Block((b.get('number')), b.get('previous'), b.get('data'), (b.get('signature')), b.get('time')))

    return blockchain
예제 #2
0
def get_blockchain():
    blockchain = Blockchain()
    blockchain_sql = Table("blockchain", "number", "hash", "previous", "data", "nonce")
    for b in blockchain_sql.getall():
        blockchain.add(Block(int(b.get('number')), b.get('previous'), b.get('data'), int(b.get('nonce'))))

    return blockchain
def test_add_new_block_to_chain():
    genesis_block = return_genesis_block()
    b = Block(
        1, 0, 213123123123123,
        b'2\x84\x0f\xf6<\x88\xeb\xbej\xcc\xa6C\x02\xc47\x89J!\x93\xf5\x14S\xc6<Y=\xe2?\xf3\xe5\xae\xa2',
        1577836800, "first block")
    # first of this is 10011100
    bc = Blockchain(genesis_block, b)
    bc_short = Blockchain(genesis_block, b)

    assert bc.validate_chain() == True, "Chain Doesn't Validate"

    b1 = Block(
        2, 0, 6477374,
        b'\x8a\x1c\x88T;\x86\x99\xe7i\xa1\xf9Y\x11\x9a\x9675\xd4^^ae+\x10h\x9f\x1f\x91{v\x99n',
        1577836845, "second block")

    assert b1.check_difficulty(0) == True, "still in first block of difficulty"

    bc.add(b1)

    assert bc.validate_chain() == True, "Chain Doesn't Validate"

    longer_chain = bc.chain

    new_blockchain = bc.resolve_via_length(bc_short)
    assert new_blockchain.chain == longer_chain, "The chain is not the longer one"

    new_chain = bc_short.resolve_via_length(bc)
    assert new_blockchain.chain == longer_chain, "The chain is not the longer one"
예제 #4
0
def initializechain():
    global txn4
    chain = Blockchain()

    txn4 = Transaction('ServerReward',client1.publickey.to_string().hex(),100).to_json()
    block = Block([txn4])
    chain.set_blockheader(block)
    chain.add(block,1)

    chain.transactionpool.append(txn4)

    return chain
예제 #5
0
def fileToBlockchain(
    f,
    dhs=None
):  # f is the filename, dhs is the diffie hellman secret (default none)
    fBytes = open(f, 'rb')
    fBlockchain = Blockchain(dhs)
    cur = fBytes.read(64)
    while True:
        fBlockchain.add(cur)
        cur = fBytes.read(64)
        if len(cur) == 0:
            break
    return fBlockchain
예제 #6
0
def fileToBlockchainStream(
    f,
    dhs=None
):  # f is the filename, dhs is the diffie hellman secret (default none)
    fBytes = open(f, 'rb')
    fBlockchain = Blockchain(dhs)
    cur = fBytes.read(64)
    while True:
        fBlockchain.add(cur)
        if fBlockchain.size > 1:
            yield fBlockchain.popHead()
        cur = fBytes.read(64)
        if len(cur) == 0:
            yield fBlockchain.popHead()
            break
예제 #7
0
def get_user_block(username):
    blockchain_sql = Table("blockchain", "number", "hash", "previous", "data",
                           "nonce")
    user_blockchain = Blockchain()
    for b in blockchain_sql.getall():
        data = b.get('data').split("-->")
        if username == data[0]:
            user_blockchain.add(
                Block(int(b.get('number')), b.get('previous'), b.get('data'),
                      b.get('nonce')))
        if username == data[1]:
            user_blockchain.add(
                Block(int(b.get('number')), b.get('previous'), b.get('data'),
                      b.get('nonce')))
    return user_blockchain
def init_chain():
    genesis_block = return_genesis_block()
    b = Block(
        1, 0, 213123123123123,
        b'2\x84\x0f\xf6<\x88\xeb\xbej\xcc\xa6C\x02\xc47\x89J!\x93\xf5\x14S\xc6<Y=\xe2?\xf3\xe5\xae\xa2',
        1577836800, "first block")
    # first of this is 10011100
    bc = Blockchain(genesis_block, b)

    b1 = Block(
        2, 0, 6477374,
        b'\x8a\x1c\x88T;\x86\x99\xe7i\xa1\xf9Y\x11\x9a\x9675\xd4^^ae+\x10h\x9f\x1f\x91{v\x99n',
        1577836845, "second block")

    bc.add(b1)

    return bc
예제 #9
0
def blockchain():
    blockchain = Blockchain()

    private_keys = [43, 53, 63]
    public_keys = mapv(lambda priv: PrivateKey(priv).public_key().to_bytes(),
                       private_keys)

    genesis_block = GenesisBlock(miner_pub_key=public_keys[0])
    genesis_block.mine(blockchain.get_difficult())
    blockchain.add(genesis_block)

    miners = [public_keys[1], public_keys[2]]
    outputs_array = [[(public_keys[0], 1), (public_keys[1], 2)],
                     [(public_keys[2], 10), (public_keys[1], 1)]]

    for key, miner, outputs in zip(private_keys, miners, outputs_array):
        transaction = Wallet(key).sign(Transaction(outputs))
        block = Block(blockchain.get_last_block(), [transaction],
                      miner_pub_key=miner)
        block.mine(blockchain.get_difficult())
        blockchain.add(block)

    return blockchain
예제 #10
0
def main():
    bc = Blockchain()

    walletA = Wallet('A')
    walletB = Wallet('B')
    coinbase = Wallet('C')
    
    genesis_trx = Transaction(coinbase.public_key, walletA.public_key, 1000000, None)
    genesis_trx.generate_signature(coinbase.private_key, coinbase.password)
    genesis_trx.transaction_id = '0'
    genesis_trx.outputs.append(TransactionOutput(genesis_trx.recipient, genesis_trx.value, genesis_trx.transaction_id))
    bc.genesis_trx = genesis_trx
    bc.UTXOs[bc.genesis_trx.outputs[0].id] = bc.genesis_trx.outputs[0]

    print('Creating and mining genesis block...')
    genesis = Block('0')
    genesis.add_transaction(genesis_trx)
    bc.add(genesis)

    f=open("time.csv", "w+")

    for i in range(1000000):
        print("%d: " % i, end='')
        start = time.time()
        block = Block(bc.get_last_hash())
        # print("Wallet A's balance is:", walletA.get_balance())
        # print("Wallet A is attempting to send funds(1) to Wallet B...")
        block.add_transaction(walletA.send_funds(walletB.public_key, 1))
        bc.add(block)
        end = time.time()
        f.write(("%d,%f\n" % (i, end-start)))
        # print("Wallet A's balance is:", walletA.get_balance())
        # print("Wallet B's balance is:", walletB.get_balance())

    print("Wallet B's balance is:", walletB.get_balance())
    print("Wallet B is attempting to send funds(1000000) to Wallet A...")
    
    start = time.time()
    block = Block(bc.get_last_hash())
    block.add_transaction(walletB.send_funds(walletA.public_key, 1000000))
    bc.add(block)
    end = time.time()

    print("Wallet A's balance is:", walletA.get_balance())
    print("Wallet B's balance is:", walletB.get_balance())

    print("Time elapsed: %fs" % (end-start))

    bc.is_valid()

    f.close()
예제 #11
0
from blockchain import Blockchain, Transaction, Block
'''
This is an example on how the simplified blockchain code can be used.
To see it in action simply run the entire notebook.
'''

# Setup blockchain
blockchain = Blockchain()

# Add new block by directly passing in transactions
transaction_1 = Transaction("Aleksander Sadowski", "Wiktor Domaradzki", 1.00)
transaction_2 = Transaction("Aleksander Sadowski", "Wiktor Domaradzki", 2.50)
transaction_3 = Transaction("Wiktor Domaradzki", "Aleksander Sadowski", 3.50)
blockchain.add_transactions([transaction_1, transaction_2, transaction_3])

# Add new block by first creating a new block and adding it to the blockchain afterwards
transaction_4 = Transaction("Wiktor Domaradzki", "Aleksander Sadowski", 12.00)
transaction_5 = Transaction("Aleksander Sadowski", "Wiktor Domaradzki", 5.50)
block = Block(blockchain.blocks[1].hash.hexdigest(),
              [transaction_4, transaction_5])
blockchain.add(block)

# Print blockchain to the console
blockchain.display()
예제 #12
0
def test():
    ## Generate Key
    sk = SigningKey.generate(curve=NIST192p)
    vk = sk.get_verifying_key()
    sk2 = SigningKey.generate(curve=NIST192p)
    vk2 = sk2.get_verifying_key()

    ## Create Transactions
    newTxn = Transaction(vk.to_string().hex(), 'receiverkey', 100)
    ## convert to JSON
    toJson = newTxn.to_json()
    ## Sign JSON
    signature = newTxn.sign(toJson, sk.to_string())
    print(signature)
    ## Validate
    validated = newTxn.validate_signature(toJson, signature, vk.to_string())

    txn1 = Transaction(vk.to_string().hex(), 'receiverkey1', 100).to_json()
    txn2 = Transaction(vk.to_string().hex(), 'client1', 100).to_json()
    txn3 = Transaction(vk2.to_string().hex(), 'client3', 100).to_json()
    transactionlist = [txn1, txn2, txn3]

    ## Create Block with transaction
    block = Block(transactionlist)
    block2 = Block([txn3])
    chain = Blockchain()
    chain.set_blockheader(block)
    chain.add(block, 1)
    chain.set_blockheader(block2)
    chain.add(block2, 2)

    #Populate blockchain with blocks
    for i in range(2):
        chain.set_blockheader(block)
        chain.add(block, 1)

    txn4 = Transaction('receiverkey1', 'receiverkey3', 100).to_json()
    txn5 = Transaction('receiverkey3', 'receiverkey1', 100).to_json()

    chain.transactionpool.append(txn4)
    chain.transactionpool.append(txn5)

    # Miner Test
    m1 = Miner(chain)
    m2 = Miner(chain)
    block4 = m1.mine(chain)
    chain.add(block4, m1.publickey.to_string().hex())
    block5 = m1.mine(chain)
    chain.add(block5, m1.publickey.to_string().hex())

    # SPV Test
    spvclient = SPVClient()
    checktransaction = spvclient.receive_transaction(txn3, m1)
    newtxn = spvclient.new_txn(m1.publickey.to_string().hex(), 100)
    nt = m1.new_txn(spvclient.publickey.to_string().hex(), 100)

    print(nt)
    miners_list = [m1, m2]

    #####selfish mining attack####
    m3 = SelfishMiner(chain)
    miners_list.append(m3)
    for miner in miners_list:
        block = miner.mine(chain)
        chain.add(block, miner.publickey.to_string().hex())

    #trying to show the number of blocks mined by selfish miners
    selfish_blocks = m3.selfish_mine(chain)
    print("Selfish miner's work: ", selfish_blocks)

    ###DOUBLE SPENDING attack###
    m4 = DoubleSpender(chain)

    #first let m4 have some money
    #m2 make txn to send 60 to m4
    txnToDS = m2.new_txn(m4.publickey.to_string().hex(), 60)

    #attacker mine the latest txn pool
    dsBlock = m4.mine(chain)
    chain.add(dsBlock, m4.publickey.to_string().hex())
    print("Attacker's balance (before) is",
          m4.get_balance(chain,
                         m4.publickey.to_string().hex()))

    #he then performs the attack
    dsBlocks = m4.attack(chain)
    print("Attacker's balance (after) is",
          m4.get_balance(chain,
                         m4.publickey.to_string().hex()))
예제 #13
0
		print("Valid: {}\n".format(self.valid))

## Unit test
if __name__ == "__main__":

	
	# Initialize MPI
	comm = MPI.COMM_WORLD
	size = comm.Get_size() # Returns the number of tasks in comm
	rank = comm.Get_rank()	# Returns the rank of the calling task

	bchain = Blockchain()

	Coinbase = {"amount": "100.00", "recipient": "Anders"}  
	Tx = []
	bchain.add( Block_v3(block = "1", nonce = "16651", coinbase = Coinbase, tx = Tx) )


	Coinbase = {"amount": "100.00", "recipient": "Anders"}  
	Tx = [{"amount": "10.00", "from": "Anders", "recipient": "Sophia"},
		{"amount": "20.00", "from": "Anders", "recipient": "Lucas"},
		{"amount": "15.00", "from": "Anders", "recipient": "Emily"},
		{"amount": "15.00", "from": "Anders", "recipient": "Madison"}  ]
	bchain.add( Block_v3(block = "2", nonce = "215458", coinbase = Coinbase, tx = Tx) )

	Coinbase = {"amount": "100.00", "recipient": "Anders"}  
	Tx = [{"amount": "10.00", "from": "Emily", "recipient": "Jackson"},
		{"amount": "5.00", "from": "Madison", "recipient": "Jackson"},
		{"amount": "20.00", "from": "Lucas", "recipient": "Grace"}  ]
	bchain.add( Block_v3(block = "3", nonce = "146", coinbase = Coinbase, tx = Tx) )
예제 #14
0
class Consensus:
    def __init__(self):
        self.state = StateMachine()
        self.blockchain = Blockchain()
        self.transaction_pool = []
        self.executed_transactions = []
        self.nodes = []
        self.lock = Lock()

    def set_port(self, port):
        ports = [port]  #5000, 5001, 5002]
        for p in ports:
            self.nodes.append(f'127.0.0.1:{p}')
        self.me = f'127.0.0.1:{port}'
        neighbours = list(self.nodes)
        neighbours.remove(self.me)
        self.network = Network(self.me, neighbours)

    def new_transaction(self, transaction):
        self.lock.acquire()
        # drive consensus over the transaction
        transaction.set_registrer(self.me)
        self.add_transaction(transaction)
        self.lock.release()
        return True

    def report_transaction(self, transaction):
        self.lock.acquire()
        self.add_transaction(transaction)
        self.lock.release()

    def add_transaction(self, transaction):
        if transaction not in self.executed_transactions and transaction not in self.transaction_pool:
            self.transaction_pool.append(transaction)
            self.network.broadcast_transaction(transaction)
            if self.my_turn():
                self.sign()

    def my_turn(self):
        last_signer = self.blockchain.last_signer()
        last_index = self.nodes.index(last_signer) if last_signer else -1
        next = 0 if last_index + 1 == len(self.nodes) else last_index + 1
        return self.nodes[next] == self.me

    def execute_block(self, block):
        for transaction in block.transactions:
            self.state.execute_transaction(transaction)

    def sign(self):
        block = Block(self.transaction_pool, self.me,
                      self.blockchain.last_hash())
        self.blockchain.add(block)
        self.transaction_pool = []
        self.network.broadcast_block(block)
        self.execute_block(block)

    def report_block(self, transactions, signer, previous):
        self.lock.acquire()
        if self.blockchain.last_hash() == previous:
            block = Block(transactions, signer, previous)
            self.blockchain.add(block)
            for transaction in transactions:
                if transaction in self.transaction_pool:
                    self.transaction_pool.remove(transaction)
                self.executed_transactions.append(transaction)
            self.network.broadcast_block(block)
            self.execute_block(block)
        self.lock.release()
예제 #15
0
## Unit test
if __name__ == "__main__":

    # Initialize MPI
    comm = MPI.COMM_WORLD
    size = comm.Get_size()  # Returns the number of tasks in comm
    rank = comm.Get_rank()  # Returns the rank of the calling task

    P1 = Person("Vincent")
    P2 = Person("Samir")

    bchain = Blockchain()

    Coinbase = {"amount": "100.00", "recipient": P1.pubkey}
    T = []
    bchain.add(Block_v4(block="1", nonce="29082", coinbase=Coinbase, tx=T))

    Coinbase = {"amount": "100.00", "recipient": P1.pubkey}
    T = [Tx("100", P1.public_key, P2.public_key, P1.private_key)]
    bchain.add(Block_v4(block="2", nonce="16651", coinbase=Coinbase, tx=T))

    if rank == 0:
        bchain.show()

    bchain.mine()

    if rank == 0:
        print("We mine, and get the NEW nonce for every blocks")
        bchain.show()
예제 #16
0
class Miner(Node):
    NORMAL = 0  # normal miner
    DS_MUTATE = 1  # starts to plant private chain for double spending
    DS_ATTACK = 2  # publish the withheld blocks to effect double spending

    def __init__(self, privkey, pubkey, address, listener=MinerListener):
        print(f"address: {address}")
        super().__init__(privkey, pubkey, address, listener)
        self.unconfirmed_transactions = []  # data yet to get into blockchain
        self.blockchain = Blockchain()
        self.my_unconfirmed_txn = list(
        )  # all unconfirmed transactions sent by me
        self.copy_all_unconfirmed_txn = list()

        self.stop_mine = threading.Event(
        )  # a indicator for whether to continue mining

        #attack
        self.mode = Miner.NORMAL
        # self.private_chain = None
        self.hidden_blocks_num = 0
        self.hidden_blocks = list()
        self.fork_block = None

    @classmethod
    def new(cls, address):
        """Create new Miner instance"""
        signing_key = ecdsa.SigningKey.generate()
        verifying_key = signing_key.get_verifying_key()
        privkey = signing_key
        pubkey = verifying_key
        return cls(privkey, pubkey, address)

    def get_own_balance(self):
        balance = self.get_balance(stringify_key(self.pubkey))
        self.log(f"balance = {balance}")
        return balance

    """ inquiry """

    def get_transaction_proof(self, tx_json):
        """Get proof of transaction given transaction json"""
        # ask the blockchain to search each block to obtain possible proof from merkle tree
        proof, blk = self.blockchain.get_proof(tx_json)
        return proof, blk.hash

    def get_balance(self, identifier):
        """Get balance given identifier ie. pubkey"""
        balance = self.blockchain.get_balance()
        if identifier not in balance:
            return 0
        return balance[identifier]

    def get_blk_headers(self):
        """Get headers of blocks of the longest chain"""
        blk_headers = {}
        for block in self.blockchain.get_blks():
            blk_headers[block.compute_hash()] = block.header

        return blk_headers

    """ Transactions """

    def make_transaction(self, receiver, amount, comment=""):
        """Create a new transaction"""
        if self.get_balance(stringify_key(self.pubkey)) >= amount:
            tx = Transaction.new(
                sender=self._keypair[1],
                receiver=obtain_key_from_string(receiver),
                amount=amount,
                comment="",
                key=self._keypair[0],
                nonce=self.blockchain.get_nonce(stringify_key(self.pubkey)) +
                1 + len(self.my_unconfirmed_txn))
            tx_json = tx.serialize()
            self.log(" Made a new transaction")
            self.my_unconfirmed_txn.append(tx_json)
            self.add_transaction(tx)
            msg = "t" + json.dumps({"tx_json": tx_json})
            self.broadcast_message(msg)
            return tx
        else:
            self.log("Not enough balance in your account!")

    def add_transaction(self, tx):
        """Add transaction to the pool of unconfirmed transactions and miner's own transaction list"""
        if not tx.validate():
            raise Exception("New transaction failed signature verification.")
        if not self.tx_resend_check(tx):
            raise Exception("New transaction failed resending check.")
        tx_json = tx.serialize()

        self.unconfirmed_transactions.append(tx_json)
        self.log(
            f"{len(self.unconfirmed_transactions)} number of unconfirmed transactions"
        )

    def tx_resend_check(self, tx):
        nonce = self.blockchain.get_nonce(stringify_key(tx.sender))
        self.log(f"most recent nonce = {nonce} vs new nonce = {tx.nonce}")
        if tx.nonce <= nonce:
            self.log(
                "New transaction failed resending check based on most updated chain."
            )
            return False
        else:
            self.log(
                "New transaction passed resending check based on most updated chain."
            )
            return True

    """ Mining """

    def mine(self):
        if self.peers is None and self.stop_mine.is_set():
            return None

        self.log(
            f"mining on block height of {self.blockchain.last_node.block.blk_height} ....\n....\n"
        )
        time.sleep(1)
        tx_collection = self.get_tx_pool()
        self.log(
            f"Number of unconfirmed transactions I'm mining on {len(self.get_tx_pool())}"
        )

        if not self.check_balance_and_nonce(
                tx_collection, self.blockchain.last_node.block.hash):
            raise Exception("abnormal transactions!")
            return None

        new_block = self.create_new_block(tx_collection)
        proof = self.proof_of_work(new_block, self.stop_mine)
        if proof is None:
            return None

        self.log("prev_hash")
        self.blockchain.add(new_block, proof)
        for tx in tx_collection:
            self.unconfirmed_transactions.remove(tx)

        self.broadcast_blk(new_block, proof)
        self.log(" Mined a new block +$$$$$$$$")
        print("""
                    |---------|
                    |  block  |
                    |---------|
        """)
        self.blockchain.print()

        return new_block

    def get_tx_pool(self):
        if self.mode == Miner.DS_ATTACK:
            unconfirm = copy.deepcopy(self.copy_all_unconfirmed_txn)

            if len(self.my_unconfirmed_txn) != len(self.ds_txns):
                raise Exception("Double spend transactions wrongly replaced")

            unconfirm.extend(self.ds_txns)
            pool = [x for x in unconfirm if x not in self.my_unconfirmed_txn]

        else:
            pool = copy.deepcopy(self.unconfirmed_transactions)

        return pool

    def get_last_node(self):
        """returns last block of specified chain"""
        if self.mode == Miner.DS_ATTACK:
            if self.hidden_blocks_num == 0:
                return self.fork_block
            else:
                return self.hidden_blocks[self.hidden_blocks_num - 1]

        else:
            return self.blockchain.last_node.block

    def create_new_block(self, tx_collection):
        last_node = self.get_last_node()

        new_block = Block(transactions=tx_collection,
                          timestamp=time.time(),
                          previous_hash=last_node.compute_hash(),
                          miner=self.pubkey)

        return new_block

    def broadcast_blk(self, new_blk, proof):
        blk_json = new_blk.serialize()
        self.broadcast_message("b" + json.dumps({
            "blk_json": blk_json,
            "blk_proof": proof
        }))
        self.broadcast_message("h" +
                               json.dumps({
                                   "blk_hash": new_blk.compute_hash(),
                                   "blk_header": new_blk.header
                               }))

    def proof_of_work(self, block, stop_mine):
        """
        Function that tries different values of the nonce to get a hash
        that satisfies our difficulty criteria.
        """
        start = time.time()
        computed_hash = block.compute_hash()

        while not computed_hash < TARGET:
            if self.stop_mine.is_set():
                # self.log("Stop Mining as others have found the block")
                return None
            random.seed(time.time())
            block.nonce = random.randint(0, 100000000)
            computed_hash = block.compute_hash()

        end = time.time()
        self.log(
            f"Found proof = {computed_hash} < TARGET in {end - start} seconds")
        return computed_hash

    def check_balance_and_nonce(self, transactions, blk_hash):
        """
            Check balance state if transactions were applied.
            The balance of an account is checked to make sure it is larger than
            or equal to the spending transaction amount.
        """
        balance = self.blockchain.get_balance(blk_hash)
        tx_nonce = {}

        for tx_json in transactions:
            recv_tx = Transaction.deserialize(tx_json)
            # Sender must exist so if it doesn't, return false

            sender = stringify_key(recv_tx.sender)
            receiver = stringify_key(recv_tx.receiver)
            if sender not in balance:
                return False
            # checking if nonce run into conflict with previous nonce
            if sender not in tx_nonce:
                tx_nonce[sender] = []
            if recv_tx.nonce <= self.blockchain.get_nonce(sender, blk_hash):
                self.log(
                    "Detect conflicting nonce from transactions in chain!")
                return False
            elif recv_tx.nonce in tx_nonce[sender]:
                self.log(
                    "Detect conflicting nonce from transactions in collection")
                return False
            else:
                tx_nonce[sender].append(recv_tx.nonce)
            # Create new account for receiver if it doesn't exist
            if receiver not in balance:
                balance[receiver] = 0
            balance[sender] -= recv_tx.amount
            balance[receiver] += recv_tx.amount
            # Negative balance, return false
            if balance[sender] < 0 or balance[receiver] < 0:
                print("Negative balance can exist!")
                return False
        return True

    """DS Miner functions"""

    def get_longest_len(self, chain):
        """Get length of longest chain"""
        if chain == "public":
            return self.blockchain.last_node.block.blk_height
        else:
            # return self.private_chain.last_node.block.blk_height
            return self.fork_block.blk_height + self.hidden_blocks_num

    def setup_ds_attack(self):
        """Change miner to DS mode and take note of fork location"""
        self.mode = Miner.DS_MUTATE
        self.fork_block = self.get_last_node()
        # self.private_chain = copy.deepcopy(self.blockchain)
        self.copy_all_unconfirmed_txn = copy.deepcopy(
            self.unconfirmed_transactions)
        self.ds_txns = self.create_ds_txn()
        self.log("Ready for DS attack")

    def create_ds_txn(self):
        """replace DS miner's own unconfirmed transactions with new senders"""
        ds_txns = list()

        if self.mode != Miner.DS_MUTATE:
            raise Exception(
                "Honest miners cannot create double spend transactions")

        for tx_json in self.my_unconfirmed_txn:
            tx = Transaction.deserialize(tx_json)

            if tx.sender != self._keypair[1]:
                raise Exception(
                    "Sender is double spending on the wrong transaction")

            replacement_tx = Transaction.new(sender=self._keypair[1],
                                             receiver=self._keypair[1],
                                             amount=tx.amount,
                                             comment=tx.comment,
                                             key=self._keypair[0],
                                             nonce=tx.nonce)
            replacement_tx_json = replacement_tx.serialize()
            ds_txns.append(replacement_tx_json)

        return ds_txns

    def ds_mine(self):
        if self.mode == Miner.NORMAL:
            raise Exception("Normal Miner cannot double spend")

        else:
            self.mode = Miner.DS_ATTACK
            self.log(
                f"mining on block height of {self.blockchain.last_node.block.blk_height} ....\n....\n"
            )

            tx_collection = self.get_tx_pool()
            # if not self.check_balance_and_nonce(tx_collection):
            #     raise Exception("abnormal transactions!")

            new_block = self.create_new_block(tx_collection)

            proof = self.proof_of_work(new_block, self.stop_mine)
            if proof is None:
                return None

            # self.private_chain.add_block(new_block, proof)
            self.hidden_blocks.append(new_block)
            self.hidden_blocks_num += 1

            for tx in tx_collection:
                if tx in self.copy_all_unconfirmed_txn:
                    self.copy_all_unconfirmed_txn.remove(tx)

            self.log(" Mined a new block +$$$$$$$$")
            print("""
                        |---------|
                        | dsblock |
                        |---------|
            """)
            self.blockchain.print()

        # if hidden chain is longer than public chain, no longer need to mine, just publish
        pub = self.get_longest_len("public")
        priv = self.get_longest_len("hidden")
        self.log(
            f"Checking if length of private chain {priv} > public chain {pub}")
        if self.get_longest_len("public") < self.get_longest_len("hidden"):
            self.ds_broadcast()
            return

        return new_block

    def ds_broadcast(self):
        if self.mode != Miner.DS_ATTACK:
            raise Exception("Miner is not in attacking mode")

        self.log("Starting DS chain Broadcast...")
        blocks = self.hidden_blocks
        count = 1

        for blk in blocks:
            self.log(
                f"Broadcasting block {count} out of {self.hidden_blocks_num}")
            self.blockchain.add_block(blk, blk.compute_hash())
            self.broadcast_blk(blk, blk.compute_hash())
            count += 1
            time.sleep(2)

        self.end_ds_attack()

    def end_ds_attack(self):
        self.log("Ended DS attack...")
        self.hidden_blocks_num = 0
        self.hidden_blocks = list()
        self.fork_block = None
        self.mode = Miner.NORMAL
        self.copy_all_unconfirmed_txn = list()
예제 #17
0
# -*- coding: utf-8 -*-
"""
Created on Fri Mar 26 09:47:11 2021

@author: Lenovo
"""

import json
import random
from uuid import uuid4
from blockchain import Blockchain, Block
from transaction import Transaction
if __name__ == '__main__':
    chain = Blockchain()
    for i in range(3):
        block = Block()
        for j in range(10):
            transaction = Transaction(sender=str(uuid4()), receiver=str(uuid4()),
                                      amount=random.randint(1, 1000000)
                                      )
            block.add(transaction)
        chain.add(block)
#if __name__ == '__main__':
#    print(json.dumps(json.loads(str(chain)), indent=4, sort_keys=True))
#    print(chain.validate())
#测试更改        
if __name__ == '__main__':
    chain.blocks[0].items[0].receiver = str(uuid4())
    print(json.dumps(json.loads(str(chain)), indent=4, sort_keys=True))
    print(chain.validate())
#