Exemplo n.º 1
0
    def CalcChange(self, change_addr=None):
        """
        Calculates the change output(s). NOTE: Assumes all other outputs have been added.

        Args:
            change_addr: (str, optional) specify a change address. NOTE: Defaults to the sourceAddress.
        """
        if not change_addr:
            change_addr = self.SOURCE_SCRIPTHASH
        if change_addr != self.SOURCE_SCRIPTHASH:
            change_hash = Helper.AddrStrToScriptHash(
                change_addr)  # also verifies if the address is valid
        else:
            change_hash = change_addr

        if not self.outputs:
            raise RawTXError(
                "Please specify outputs prior to creating change output(s).")

        neo = []
        gas = []
        for output in self.outputs:
            if output.AssetId == UInt256.ParseString(self.neo_asset_id):
                neo.append(output.Value.value)
            elif output.AssetId == UInt256.ParseString(self.gas_asset_id):
                gas.append(output.Value.value)
        if self.SystemFee() > Fixed8.Zero():
            gas.append(self.SystemFee().value)
        if self._network_fee:
            if self._network_fee > Fixed8.Zero():
                gas.append(self._network_fee.value)
        neo_total = 0
        gas_total = 0
        for asset in self.BALANCE:
            if asset['asset_hash'] == self.neo_asset_id:
                neo_total = asset['amount']
            elif asset['asset_hash'] == self.gas_asset_id:
                gas_total = asset['amount']
        neo_diff = Fixed8.FromDecimal(neo_total) - Fixed8(sum(neo))
        gas_diff = Fixed8.FromDecimal(gas_total) - Fixed8(sum(gas))

        if neo_diff < Fixed8.Zero() or gas_diff < Fixed8.Zero():
            raise AssetError('Total outputs exceed the available unspents.')

        if neo_diff > Fixed8.Zero():
            self.outputs.append(
                TransactionOutput(AssetId=UInt256.ParseString(
                    self.neo_asset_id),
                                  Value=neo_diff,
                                  script_hash=change_hash))
        if gas_diff > Fixed8.Zero() and Fixed8(sum(gas)) > Fixed8.Zero():
            self.outputs.append(
                TransactionOutput(AssetId=UInt256.ParseString(
                    self.gas_asset_id),
                                  Value=gas_diff,
                                  script_hash=change_hash))
Exemplo n.º 2
0
    def test_compute_root_multiple_hashes(self):
        expected_hash = Helper.bin_dbl_sha256(
            binascii.unhexlify(b'aa' * 32 + b'bb' * 32))

        hash1 = UInt256(data=binascii.unhexlify(b'aa' * 32))
        hash2 = UInt256(data=binascii.unhexlify(b'bb' * 32))
        hashes = [hash1, hash2]
        root = MerkleTree.ComputeRoot(hashes)

        self.assertEqual(expected_hash, root.ToArray())
Exemplo n.º 3
0
    def test_trim_node3(self):
        hash1 = UInt256(data=binascii.unhexlify(b'aa' * 32))
        hash2 = UInt256(data=binascii.unhexlify(b'bb' * 32))
        hashes = [hash1, hash2]
        m = MerkleTree(hashes)

        depth = 1
        flags = bytearray.fromhex('0000')
        m._TrimNode(m.Root, 1, depth, flags)

        self.assertNotEqual(None, m.Root.LeftChild)
        self.assertNotEqual(None, m.Root.RightChild)
Exemplo n.º 4
0
    def test_trim_tree(self):
        hash1 = UInt256(data=binascii.unhexlify(b'aa' * 32))
        hash2 = UInt256(data=binascii.unhexlify(b'bb' * 32))
        hash3 = UInt256(data=binascii.unhexlify(b'cc' * 32))
        hashes = [hash1, hash2, hash3]
        m = MerkleTree(hashes)

        flags = bytearray.fromhex('0000')
        m.Trim(flags)

        self.assertEqual(None, m.Root.LeftChild)
        self.assertEqual(None, m.Root.RightChild)
