예제 #1
0
 def test_from_dict(self):
     value = {
         "chain": "BNB",
         "from_address": "USER",
         "to_address": "VAULT",
         "coins": [
             {"asset": "BNB.BNB", "amount": 1000},
             {"asset": RUNE, "amount": "1000"},
         ],
         "memo": "STAKE:BNB.BNB",
     }
     txn = Transaction.from_dict(value)
     self.assertEqual(txn.chain, "BNB")
     self.assertEqual(txn.from_address, "USER")
     self.assertEqual(txn.to_address, "VAULT")
     self.assertEqual(txn.memo, "STAKE:BNB.BNB")
     self.assertEqual(txn.coins[0].asset, "BNB.BNB")
     self.assertEqual(txn.coins[0].amount, 1000)
     self.assertEqual(txn.coins[1].asset, RUNE)
     self.assertEqual(txn.coins[1].amount, 1000)
     self.assertEqual(txn.gas, None)
     value["coins"] = None
     value["gas"] = [{"asset": "BNB.BNB", "amount": "37500"}]
     txn = Transaction.from_dict(value)
     self.assertEqual(txn.chain, "BNB")
     self.assertEqual(txn.from_address, "USER")
     self.assertEqual(txn.to_address, "VAULT")
     self.assertEqual(txn.memo, "STAKE:BNB.BNB")
     self.assertEqual(txn.coins, None)
     self.assertEqual(txn.gas[0].asset, "BNB.BNB")
     self.assertEqual(txn.gas[0].amount, 37500)
예제 #2
0
 def test_custom_hash(self):
     txn = Transaction(
         Binance.chain,
         "USER",
         "tbnb1yxfyeda8pnlxlmx0z3cwx74w9xevspwdpzdxpj",
         Coin("BNB.BNB", 194765912),
         "REFUND:TODO",
         id="9999A5A08D8FCF942E1AAAA01AB1E521B699BA3A009FA0591C011DC1FFDC5E68",
     )
     self.assertEqual(
         txn.custom_hash(""),
         "FE64709713A9F9D691CF2C5B144CA6DAA53E902800C1367C692FE7935BD029CE",
     )
     txn.coins = None
     self.assertEqual(
         txn.custom_hash(""),
         "229BD31DB372A43FB71896BDE7512BFCA06731A4D825B4721A1D8DD800159DCD",
     )
     txn.to_address = "tbnb189az9plcke2c00vns0zfmllfpfdw67dtv25kgx"
     txn.coins = [Coin(RUNE, 49900000000)]
     txn.memo = (
         "REFUND:CA3A36052DC2FC30B91AD3996012E9EF2E69EEA70D5FBBBD9364F6F97A056D7C"
     )
     pubkey = (
         "thorpub1addwnpepqv7kdf473gc4jyls7hlx4rg"
         "t2lqxm9qkfh5m3ua7wnzzzfhlpz49u4slu4g"
     )
     if DEFAULT_RUNE_ASSET == RUNE:
         self.assertEqual(
             txn.custom_hash(pubkey),
             "158D75777A5C23A5C8A39B55C0812252C0ABA9A87816D5E74BB7166EB95EDB73",
         )
예제 #3
0
 def test_to_json(self):
     txn = Transaction(
         Binance.chain, "USER", "VAULT", Coin("BNB.BNB", 100), "STAKE:BNB",
     )
     self.assertEqual(
         txn.to_json(),
         '{"id": "TODO", "chain": "BNB", "from_address": "USER", '
         '"to_address": "VAULT", "memo": "STAKE:BNB", "coins": '
         '[{"asset": "BNB.BNB", "amount": 100}], "gas": null}',
     )
     txn.coins = [Coin("BNB.BNB", 1000000000), Coin(RUNE, 1000000000)]
     self.assertEqual(
         txn.to_json(),
         '{"id": "TODO", "chain": "BNB", "from_address": "USER", '
         '"to_address": "VAULT", "memo": "STAKE:BNB", "coins": ['
         '{"asset": "BNB.BNB", "amount": 1000000000}, '
         '{"asset": "' + RUNE + '", "amount": 1000000000}], "gas": null}',
     )
     txn.coins = None
     self.assertEqual(
         txn.to_json(),
         '{"id": "TODO", "chain": "BNB", "from_address": "USER", '
         '"to_address": "VAULT", "memo": "STAKE:BNB", "coins": null, "gas": null}',
     )
     txn.gas = [Coin("BNB.BNB", 37500)]
     self.assertEqual(
         txn.to_json(),
         '{"id": "TODO", "chain": "BNB", "from_address": "USER", '
         '"to_address": "VAULT", "memo": "STAKE:BNB", "coins": null,'
         ' "gas": [{"asset": "BNB.BNB", "amount": 37500}]}',
     )
