#!/usr/bin/env python3
# Copyright (c) 2015-2021 The Dash Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.messages import COIN, COutPoint, CTransaction, CTxIn, CTxOut, ToHex
from test_framework.script import CScript, OP_CAT, OP_DROP, OP_TRUE
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error, get_bip9_status, satoshi_round

'''
feature_dip0020_activation.py

This test checks activation of DIP0020 opcodes
'''

DISABLED_OPCODE_ERROR = "non-mandatory-script-verify-flag (Attempted to use a disabled opcode)"


class DIP0020ActivationTest(BitcoinTestFramework):
    def set_test_params(self):
        self.num_nodes = 1
        self.extra_args = [["-acceptnonstdtxn=1"]]

    def skip_test_if_missing_module(self):
        self.skip_if_no_wallet()

    def run_test(self):
        self.node = self.nodes[0]
        self.relayfee = satoshi_round(self.nodes[0].getnetworkinfo()["relayfee"])

        # We should have some coins already
        utxos = self.node.listunspent()
        assert len(utxos) > 0

        # Lock some coins using disabled opcodes
        utxo = utxos[len(utxos) - 1]
        value = int(satoshi_round(utxo["amount"] - self.relayfee) * COIN)
        tx = CTransaction()
        tx.vin.append(CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"])))
        tx.vout.append(CTxOut(value, CScript([b'1', b'2', OP_CAT])))
        tx_signed_hex = self.node.signrawtransaction(ToHex(tx))["hex"]
        txid = self.node.sendrawtransaction(tx_signed_hex)

        # This tx should be completely valid, should be included in mempool and mined in the next block
        assert txid in set(self.node.getrawmempool())
        self.node.generate(1)
        assert txid not in set(self.node.getrawmempool())

        # Create spending tx
        value = int(value - self.relayfee * COIN)
        tx0 = CTransaction()
        tx0.vin.append(CTxIn(COutPoint(int(txid, 16), 0)))
        tx0.vout.append(CTxOut(value, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
        tx0.rehash()
        tx0_hex = ToHex(tx0)

        # This tx isn't valid yet
        assert_equal(get_bip9_status(self.nodes[0], 'dip0020')['status'], 'locked_in')
        assert_raises_rpc_error(-26, DISABLED_OPCODE_ERROR, self.node.sendrawtransaction, tx0_hex)

        # Generate enough blocks to activate DIP0020 opcodes
        self.node.generate(98)
        assert_equal(get_bip9_status(self.nodes[0], 'dip0020')['status'], 'active')

        # Still need 1 more block for mempool to accept new opcodes
        assert_raises_rpc_error(-26, DISABLED_OPCODE_ERROR, self.node.sendrawtransaction, tx0_hex)
        self.node.generate(1)

        # Should be spendable now
        tx0id = self.node.sendrawtransaction(tx0_hex)
        assert tx0id in set(self.node.getrawmempool())


if __name__ == '__main__':
    DIP0020ActivationTest().main()