Exemplo n.º 5
0
    def test_node_methods(self):
        hash1 = UInt256(data=binascii.unhexlify(b'aa' * 32))
        hash2 = UInt256(data=binascii.unhexlify(b'bb' * 32))
        hashes = [hash1, hash2]
        m = MerkleTree(hashes)

        self.assertEqual(True, m.Root.IsRoot())
        self.assertEqual(False, m.Root.IsLeaf())
        self.assertEqual(False, m.Root.LeftChild.IsRoot())
        self.assertEqual(True, m.Root.LeftChild.IsLeaf())

        # I have no acceptable test vector
        m.Root.LeftChild.Size()
Exemplo n.º 6
0
    def LoadCoins(self):
        coins = {}

        try:
            for coin in Coin.select():
                reference = CoinReference(prev_hash=UInt256(coin.TxId), prev_index=coin.Index)
                output = TransactionOutput(UInt256(coin.AssetId), Fixed8(coin.Value), UInt160(coin.ScriptHash))
                walletcoin = WalletCoin.CoinFromRef(reference, output, coin.State)
                coins[reference] = walletcoin
        except Exception as e:
            logger.error("could not load coins %s " % e)

        return coins
Exemplo n.º 7
0
    def test_trim_node1(self):
        hash1 = UInt256(data=binascii.unhexlify(b'aa' * 32))
        hash2 = UInt256(data=binascii.unhexlify(b'bb' * 32))
        hash3 = UInt256(data=binascii.unhexlify(b'cc' * 32))
        hashes = [hash1, hash2, hash3]
        m = MerkleTree(hashes)

        depth = 2
        flags = bytearray.fromhex(
            '11110000'
        )  # 1 byte left node , 1 byte right node  00=delete, non-00 is keep
        m._TrimNode(m.Root, 1, depth, flags)
        self.assertEqual(None, m.Root.LeftChild)
        self.assertEqual(None, m.Root.RightChild)
Exemplo n.º 8
0
    def test_parse(self):
        string = '0xcedb5c4e24b1f6fc5b239f2d1049c3229ad5ed05293c696b3740dc236c3f41b4'
        uint256 = UInt256.ParseString(string)
        self.assertIsInstance(uint256, UInt256)
        self.assertEqual(uint256.To0xString(), string)

        string = '9410bd44beb7d6febc9278b028158af2781fcfb40cf2c6067b3525d24eff19f6'
        uint256 = UInt256.ParseString(string)
        self.assertIsInstance(uint256, UInt256)
        self.assertEqual(uint256.ToString(), string)

        string = '9410bd44beb7d6febc9278b028158af2781fcfb40cf2c6067b3525d24eff19f'
        with self.assertRaises(ValueError) as context:
            uint256 = UInt256.ParseString(string)
            self.assertIn(f"Invalid UInt256 input: {len(string)} chars != 64 chars", context)
Exemplo n.º 9
0
    def Blockchain_GetHeader(self, engine: ExecutionEngine):
        data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()

        header = None

        if len(data) <= 5:

            height = BigInteger.FromBytes(data)

            if Blockchain.Default() is not None:

                header = Blockchain.Default().GetHeaderBy(height_or_hash=height)

            elif height == 0:

                header = Blockchain.GenesisBlock().Header

        elif len(data) == 32:

            hash = UInt256(data=data)

            if Blockchain.Default() is not None:

                header = Blockchain.Default().GetHeaderBy(height_or_hash=hash)

            elif hash == Blockchain.GenesisBlock().Hash:

                header = Blockchain.GenesisBlock().Header

        engine.CurrentContext.EvaluationStack.PushT(StackItem.FromInterface(header))
        return True