예제 #4
0
 def test_constructor(self):
     txn = Transaction(Binance.chain, "USER", "VAULT", Coin("BNB.BNB", 100), "MEMO",)
     self.assertEqual(txn.chain, "BNB")
     self.assertEqual(txn.from_address, "USER")
     self.assertEqual(txn.to_address, "VAULT")
     self.assertEqual(txn.coins[0].asset, "BNB.BNB")
     self.assertEqual(txn.coins[0].amount, 100)
     self.assertEqual(txn.memo, "MEMO")
     txn.coins = [Coin("BNB.BNB", 1000000000), Coin(RUNE, 1000000000)]
     self.assertEqual(txn.coins[0].asset, "BNB.BNB")
     self.assertEqual(txn.coins[0].amount, 1000000000)
     self.assertEqual(txn.coins[1].asset, RUNE)
     self.assertEqual(txn.coins[1].amount, 1000000000)
예제 #5
0
    def refund(self, txn, code, reason):
        """
        Returns a list of refund transactions based on given txn
        """
        txns = []
        for coin in txn.coins:
            if not coin.is_rune():
                pool = self.get_pool(coin.asset)
                if pool.rune_balance == 0:
                    continue  # no pool exists, skip it
            txns.append(
                Transaction(
                    txn.chain,
                    txn.to_address,
                    txn.from_address,
                    [coin],
                    f"REFUND:{txn.id}",
                ))

        # generate event REFUND for the transaction
        event = Event(
            "refund",
            [{
                "code": code
            }, {
                "reason": reason
            }, *txn.get_attributes()],
        )
        self.events.append(event)
        return txns
예제 #6
0
 def test_str(self):
     txn = Transaction(Binance.chain, "USER", "VAULT", Coin("BNB.BNB", 100), "MEMO",)
     self.assertEqual(str(txn), "Tx     USER ==> VAULT    | MEMO | 100_BNB.BNB")
     txn.coins = [Coin("BNB.BNB", 1000000000), Coin(RUNE, 1000000000)]
     self.assertEqual(
         str(txn),
         "Tx     USER ==> VAULT    | MEMO | 1,000,000,000_BNB.BNB"
         f", 1,000,000,000_{RUNE}",
     )
     txn.coins = None
     self.assertEqual(
         str(txn), "Tx     USER ==> VAULT    | MEMO | No Coins",
     )
     txn.gas = [Coin("BNB.BNB", 37500)]
     self.assertEqual(
         str(txn), "Tx     USER ==> VAULT    | MEMO | No Coins | Gas 37,500_BNB.BNB",
     )
예제 #7
0
 def test_gas(self):
     bnb = Binance()
     txn = Transaction(
         Binance.chain, "USER", "VAULT", Coin("BNB.BNB", 5757575), "MEMO",
     )
     self.assertEqual(
         bnb._calculate_gas(None, txn), Coin("BNB.BNB", 37500),
     )
     txn = Transaction(
         Binance.chain,
         "USER",
         "VAULT",
         [Coin("BNB.BNB", 0), Coin("RUNE", 0)],
         "MEMO",
     )
     self.assertEqual(
         bnb._calculate_gas(None, txn), Coin("BNB.BNB", 60000),
     )
