text: #!/usr/bin/env python3
  # Copyright (c) 2018 The Beenode 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.mininode import *
  from test_framework.test_framework import BitcoinTestFramework
  from test_framework.util import *
  from time import *
  
  '''
  multikeysporks.py
  
  Test logic for several signer keys usage for spork broadcast.
  
  We set 5 possible keys for sporks signing and set minimum 
  required signers to 3. We check 1 and 2 signers can't set the spork 
  value, any 3 signers can change spork value and other 3 signers
  can change it again.
  '''
  
  
  class MultiKeySporkTest(BitcoinTestFramework):
      def __init__(self):
          super().__init__()
          self.num_nodes = 5
          self.setup_clean_chain = True
          self.is_network_split = False
  
      def setup_network(self):
          self.nodes = []
  
          # secret(base58): 931wyuRNVYvhg18Uu9bky5Qg1z4QbxaJ7fefNBzjBPiLRqcd33F
          # keyid(hex): 60f0f57f71f0081f1aacdd8432340a33a526f91b
          # address(base58): yNsMZhEhYqv14TgdYb1NS2UmNZjE8FSJxa
  
          # secret(base58): 91vbXGMSWKGHom62986XtL1q2mQDA12ngcuUNNe5NfMSj44j7g3
          # keyid(hex): 43dff2b09de2f904f688ec14ee6899087b889ad0
          # address(base58): yfLSXFfipnkgYioD6L8aUNyfRgEBuJv48h
  
          # secret(base58): 92bxUjPT5AhgXuXJwfGGXqhomY2SdQ55MYjXyx9DZNxCABCSsRH
          # keyid(hex): d9aa5fa00cce99101a4044e65dc544d1579890de
          # address(base58): ygcG5S2pQz2U1UAaHvU6EznKZW7yapKMA7
  
          # secret(base58): 934yPXiVGf4RCY2qTs2Bt5k3TEtAiAg12sMxCt8yVWbSU7p3fuD
          # keyid(hex): 0b23935ce0bea3b997a334f6fa276c9fa17687b2
          # address(base58): ycbRQWbovrhQMTuxg9p4LAuW5SCMAKqPrn
  
          # secret(base58): 92Cxwia363Wg2qGF1fE5z4GKi8u7r1nrWQXdtsj2ACZqaDPSihD
          # keyid(hex): 1d1098b2b1f759b678a0a7a098637a9b898adcac
          # address(base58): yc5TGfcHYoLCrcbVy4umsiDjsYUn39vLui
  
          self.nodes.append(start_node(0, self.options.tmpdir,
                                       ["-sporkkey=931wyuRNVYvhg18Uu9bky5Qg1z4QbxaJ7fefNBzjBPiLRqcd33F",
                                        "-sporkaddr=ygcG5S2pQz2U1UAaHvU6EznKZW7yapKMA7",
                                        "-sporkaddr=yfLSXFfipnkgYioD6L8aUNyfRgEBuJv48h",
                                        "-sporkaddr=yNsMZhEhYqv14TgdYb1NS2UmNZjE8FSJxa",
                                        "-sporkaddr=ycbRQWbovrhQMTuxg9p4LAuW5SCMAKqPrn",
                                        "-sporkaddr=yc5TGfcHYoLCrcbVy4umsiDjsYUn39vLui",
                                        "-minsporkkeys=3"]))
          self.nodes.append(start_node(1, self.options.tmpdir,
                                       ["-sporkkey=91vbXGMSWKGHom62986XtL1q2mQDA12ngcuUNNe5NfMSj44j7g3",
                                        "-sporkaddr=ygcG5S2pQz2U1UAaHvU6EznKZW7yapKMA7",
                                        "-sporkaddr=yfLSXFfipnkgYioD6L8aUNyfRgEBuJv48h",
                                        "-sporkaddr=yNsMZhEhYqv14TgdYb1NS2UmNZjE8FSJxa",
                                        "-sporkaddr=ycbRQWbovrhQMTuxg9p4LAuW5SCMAKqPrn",
                                        "-sporkaddr=yc5TGfcHYoLCrcbVy4umsiDjsYUn39vLui",
                                        "-minsporkkeys=3"]))
          self.nodes.append(start_node(2, self.options.tmpdir,
                                       ["-sporkkey=92bxUjPT5AhgXuXJwfGGXqhomY2SdQ55MYjXyx9DZNxCABCSsRH",
                                        "-sporkaddr=ygcG5S2pQz2U1UAaHvU6EznKZW7yapKMA7",
                                        "-sporkaddr=yfLSXFfipnkgYioD6L8aUNyfRgEBuJv48h",
                                        "-sporkaddr=yNsMZhEhYqv14TgdYb1NS2UmNZjE8FSJxa",
                                        "-sporkaddr=ycbRQWbovrhQMTuxg9p4LAuW5SCMAKqPrn",
                                        "-sporkaddr=yc5TGfcHYoLCrcbVy4umsiDjsYUn39vLui",
                                        "-minsporkkeys=3"]))
          self.nodes.append(start_node(3, self.options.tmpdir,
                                       ["-sporkkey=934yPXiVGf4RCY2qTs2Bt5k3TEtAiAg12sMxCt8yVWbSU7p3fuD",
                                        "-sporkaddr=ygcG5S2pQz2U1UAaHvU6EznKZW7yapKMA7",
                                        "-sporkaddr=yfLSXFfipnkgYioD6L8aUNyfRgEBuJv48h",
                                        "-sporkaddr=yNsMZhEhYqv14TgdYb1NS2UmNZjE8FSJxa",
                                        "-sporkaddr=ycbRQWbovrhQMTuxg9p4LAuW5SCMAKqPrn",
                                        "-sporkaddr=yc5TGfcHYoLCrcbVy4umsiDjsYUn39vLui",
                                        "-minsporkkeys=3"]))
          self.nodes.append(start_node(4, self.options.tmpdir,
                                       ["-sporkkey=92Cxwia363Wg2qGF1fE5z4GKi8u7r1nrWQXdtsj2ACZqaDPSihD",
                                        "-sporkaddr=ygcG5S2pQz2U1UAaHvU6EznKZW7yapKMA7",
                                        "-sporkaddr=yfLSXFfipnkgYioD6L8aUNyfRgEBuJv48h",
                                        "-sporkaddr=yNsMZhEhYqv14TgdYb1NS2UmNZjE8FSJxa",
                                        "-sporkaddr=ycbRQWbovrhQMTuxg9p4LAuW5SCMAKqPrn",
                                        "-sporkaddr=yc5TGfcHYoLCrcbVy4umsiDjsYUn39vLui",
                                        "-minsporkkeys=3"]))
          # connect nodes at start
          for i in range(0, 5):
              for j in range(i, 5):
                  connect_nodes(self.nodes[i], j)
  
      def get_test_spork_state(self, node):
          info = node.spork('show')
          # use InstantSend spork for tests
          return info['SPORK_2_INSTANTSEND_ENABLED']
  
      def set_test_spork_state(self, node, value):
          # use InstantSend spork for tests
          node.spork('SPORK_2_INSTANTSEND_ENABLED', value)
  
      def wait_for_test_spork_state(self, node, value):
          start = time()
          got_state = False
          while True:
              if self.get_test_spork_state(node) == value:
                  got_state = True
                  break
              if time() > start + 10:
                  break
              sleep(0.1)
          return got_state
  
      def run_test(self):
          # check test spork default state
          for node in self.nodes:
              assert(self.get_test_spork_state(node) == 0)
  
          set_mocktime(get_mocktime() + 1)
          set_node_times(self.nodes, get_mocktime())
          # first and second signers set spork value
          self.set_test_spork_state(self.nodes[0], 1)
          self.set_test_spork_state(self.nodes[1], 1)
          # spork change requires at least 3 signers
          for node in self.nodes:
              assert(not self.wait_for_test_spork_state(node, 1))
  
          # third signer set spork value
          self.set_test_spork_state(self.nodes[2], 1)
          # now spork state is changed
          for node in self.nodes:
              assert(self.wait_for_test_spork_state(node, 1))
  
          set_mocktime(get_mocktime() + 1)
          set_node_times(self.nodes, get_mocktime())
          # now set the spork again with other signers to test
          # old and new spork messages interaction
          self.set_test_spork_state(self.nodes[2], 2)
          self.set_test_spork_state(self.nodes[3], 2)
          self.set_test_spork_state(self.nodes[4], 2)
          for node in self.nodes:
              assert(self.wait_for_test_spork_state(node, 2))
  
  
  if __name__ == '__main__':
      MultiKeySporkTest().main()
  