Exemplo n.º 10
0
    def Blockchain_GetBlock(self, engine: ExecutionEngine):
        data = engine.CurrentContext.EvaluationStack.Pop()

        if data:
            data = data.GetByteArray()
        else:
            return False

        block = None

        if len(data) <= 5:
            height = BigInteger.FromBytes(data)

            if Blockchain.Default() is not None:

                block = Blockchain.Default().GetBlockByHeight(height)

            elif height == 0:

                block = Blockchain.GenesisBlock()

        elif len(data) == 32:

            hash = UInt256(data=data).ToBytes()

            if Blockchain.Default() is not None:

                block = Blockchain.Default().GetBlockByHash(hash=hash)

            elif hash == Blockchain.GenesisBlock().Hash:

                block = Blockchain.GenesisBlock().Header

        engine.CurrentContext.EvaluationStack.PushT(StackItem.FromInterface(block))
        return True
Exemplo n.º 11
0
    def GenesisBlock() -> Block:
        """
        Create the GenesisBlock.

        Returns:
            BLock:
        """
        prev_hash = UInt256(data=bytearray(32))
        timestamp = int(
            datetime(2016, 7, 15, 15, 8, 21, tzinfo=pytz.utc).timestamp())
        index = 0
        consensus_data = 2083236893  # Pay tribute To Bitcoin
        next_consensus = Blockchain.GetConsensusAddress(
            Blockchain.StandbyValidators())
        script = Witness(bytearray(0), bytearray(PUSHT))

        mt = MinerTransaction()
        mt.Nonce = 2083236893

        output = TransactionOutput(
            Blockchain.SystemShare().Hash,
            Blockchain.SystemShare().Amount,
            Crypto.ToScriptHash(
                Contract.CreateMultiSigRedeemScript(
                    int(len(Blockchain.StandbyValidators()) / 2) + 1,
                    Blockchain.StandbyValidators())))

        it = IssueTransaction([], [output], [], [script])

        return Block(
            prev_hash, timestamp, index, consensus_data, next_consensus,
            script,
            [mt, Blockchain.SystemShare(),
             Blockchain.SystemCoin(), it], True)
Exemplo n.º 12
0
    def __Build(leaves):
        """
        Build the merkle tree.

        Args:
            leaves (list): items are of type MerkleTreeNode.

        Returns:
            MerkleTreeNode: the root node.

        Raises:
            ValueError: if the length of `leaves` is < 1
        """
        if len(leaves) < 1:
            raise ValueError('Leaves must have length')
        if len(leaves) == 1:
            return leaves[0]

        num_parents = int((len(leaves) + 1) / 2)
        parents = [MerkleTreeNode() for i in range(0, num_parents)]

        for i in range(0, num_parents):
            node = parents[i]
            node.LeftChild = leaves[i * 2]
            leaves[i * 2].Parent = node
            if (i * 2 + 1 == len(leaves)):
                node.RightChild = node.LeftChild
            else:
                node.RightChild = leaves[i * 2 + 1]
                leaves[i * 2 + 1].Parent = node

            hasharray = bytearray(node.LeftChild.Hash.ToArray() + node.RightChild.Hash.ToArray())
            node.Hash = UInt256(data=Crypto.Hash256(hasharray))

        return MerkleTree.__Build(parents)
Exemplo n.º 13
0
    def test_to_hash_array(self):
        hash1 = UInt256(data=binascii.unhexlify(b'aa' * 32))
        hash2 = UInt256(data=binascii.unhexlify(b'bb' * 32))
        hash3 = UInt256(data=binascii.unhexlify(b'cc' * 32))
        hash4 = UInt256(data=binascii.unhexlify(b'dd' * 32))
        hash5 = UInt256(data=binascii.unhexlify(b'ee' * 32))
        hashes = [hash1, hash2, hash3, hash4, hash5]

        m = MerkleTree(hashes)
        hash_array = m.ToHashArray()

        # sort the array
        hash_array = sorted(hash_array)

        for i, h in enumerate(hashes):
            self.assertEqual(h.ToBytes(), hash_array[i].ToBytes())