예제 #8
0
 def test_is_cross_chain_stake(self):
     tx = Transaction(
         Binance.chain,
         "USER",
         "VAULT",
         Coin("BNB.BNB", 100),
         "STAKE:BNB.BNB:STAKER-1",
     )
     self.assertEqual(tx.is_cross_chain_stake(), False)
     tx = Transaction(
         "THOR", "USER", "VAULT", Coin("THOR.RUNE", 100), "STAKE:BNB.BNB:STAKER-1",
     )
     self.assertEqual(tx.is_cross_chain_stake(), True)
     tx = Transaction("THOR", "USER", "VAULT", Coin("THOR.RUNE", 100), "STAKE:",)
     self.assertEqual(tx.is_cross_chain_stake(), False)
예제 #9
0
 def test_repr(self):
     txn = Transaction(Binance.chain, "USER", "VAULT", Coin("BNB.BNB", 100), "MEMO",)
     self.assertEqual(
         repr(txn), "<Tx     USER ==> VAULT    | MEMO | [<Coin 100_BNB.BNB>]>"
     )
     txn.coins = [Coin("BNB.BNB", 1000000000), Coin(RUNE, 1000000000)]
     self.assertEqual(
         repr(txn),
         "<Tx     USER ==> VAULT    | MEMO | [<Coin 1,000,000,000_BNB.BNB>,"
         f" <Coin 1,000,000,000_{RUNE}>]>",
     )
     txn.coins = None
     self.assertEqual(
         repr(txn), "<Tx     USER ==> VAULT    | MEMO | No Coins>",
     )
     txn.gas = [Coin("BNB.BNB", 37500)]
     self.assertEqual(
         repr(txn),
         "<Tx     USER ==> VAULT    | MEMO | No Coins |"
         " Gas [<Coin 37,500_BNB.BNB>]>",
     )
예제 #10
0
    def test_transfer(self):
        bnb = Binance()
        from_acct = bnb.get_account("tbnbA")
        from_acct.add(Coin("BNB.BNB", 300000000))
        bnb.set_account(from_acct)

        txn = Transaction(
            bnb.chain, "tbnbA", "tbnbB", Coin("BNB.BNB", 200000000), "test transfer"
        )
        bnb.transfer(txn)

        to_acct = bnb.get_account("tbnbB")

        self.assertEqual(to_acct.get("BNB.BNB"), 200000000)
        self.assertEqual(from_acct.get("BNB.BNB"), 99962500)
예제 #11
0
    def handle_swap(self, txn):
        """
        Does a swap (or double swap)
        MEMO: SWAP:<asset(req)>:<address(op)>:<target_trade(op)>
        """
        # parse memo
        parts = txn.memo.split(":")
        if len(parts) < 2:
            if txn.memo == "":
                return self.refund(txn, 105, "memo can't be empty")
            return self.refund(txn, 105, f"invalid tx type: {txn.memo}")

        address = txn.from_address
        # check address to send to from memo
        if len(parts) > 2:
            address = parts[2]
            # checking if address is for mainnet, not testnet
            if address.lower().startswith("bnb"):
                reason = f"address format not supported: {address}"
                return self.refund(txn, 105, reason)

        # get trade target, if exists
        target_trade = 0
        if len(parts) > 3:
            target_trade = int(parts[3] or "0")

        asset = Asset(parts[1])

        # check that we have one coin
        if len(txn.coins) != 1:
            reason = "unknown request: not expecting multiple coins in a swap"
            return self.refund(txn, 105, reason)

        source = txn.coins[0].asset
        target = asset

        # refund if we're trying to swap with the coin we given ie swapping bnb
        # with bnb
        if source == asset:
            reason = "unknown request: swap Source and Target cannot be the same."
            return self.refund(txn, 105, reason)

        pools = []

        in_txn = txn

        if not txn.coins[0].is_rune() and not asset.is_rune():
            # its a double swap
            pool = self.get_pool(source)
            if pool.is_zero():
                # FIXME real world message
                return self.refund(txn, 105, "refund reason message")

            emit, liquidity_fee, liquidity_fee_in_rune, trade_slip, pool = self.swap(
                txn.coins[0], RUNE)
            if str(pool.asset) not in self.liquidity:
                self.liquidity[str(pool.asset)] = 0
            self.liquidity[str(pool.asset)] += liquidity_fee_in_rune

            # here we copy the txn to break references cause
            # the tx is split in 2 events and gas is handled only once
            in_txn = deepcopy(txn)

            # generate first swap "fake" outbound event
            out_txn = Transaction(
                emit.asset.get_chain(),
                txn.from_address,
                txn.to_address,
                [emit],
                txn.memo,
                id=Transaction.empty_id,
            )

            event = Event("outbound", [{
                "in_tx_id": in_txn.id
            }, *out_txn.get_attributes()])
            self.events.append(event)

            # generate event for SWAP transaction
            event = Event(
                "swap",
                [
                    {
                        "pool": pool.asset
                    },
                    {
                        "price_target": 0
                    },
                    {
                        "trade_slip": trade_slip
                    },
                    {
                        "liquidity_fee": liquidity_fee
                    },
                    {
                        "liquidity_fee_in_rune": liquidity_fee_in_rune
                    },
                    *in_txn.get_attributes(),
                ],
            )
            self.events.append(event)

            # and we remove the gas on in_txn for the next event so we don't
            # have it twice
            in_txn.gas = None

            pools.append(pool)
            in_txn.coins[0] = emit
            source = RUNE
            target = asset

        # set asset to non-rune asset
        asset = source
        if asset.is_rune():
            asset = target

        pool = self.get_pool(asset)
        if pool.is_zero():
            # FIXME real world message
            return self.refund(in_txn, 105,
                               "refund reason message: pool is zero")

        emit, liquidity_fee, liquidity_fee_in_rune, trade_slip, pool = self.swap(
            in_txn.coins[0], asset)
        pools.append(pool)

        # check emit is non-zero and is not less than the target trade
        if emit.is_zero() or (emit.amount < target_trade):
            reason = f"emit asset {emit.amount} less than price limit {target_trade}"
            return self.refund(in_txn, 108, reason)

        if str(pool.asset) not in self.liquidity:
            self.liquidity[str(pool.asset)] = 0
        self.liquidity[str(pool.asset)] += liquidity_fee_in_rune

        # save pools
        for pool in pools:
            self.set_pool(pool)

        # get from address VAULT cross chain
        from_address = in_txn.to_address
        if from_address != "VAULT":  # don't replace for unit tests
            from_alias = get_alias(in_txn.chain, from_address)
            from_address = get_alias_address(target.get_chain(), from_alias)

        gas = None

        # calculate gas if BTC
        if target.get_chain() == "BTC":
            gas = [Bitcoin._calculate_gas(pool, txn)]

        # calculate gas if ETH
        if target.get_chain() == "ETH":
            gas = [Ethereum._calculate_gas(pool, txn)]

        out_txns = [
            Transaction(
                target.get_chain(),
                from_address,
                address,
                [emit],
                f"OUTBOUND:{txn.id.upper()}",
                gas=gas,
            )
        ]

        # generate event for SWAP transaction
        event = Event(
            "swap",
            [
                {
                    "pool": pool.asset
                },
                {
                    "price_target": target_trade
                },
                {
                    "trade_slip": trade_slip
                },
                {
                    "liquidity_fee": liquidity_fee
                },
                {
                    "liquidity_fee_in_rune": liquidity_fee_in_rune
                },
                *in_txn.get_attributes(),
            ],
        )
        self.events.append(event)

        return out_txns