Exemplo n.º 14
0
    def Blockchain_GetTransactionHeight(self, engine: ExecutionEngine):
        data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()
        height = -1

        if Blockchain.Default() is not None:
            tx, height = Blockchain.Default().GetTransaction(UInt256(data=data))

        engine.CurrentContext.EvaluationStack.PushT(height)
        return True
Exemplo n.º 15
0
    def Account_GetBalance(self, engine: ExecutionEngine):
        account = engine.CurrentContext.EvaluationStack.Pop().GetInterface()
        assetId = UInt256(data=engine.CurrentContext.EvaluationStack.Pop().GetByteArray())

        if account is None:
            return False
        balance = account.BalanceFor(assetId)
        engine.CurrentContext.EvaluationStack.PushT(balance.GetData())
        return True
Exemplo n.º 16
0
    def Blockchain_GetTransaction(self, engine: ExecutionEngine):
        data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()
        tx = None

        if Blockchain.Default() is not None:
            tx, height = Blockchain.Default().GetTransaction(UInt256(data=data))

        engine.CurrentContext.EvaluationStack.PushT(StackItem.FromInterface(tx))
        return True
Exemplo n.º 17
0
    def Size(self):
        """
        Get the total size in bytes of the object.

        Returns:
            int: size.
        """
        corrected_hashes = list(
            map(lambda i: UInt256(data=binascii.unhexlify(i)), self.HashStart))
        return GetVarSize(corrected_hashes) + self.hash_stop.Size
Exemplo n.º 18
0
    def __init__(self, hash_start=[], hash_stop=UInt256()):
        """
        Create an instance.

        Args:
            hash_start (list): a list of hash values. Each value is of the bytearray type. Note: should actually be UInt256 objects.
            hash_stop (UInt256):
        """
        self.HashStart = hash_start
        self.HashStop = hash_stop
Exemplo n.º 19
0
    def Blockchain_GetAsset(self, engine: ExecutionEngine):
        data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray()
        asset = None

        if Blockchain.Default() is not None:
            asset = self.Assets.TryGet(UInt256(data=data))
        if asset is None:
            return False
        engine.CurrentContext.EvaluationStack.PushT(StackItem.FromInterface(asset))
        return True
Exemplo n.º 20
0
    def AddOutput(self, asset, to_addr, amount):
        """
        Specify an output for the transaction.
        NOTE: Can be used multiple times to create multiple outputs.

        Args:
            asset: (str) the asset name or asset hash
            to_addr: (str) the destination NEO address (e.g. 'AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3')
            amount: (int/decimal) the amount of the asset to send
        """
        if asset[0:1] == "0x":
            asset == asset[2:]
        if asset.lower() == "neo":
            assetId = self.neo_asset_id
        elif asset == self.neo_asset_id:
            assetId = self.neo_asset_id
        elif asset.lower() == "gas":
            assetId = self.gas_asset_id
        elif asset == self.gas_asset_id:
            assetId = self.gas_asset_id
        else:
            raise AssetError(
                f'Asset {asset} not found. If trying to send tokens use the `buildTokenTransfer` function.'
            )

        dest_scripthash = Helper.AddrStrToScriptHash(
            to_addr)  # also verifies if the address is valid

        if float(amount) == 0:
            raise ValueError('Amount cannot be 0.')
        f8amount = Fixed8.TryParse(amount, require_positive=True)
        if f8amount is None:
            raise ValueError('Invalid amount format.')
        elif assetId == self.neo_asset_id and (f8amount.value /
                                               Fixed8.D) != f8amount.ToInt():
            raise ValueError('Incorrect amount precision.')

        # check if the outputs exceed the available unspents
        subtotal = []
        if self.outputs:
            for output in self.outputs:
                if output.AssetId == assetId:
                    subtotal.append(output.Value.value)
        total = f8amount.value + sum(subtotal)
        total = float(Fixed8(total).ToString())
        for asset in self.BALANCE:
            if assetId == asset['asset_hash']:
                if total > asset['amount']:
                    raise AssetError(
                        'Total outputs exceed the available unspents.')

        self.outputs.append(
            TransactionOutput(AssetId=UInt256.ParseString(assetId),
                              Value=f8amount,
                              script_hash=dest_scripthash))