예제 #12
0
    def handle_unstake(self, txn):
        """
        handles a unstaking transaction
        MEMO: WITHDRAW:<asset(req)>:<address(op)>:<basis_points(op)>
        """
        withdraw_basis_points = 10000

        # parse memo
        parts = txn.memo.split(":")
        if len(parts) < 2:
            if txn.memo == "":
                return self.refund(txn, 105, "memo can't be empty")
            return self.refund(txn, 105, f"invalid tx type: {txn.memo}")

        # get withdrawal basis points, if it exists in the memo
        if len(parts) >= 3:
            withdraw_basis_points = int(parts[2])

        # empty asset
        if parts[1] == "":
            return self.refund(txn, 105, "Invalid symbol")

        asset = Asset(parts[1])

        # add any rune to the reserve
        for coin in txn.coins:
            if coin.asset.is_rune():
                self.reserve += coin.amount
            else:
                coin.amount = 0

        pool = self.get_pool(asset)
        staker = pool.get_staker(txn.from_address)
        if staker.is_zero():
            # FIXME real world message
            return self.refund(txn, 105, "refund reason message")

        # calculate gas prior to update pool in case we empty the pool
        # and need to subtract
        gas = None
        if asset.get_chain() == "BTC":
            gas = [Bitcoin._calculate_gas(pool, txn)]

        if asset.get_chain() == "ETH":
            gas = [Ethereum._calculate_gas(pool, txn)]

        unstake_units, rune_amt, asset_amt = pool.unstake(
            txn.from_address, withdraw_basis_points)

        # if this is our last staker of bnb, subtract a little BNB for gas.
        if pool.total_units == 0:
            if pool.asset.is_bnb():
                fee_amt = 37500
                if RUNE.get_chain() == "BNB":
                    fee_amt *= 2
                asset_amt -= fee_amt
                pool.asset_balance += fee_amt
            elif pool.asset.is_btc() or pool.asset.is_eth():
                asset_amt -= gas[0].amount
                pool.asset_balance += gas[0].amount

        self.set_pool(pool)

        # get from address VAULT cross chain
        from_address = txn.to_address
        if from_address != "VAULT":  # don't replace for unit tests
            from_alias = get_alias(txn.chain, from_address)
            from_address = get_alias_address(asset.get_chain(), from_alias)

        # get to address cross chain
        to_address = txn.from_address
        if to_address not in get_aliases():  # don't replace for unit tests
            to_alias = get_alias(txn.chain, to_address)
            to_address = get_alias_address(asset.get_chain(), to_alias)

        out_txns = [
            Transaction(
                RUNE.get_chain(),
                txn.to_address,
                txn.from_address,
                [Coin(RUNE, rune_amt)],
                f"OUTBOUND:{txn.id.upper()}",
            ),
            Transaction(
                asset.get_chain(),
                from_address,
                to_address,
                [Coin(asset, asset_amt)],
                f"OUTBOUND:{txn.id.upper()}",
                gas=gas,
            ),
        ]

        # generate event for UNSTAKE transaction
        event = Event(
            "unstake",
            [
                {
                    "pool": pool.asset
                },
                {
                    "stake_units": unstake_units
                },
                {
                    "basis_points": withdraw_basis_points
                },
                {
                    "asymmetry": "0.000000000000000000"
                },
                *txn.get_attributes(),
            ],
        )
        self.events.append(event)

        return out_txns
예제 #13
0
    def test_smoke(self):
        export = os.environ.get("EXPORT", None)
        export_events = os.environ.get("EXPORT_EVENTS", None)

        failure = False
        snaps = []
        bnb = Binance()  # init local binance chain
        btc = Bitcoin()  # init local bitcoin chain
        eth = Ethereum()  # init local ethereum chain
        thorchain = ThorchainState()  # init local thorchain

        file = "data/smoke_test_transactions.json"
        if RUNE.get_chain() == "THOR":
            file = "data/smoke_test_native_transactions.json"

        with open(file, "r") as f:
            contents = f.read()
            loaded = json.loads(contents)

        for i, txn in enumerate(loaded):
            txn = Transaction.from_dict(txn)
            logging.info(f"{i} {txn}")

            if txn.chain == Binance.chain:
                bnb.transfer(txn)  # send transfer on binance chain
            if txn.chain == Bitcoin.chain:
                btc.transfer(txn)  # send transfer on bitcoin chain
            if txn.chain == Ethereum.chain:
                eth.transfer(txn)  # send transfer on ethereum chain

            if txn.memo == "SEED":
                continue

            outbound = thorchain.handle(
                txn)  # process transaction in thorchain
            outbound = thorchain.handle_fee(txn, outbound)
            thorchain.order_outbound_txns(outbound)

            for txn in outbound:
                if txn.chain == Binance.chain:
                    bnb.transfer(txn)  # send outbound txns back to Binance
                if txn.chain == Bitcoin.chain:
                    btc.transfer(txn)  # send outbound txns back to Bitcoin
                if txn.chain == Ethereum.chain:
                    eth.transfer(txn)  # send outbound txns back to Ethereum

            thorchain.handle_rewards()

            bnbOut = []
            for out in outbound:
                if out.coins[0].asset.get_chain() == "BNB":
                    bnbOut.append(out)
            btcOut = []
            for out in outbound:
                if out.coins[0].asset.get_chain() == "BTC":
                    btcOut.append(out)
            ethOut = []
            for out in outbound:
                if out.coins[0].asset.get_chain() == "ETH":
                    ethOut.append(out)
            thorchain.handle_gas(bnbOut)  # subtract gas from pool(s)
            thorchain.handle_gas(btcOut)  # subtract gas from pool(s)
            thorchain.handle_gas(ethOut)  # subtract gas from pool(s)

            # generated a snapshop picture of thorchain and bnb
            snap = Breakpoint(thorchain, bnb).snapshot(i, len(outbound))
            snaps.append(snap)
            expected = get_balance(
                i)  # get the expected balance from json file

            diff = DeepDiff(snap, expected,
                            ignore_order=True)  # empty dict if are equal
            if len(diff) > 0:
                logging.info(f"Transaction: {i} {txn}")
                logging.info(">>>>>> Expected")
                logging.info(pformat(expected))
                logging.info(">>>>>> Obtained")
                logging.info(pformat(snap))
                logging.info(">>>>>> DIFF")
                logging.info(pformat(diff))
                if not export:
                    raise Exception("did not match!")

        if export:
            with open(export, "w") as fp:
                json.dump(snaps, fp, indent=4)

        if export_events:
            with open(export_events, "w") as fp:
                json.dump(thorchain.events,
                          fp,
                          default=lambda x: x.__dict__,
                          indent=4)

        # check events against expected
        expected_events = get_events()
        for event, expected_event in zip(thorchain.events, expected_events):
            if event != expected_event:
                logging.error(f"Event Thorchain {event} \n   !="
                              f"  \nEvent Expected {expected_event}")
                if not export_events:
                    raise Exception("Events mismatch")

        if failure:
            raise Exception("Fail")
예제 #14
0
    def run(self):
        logging.info(f">>> Starting benchmark... ({self.tx_type}: {self.num})")
        logging.info(">>> setting up...")
        # seed staker
        self.mock_binance.transfer(
            Transaction(
                "BNB",
                get_alias("BNB", "MASTER"),
                get_alias("BNB", "STAKER-1"),
                [
                    Coin("BNB.BNB", self.num * 100 * Coin.ONE),
                    Coin(RUNE, self.num * 100 * Coin.ONE),
                ],
            )
        )

        # seed swapper
        self.mock_binance.transfer(
            Transaction(
                "BNB",
                get_alias("BNB", "MASTER"),
                get_alias("BNB", "USER-1"),
                [
                    Coin("BNB.BNB", self.num * 100 * Coin.ONE),
                    Coin(RUNE, self.num * 100 * Coin.ONE),
                ],
            )
        )

        if self.tx_type == "swap":
            # stake BNB
            self.mock_binance.transfer(
                Transaction(
                    "BNB",
                    get_alias("BNB", "STAKER-1"),
                    get_alias("BNB", "VAULT"),
                    [
                        Coin("BNB.BNB", self.num * 100 * Coin.ONE),
                        Coin(RUNE, self.num * 100 * Coin.ONE),
                    ],
                    memo="STAKE:BNB.BNB",
                )
            )

        time.sleep(5)  # give thorchain extra time to start the blockchain

        logging.info("<<< done.")
        logging.info(">>> compiling transactions...")
        txns = []
        memo = f"{self.tx_type}:BNB.BNB"
        for x in range(0, self.num):
            if self.tx_type == "stake":
                coins = [
                    Coin(RUNE, 10 * Coin.ONE),
                    Coin("BNB.BNB", 10 * Coin.ONE),
                ]
            elif self.tx_type == "swap":
                coins = [
                    Coin(RUNE, 10 * Coin.ONE),
                ]
            txns.append(
                Transaction(
                    "BNB",
                    get_alias("BNB", "USER-1"),
                    get_alias("BNB", "VAULT"),
                    coins,
                    memo=memo,
                )
            )

        logging.info("<<< done.")
        logging.info(">>> broadcasting transactions...")
        self.mock_binance.transfer(txns)
        logging.info("<<< done.")

        logging.info(">>> timing for thorchain...")
        start_block_height = self.thorchain_client.get_block_height()
        t1 = time.time()
        completed = 0

        pbar = tqdm(total=self.num)
        while completed < self.num:
            events = self.thorchain_client.events
            if len(events) == 0:
                time.sleep(1)
                continue
            completed = len([e for e in events if e.type == self.tx_type.lower()])
            pbar.update(completed)
            time.sleep(1)
        pbar.close()

        t2 = time.time()
        end_block_height = self.thorchain_client.get_block_height()
        total_time = t2 - t1
        total_blocks = end_block_height - start_block_height
        logging.info("<<< done.")
        logging.info(f"({self.tx_type}: {completed}")
        logging.info(f"Blocks: {total_blocks}, {total_time} seconds)")