Exemplo n.º 21
0
    def Size(self):
        """
        Get the total size in bytes of the object.

        Returns:
            int: size.
        """
        if len(self.Hashes) > 0:
            if not isinstance(self.Hashes[0], UInt256):
                corrected_hashes = list(map(lambda i: UInt256(data=binascii.unhexlify(i)), self.Hashes))
        return s.uint8 + GetVarSize(corrected_hashes)
Exemplo n.º 22
0
    def StaticAssetState(assetId):
        neo = AssetState()
        neo.AssetId = UInt256.ParseString(
            "0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b"
        )
        neo.AssetType = 0x00

        gas = AssetState()
        gas.AssetId = UInt256.ParseString(
            "0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
        )
        gas.AssetType = 0x01

        if assetId == neo.AssetId:
            return neo

        elif assetId == gas.AssetId:
            return gas

        else:
            return None
Exemplo n.º 23
0
    def test_interop_get_bad_transaction_height(self):
        u256 = UInt256.ParseString('8be9660512991d36e016b8ced6fda5d611d26a0f6e2faaaf1f379496edb33956')

        hash = StackItem.New(u256.Data)

        self.econtext.EvaluationStack.PushT(hash)
        self.engine.InvocationStack.PushT(self.econtext)
        self.state_reader.Blockchain_GetTransactionHeight(self.engine)

        height = self.econtext.EvaluationStack.Pop().GetBigInteger()

        self.assertEqual(height, -1)
Exemplo n.º 24
0
    def test_interop_get_transaction(self):
        u256 = UInt256.ParseString('8be9660512991d36e016b8ced6fda5d611d26a0f6e2faaaf1f379496edb3395f')

        hash = StackItem.New(u256.Data)

        self.econtext.EvaluationStack.PushT(hash)
        self.engine.InvocationStack.PushT(self.econtext)
        self.state_reader.Blockchain_GetTransaction(self.engine)

        tx = self.econtext.EvaluationStack.Pop().GetInterface()

        self.assertIsInstance(tx, Transaction)
Exemplo n.º 25
0
    def Hash(self):
        """
        Get the hash of the transaction.

        Returns:
            UInt256:
        """
        if not self.__hash:
            ba = bytearray(binascii.unhexlify(self.GetHashData()))
            hash = Crypto.Hash256(ba)
            self.__hash = UInt256(data=hash)
        return self.__hash
Exemplo n.º 26
0
    def AddClaim(self, claim_addr, to_addr=None):
        """
        Builds a claim transaction for the specified address.

        Args:
            claim_addr: (str) the address from which the claim is being constructed (e.g. 'AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3'). NOTE: Claimed GAS is sent to the claim_addr by default
            to_addr: (str, optional) specify a different destination NEO address (e.g. 'AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3')
        """
        dest_scripthash = Helper.AddrStrToScriptHash(
            claim_addr)  # also verifies if the address is valid
        self.SOURCE_SCRIPTHASH = dest_scripthash

        url = self._network + self._get_claimable + claim_addr
        res = requests.get(url=url)

        if not res.status_code == 200:
            raise NetworkError(
                'Neoscan request failed. Please check your internet connection.'
            )

        res = res.json()
        available = res["unclaimed"]
        if available == 0:
            raise AssetError(
                f"Address {claim_addr} has 0 unclaimed GAS. Please ensure the correct network is selected or specify a difference source address."
            )

        for ref in res['claimable']:
            self.Claims.append(
                CoinReference(prev_hash=UInt256.ParseString(ref['txid']),
                              prev_index=ref['n']))

        if to_addr:
            dest_scripthash = Helper.AddrStrToScriptHash(
                to_addr)  # also verifies if the address is valid

        self.outputs.append(
            TransactionOutput(AssetId=UInt256.ParseString(self.gas_asset_id),
                              Value=Fixed8.FromDecimal(available),
                              script_hash=dest_scripthash))
Exemplo n.º 27
0
    def References(self):
        """
        Get all references.

        Returns:
            dict:
                Key (UInt256): input PrevHash
                Value (TransactionOutput): object.
        """
        if self.__references is None:
            refs = {}
            # group by the input prevhash
            for hash, group in groupby(self.inputs, lambda x: x.PrevHash):
                url = self._network + self._get_transaction + hash.ToString()
                tx = requests.get(url=url)

                if not tx.status_code == 200:
                    raise NetworkError(
                        'Neoscan request failed. Please check your internet connection.'
                    )
                tx = tx.json()

                if tx is not None:
                    for input in group:
                        t = tx['vouts'][input.PrevIndex]
                        if t['asset'].lower() == 'neo':
                            asset = UInt256.ParseString(self.neo_asset_id)
                        elif t['asset'].lower() == 'gas':
                            asset = UInt256.ParseString(self.gas_asset_id)
                        refs[input] = TransactionOutput(
                            AssetId=asset,
                            Value=Fixed8.FromDecimal(t['value']),
                            script_hash=Helper.AddrStrToScriptHash(
                                t['address_hash']))

            self.__references = refs

        return self.__references
Exemplo n.º 28
0
    def test_compareto_valid(self):
        u1 = UInt160(b'12345678901234567890')

        # Same value should return 0
        u2 = UIntBase(20, b'12345678901234567890')
        self.assertEqual(u1.CompareTo(u2), 0)

        # Higher digit in 'other' should return -1
        u2 = UIntBase(20, b'12345678901234567891')
        self.assertEqual(u1.CompareTo(u2), -1)

        # Lower digit in 'other' should return 1
        u2 = UIntBase(20, b'12345678901234567980')
        self.assertEqual(u1.CompareTo(u2), 1)

        # CompareTo across different UIntBase subclasses
        data = b'12345678901234567890'
        self.assertEqual(UInt160(data).CompareTo(UIntBase(len(data), data)), 0)
        self.assertEqual(UIntBase(len(data), data).CompareTo(UInt160(data)), 0)

        data = b'12345678901234567890123456789012'
        self.assertEqual(UInt256(data).CompareTo(UIntBase(len(data), data)), 0)
        self.assertEqual(UIntBase(len(data), data).CompareTo(UInt256(data)), 0)
Exemplo n.º 29
0
    def Hash(self):
        """
        Get the hash value of the Blockbase.

        Returns:
            UInt256: containing the hash of the data.
        """
        if not self.__hash:
            hashdata = self.RawData()
            ba = bytearray(binascii.unhexlify(hashdata))
            hash = bin_dbl_sha256(ba)
            self.__hash = UInt256(data=hash)

        return self.__hash
Exemplo n.º 30
0
    def test_trim_node2(self):
        hash1 = UInt256(data=binascii.unhexlify(b'aa' * 32))
        hash2 = UInt256(data=binascii.unhexlify(b'bb' * 32))
        hash3 = UInt256(data=binascii.unhexlify(b'cc' * 32))
        hash4 = UInt256(data=binascii.unhexlify(b'dd' * 32))
        hash5 = UInt256(data=binascii.unhexlify(b'ee' * 32))
        hash6 = UInt256(data=binascii.unhexlify(b'11' * 32))
        hash7 = UInt256(data=binascii.unhexlify(b'22' * 32))
        hash8 = UInt256(data=binascii.unhexlify(b'33' * 32))
        hash9 = UInt256(data=binascii.unhexlify(b'44' * 32))
        hashes = [
            hash1, hash2, hash3, hash4, hash5, hash6, hash7, hash8, hash9
        ]
        m = MerkleTree(hashes)

        depth = 3
        flags = bytearray.fromhex('111100000000')
        m._TrimNode(m.Root, 1, depth, flags)
        self.assertEqual(None, m.Root.LeftChild)
        self.assertEqual(None, m.Root.RightChild)