예제 #15
0
파일: smoke.py 프로젝트: thorchain/heimdall
    def run(self):
        for i, txn in enumerate(self.txns):
            txn = Transaction.from_dict(txn)

            if self.bitcoin_reorg:
                # get block hash from bitcoin we are going to invalidate later
                if i == 14 or i == 24:
                    current_height = self.mock_bitcoin.get_block_height()
                    block_hash = self.mock_bitcoin.get_block_hash(
                        current_height)
                    logging.info(
                        f"Block to invalidate {current_height} {block_hash}")

                # now we processed some btc txs and we invalidate an older block
                # to make those txs not valid anymore and test thornode reaction
                if i == 18 or i == 28:
                    self.mock_bitcoin.invalidate_block(block_hash)
                    logging.info("Reorg triggered")

            if self.ethereum_reorg:
                # get block hash from ethereum we are going to invalidate later
                if i == 14 or i == 24:
                    current_height = self.mock_ethereum.get_block_height()
                    block_hash = self.mock_ethereum.get_block_hash(
                        current_height)
                    logging.info(
                        f"Block to invalidate {current_height} {block_hash}")

                # now we processed some eth txs and we invalidate an older block
                # to make those txs not valid anymore and test thornode reaction
                if i == 18 or i == 28:
                    self.mock_ethereum.set_block(current_height)
                    logging.info("Reorg triggered")

            logging.info(f"{i:2} {txn}")

            self.broadcast_chain(txn)
            self.broadcast_simulator(txn)

            if txn.memo == "SEED":
                continue

            self.sim_catch_up(txn)

            # check if we are verifying the results
            if self.no_verify:
                continue

            self.check_events()
            self.check_pools()

            self.check_binance()
            self.check_chain(self.bitcoin, self.mock_bitcoin,
                             self.bitcoin_reorg)
            self.check_chain(self.ethereum, self.mock_ethereum,
                             self.ethereum_reorg)

            if RUNE.get_chain() == "THOR":
                self.check_chain(self.thorchain, self.mock_thorchain, None)

            self.check_vaults()
예제 #16
0
    def test_eq(self):
        tx1 = Transaction(
            Binance.chain, "USER", "VAULT", Coin("BNB.BNB", 100), "STAKE:BNB",
        )
        tx2 = Transaction(
            Binance.chain, "USER", "VAULT", Coin("BNB.BNB", 100), "STAKE:BNB",
        )
        self.assertEqual(tx1, tx2)
        tx2.chain = "BTC"
        self.assertNotEqual(tx1, tx2)
        tx1 = Transaction(
            Binance.chain, "USER", "VAULT", [Coin("BNB.BNB", 100)], "STAKE:BNB",
        )
        tx2 = Transaction(
            Binance.chain, "USER", "VAULT", [Coin("BNB.BNB", 100)], "STAKE:BNB",
        )
        self.assertEqual(tx1, tx2)
        tx1.memo = "STAKE:BNB"
        tx2.memo = "ADD:BNB"
        self.assertNotEqual(tx1, tx2)
        tx1.memo = "STAKE"
        tx2.memo = "ADD"
        self.assertNotEqual(tx1, tx2)
        tx1.memo = ""
        tx2.memo = ""
        self.assertEqual(tx1, tx2)
        tx1.memo = "Hello"
        tx2.memo = ""
        self.assertNotEqual(tx1, tx2)
        # we ignore addresses in memo
        tx1.memo = "REFUND:ADDRESS"
        tx2.memo = "REFUND:TODO"
        self.assertNotEqual(tx1, tx2)
        # we dont ignore different assets though
        tx1.memo = "STAKE:BNB"
        tx2.memo = "STAKE:RUNE"
        self.assertNotEqual(tx1, tx2)
        tx2.memo = "STAKE:BNB"
        self.assertEqual(tx1, tx2)
        tx2.coins = [Coin("BNB.BNB", 100)]
        self.assertEqual(tx1, tx2)
        tx2.coins = [Coin("BNB.BNB", 100), Coin("RUNE", 100)]
        self.assertNotEqual(tx1, tx2)
        # different list of coins not equal
        tx1.coins = [Coin("RUNE", 200), Coin("RUNE", 100)]
        tx2.coins = [Coin("BNB.BNB", 100), Coin("RUNE", 200)]
        self.assertNotEqual(tx1, tx2)
        # coins different order tx are still equal
        tx1.coins = [Coin("RUNE", 200), Coin("BNB.BNB", 100)]
        tx2.coins = [Coin("BNB.BNB", 100), Coin("RUNE", 200)]
        self.assertEqual(tx1, tx2)
        # we ignore from / to address for equality
        tx1.to_address = "VAULT1"
        tx2.to_address = "VAULT2"
        tx1.from_address = "USER1"
        tx2.from_address = "USER2"
        self.assertNotEqual(tx1, tx2)
        # check list of transactions equality
        tx1 = Transaction(
            Binance.chain, "USER", "VAULT", [Coin("BNB.BNB", 100)], "STAKE:BNB",
        )
        tx2 = deepcopy(tx1)
        tx3 = deepcopy(tx1)
        tx4 = deepcopy(tx1)
        list1 = [tx1, tx2]
        list2 = [tx3, tx4]
        self.assertEqual(list1, list2)

        # check sort list of transactions get sorted by smallest coin
        # check list of 1 coin
        # descending order in list1
        tx1.coins = [Coin("RUNE", 200)]
        tx2.coins = [Coin("BNB.BNB", 100)]
        # ascrending order in list2
        tx3.coins = [Coin("BNB.BNB", 100)]
        tx4.coins = [Coin("RUNE", 200)]
        self.assertNotEqual(list1, list2)
        self.assertEqual(sorted(list1), list2)
        self.assertEqual(sorted(list1), sorted(list2))

        # check list of > 1 coin
        # descending order in list1
        tx1.coins = [Coin("RUNE", 200), Coin("BNB.BNB", 300)]
        tx2.coins = [Coin("BNB.BNB", 100), Coin("LOK-3C0", 500)]
        # ascrending order in list2
        tx3.coins = [Coin("BNB.BNB", 100), Coin("LOK-3C0", 500)]
        tx4.coins = [Coin("RUNE", 200), Coin("BNB.BNB", 300)]
        self.assertNotEqual(list1, list2)
        self.assertEqual(sorted(list1), list2)
        self.assertEqual(sorted(list1), sorted(list2))

        # check 1 tx with no coins
        list1 = sorted(list1)
        self.assertEqual(list1, list2)
        list1[0].coins = None
        self.assertNotEqual(list1, list2)
        list2[0].coins = None
        self.assertEqual(list1, list2)