Esempio n. 1
0
    def confirm_bitcoin_tx_online(self, hash, sender_gid, network):
        """ confirm bitcoin transaction using default online Samourai API instance

        Usage: confirm_bitcoin_tx tx_id gid network
        """

        if  network == 't' :
            url = "https://api.samourai.io/test/v2/tx/" + hash ## default testnet txtenna-server
        else :
            url = "https://api.samourai.io/v2/tx/" + hash ## default txtenna-server
        
        try:
            r = requests.get(url)
            ## print(r.text)

            while r.status_code != 200:
                sleep(60) # sleep for a minute
                r = requests.get(url)

            ## send zero-conf message back to tx sender
            rObj = TxTennaSegment('', '', tx_hash=hash, block=0)
            # arg = str(sender_gid) + ' ' + rObj.serialize_to_json()
            arg = str(sender_gid) + " Transaction " + hash + " added to the mempool."
            self.do_send_private(arg)    

            print("\nSent to GID: " + str(sender_gid) + ": Transaction " + hash + " added to the mempool.")            

            r_text = "".join(r.text.split()) # remove whitespace
            obj = json.loads(r_text)
            while not 'block' in obj.keys():
                sleep(60) # sleep for a minute
                r = requests.get(url)
                r_text = "".join(r.text.split())
                obj = json.loads(r_text)

            ## send block height message back to tx sender
            blockheight = obj['block']['height']
            rObj = TxTennaSegment('', '', tx_hash=hash, block=blockheight)
            # arg = str(sender_gid) + ' ' + rObj.serialize_to_json()
            # TODO: merkle proof for transaction
            arg = str(sender_gid) + " Transaction " + hash + " confirmed in block " + str(blockheight) + "."
            self.do_send_private(arg)

            print("\nSent to GID: " + str(sender_gid) + ": Transaction " + hash + " confirmed in block " + str(blockheight) + ".")

        except:
            traceback.print_exc()
 def test_put_new_payload_out_of_order(self, segments):
     sg0 = TxTennaSegment("1005",
                          "the payload data for segment 0",
                          tx_hash="eeeeee",
                          sequence_num=0,
                          segment_count=3)
     sg1 = TxTennaSegment("1005",
                          "the payload data for segment 1",
                          sequence_num=1)
     segments.put(sg1)
     segments.put(sg0)
     gsg = segments.get("1005")
     gsg2 = segments.get_by_transaction_id("eeeeee")
     assert gsg2[0].payload_id == gsg[0].payload_id
     assert len(gsg) == 2
     assert gsg[0].sequence_num == 0
     assert gsg[1].sequence_num == 1
Esempio n. 3
0
 def test_deserialize_non_first_from_json(self):
     json_ser = '{"i": "1000", "t": "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc", "c": 1}'
     segment = TxTennaSegment.deserialize_from_json(json_ser)
     assert segment.payload_id == "1000"
     assert segment.sequence_num == 1
     assert segment.segment_count is None
     assert segment.testnet is False
     assert segment.payload == "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc"
Esempio n. 4
0
 def test_constructor_defaults(self):
     segment = TxTennaSegment("1000", "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc")
     assert segment.tx_hash is None
     assert segment.payload_id == "1000"
     assert segment.payload == "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc"
     assert segment.sequence_num == 0
     assert not segment.testnet
     assert segment.segment_count is None
 def test_put_new_payload(self, segments):
     sg = TxTennaSegment("1004",
                         "the payload data for segment 0",
                         tx_hash="789fff",
                         sequence_num=0,
                         segment_count=3)
     segments.put(sg)
     gsg = segments.get("1004")
     assert gsg is not None
     assert gsg[0].tx_hash == "789fff"
def segments():
    payload1seg1 = TxTennaSegment("1000",
                                  "ra]?=rb3hXB09d)awc6WatLS8ir",
                                  tx_hash="abc123",
                                  sequence_num=0,
                                  segment_count=3,
                                  testnet=False)
    payload1seg2 = TxTennaSegment("1000",
                                  "lUG[Cv}xE)z/M$szxIn^x(mX",
                                  sequence_num=1,
                                  testnet=False)
    payload1seg3 = TxTennaSegment("1000",
                                  "z!pa<wN/T@wfsiEx(4ZgBrCglAV^XSzFKp",
                                  sequence_num=2,
                                  testnet=False)

    payload2seg1 = TxTennaSegment("1001",
                                  "ra]?=B9z5kz6iLlazts{wmYo]Bz(wiA+6klB-N",
                                  tx_hash="def456",
                                  sequence_num=0,
                                  segment_count=2,
                                  testnet=False)

    payload3seg2 = TxTennaSegment(
        "1002",
        "vS==nBzbkdxLzKfz/QaCz!pb7x<(9av%8*jwO#0(wPF#dB0b7qy?$kjw/$M6wNP7ZwPF#jw/#hevrrSlA=(CB",
        sequence_num=1,
        testnet=False)

    # payload3seg1 = "ra]?=v}xL1A:-=bvQTd&az(mxBrC47aARTDB97#7az#ataARJAwmYjUB7DFoxK@q@B-IIlzEW@y"

    storage = SegmentStorage()

    storage.put(payload1seg1)
    storage.put(payload1seg2)
    storage.put(payload1seg3)
    storage.put(payload2seg1)
    storage.put(payload3seg2)
    return storage
Esempio n. 7
0
    def broadcast_message_files(self, directory, filenames):
        for filename in filenames:
            print("Broadcasting ",directory+"/"+filename)
            f = open(directory+"/"+filename,'r')
            message_data = f.read()
            f.close
            
            ## binary to ascii encoding and strip out newlines
            encoded = zlib.compress(message_data, 9).encode('base64').replace('\n','')
            print("[\n" + encoded.decode() + "\n]")

            gid = self.api_thread.gid.gid_val
            segments = TxTennaSegment.tx_to_segments(gid, encoded, filename, str(self.messageIdx), "d", False)
            for seg in segments :
                self.do_send_broadcast(seg.serialize_to_json())
                sleep(10)
            self.messageIdx = (self.messageIdx+1) % 9999
Esempio n. 8
0
    def do_mesh_broadcast_rawtx(self, rem):
        """ 
        Broadcast the raw hex of a Bitcoin transaction and its transaction ID over mainnet or testnet. 
        A local copy of txtenna-server must be configured to support the selected network.

        Usage: mesh_broadcast_tx RAW_HEX TX_ID NETWORK(m|t)

        eg. txTenna> mesh_broadcast_rawtx 01000000000101bf6c3ed233e8700b42c1369993c2078780015bab7067b9751b7f49f799efbffd0000000017160014f25dbf0eab0ba7e3482287ebb41a7f6d361de6efffffffff02204e00000000000017a91439cdb4242013e108337df383b1bf063561eb582687abb93b000000000017a9148b963056eedd4a02c91747ea667fc34548cab0848702483045022100e92ce9b5c91dbf1c976d10b2c5ed70d140318f3bf2123091d9071ada27a4a543022030c289d43298ca4ca9d52a4c85f95786c5e27de5881366d9154f6fe13a717f3701210204b40eff96588033722f487a52d39a345dc91413281b31909a4018efb330ba2600000000 94406beb94761fa728a2cde836ca636ecd3c51cbc0febc87a968cb8522ce7cc1 m
        """

        ## TODO: test Z85 binary encoding and add as an option
        (strHexTx, strHexTxHash, network) = rem.split(" ")
        gid = self.api_thread.gid.gid_val
        segments = TxTennaSegment.tx_to_segments(gid, strHexTx, strHexTxHash, str(self.messageIdx), network, False)
        for seg in segments :
            self.do_send_broadcast(seg.serialize_to_json())
            sleep(10)
        self.messageIdx = (self.messageIdx+1) % 9999
Esempio n. 9
0
    def handle_cbor_message(self, sender_gid, protocol_msg):

        # TODO: 1a) concatonate segments and send as new transaction to block explorer 
        # TODO: 1b) send acknowledgement back to Signal Mesh as a text message
        # TODO: 2a) monitor for transaction to be confirmed in a block
        # TODO: 2b) send blockchain confirmation back to Signal Mesh as a text message

        txtenna_json = self.cbor_to_txtenna_json(protocol_msg)
        segment = TxTennaSegment.deserialize_from_json(txtenna_json)
        self.segment_storage.put(segment)
        network = self.segment_storage.get_network(segment.payload_id)

        ## process incoming transaction confirmation from another server
        if (segment.block != None):
            if (segment.block > 0):
                print("\nTransaction " + segment.payload_id + " confirmed in block " + str(segment.block))
            elif (segment.block is 0):
                print("\nTransaction " + segment.payload_id + " added to the the mem pool")
        elif (network is 'd'):
            ## process message data
            if (self.segment_storage.is_complete(segment.payload_id)):
                filename = self.segment_storage.get_transaction_id(segment.payload_id)
                t = Thread(target=self.receive_message_from_gateway, args=(filename,))
                t.start()
        else:
            ## process incoming tx segment
            if not self.local_bitcoind :
                headers = {u'content-type': u'application/json'}
                url = "https://api.samouraiwallet.com/v2/txtenna/segments" ## default txtenna-server
                r = requests.post(url, headers= headers, data=txtenna_json)
                print(r.text)

            if (self.segment_storage.is_complete(segment.payload_id)):
                # sender_gid = message.sender.gid_val
                tx_id = self.segment_storage.get_transaction_id(segment.payload_id)

                ## check for confirmed transaction in a new thread
                if (self.local_bitcoind) :
                    t = Thread(target=self.confirm_bitcoin_tx_local, args=(tx_id, sender_gid))
                else :
                    t = Thread(target=self.confirm_bitcoin_tx_online, args=(tx_id, sender_gid, network))
                t.start()
Esempio n. 10
0
    def handle_message(self, message):
        """ handle a txtenna message received over the mesh network

        Usage: handle_message message
        """
        payload = str(message.payload.message)
        print("received transaction payload: " + payload)

        segment = TxTennaSegment.deserialize_from_json(payload)
        self.segment_storage.put(segment)
        network = self.segment_storage.get_network(segment.payload_id)

        ## process incoming transaction confirmation from another server
        if (segment.block > 0):
            print("\nTransaction " + segment.payload_id + " confirmed in block " + str(segment.block))
        elif (segment.block is 0):
            print("\nTransaction " + segment.payload_id + " added to the the mem pool")
        elif (network is 'd'):
            ## process message data
            if (self.segment_storage.is_complete(segment.payload_id)):
                filename = self.segment_storage.get_transaction_id(segment.payload_id)
                t = Thread(target=self.receive_message_from_gateway, args=(filename,))
                t.start()
        else:
            ## process incoming tx segment
            if not self.local :
                headers = {u'content-type': u'application/json'}
                url = "https://api.samouraiwallet.com/v2/txtenna/segments" ## default txtenna-server
                r = requests.post(url, headers= headers, data=payload)
                print(r.text)

            if (self.segment_storage.is_complete(segment.payload_id)):
                sender_gid = message.sender.gid_val
                tx_id = self.segment_storage.get_transaction_id(segment.payload_id)

                ## check for confirmed transaction in a new thread
                if (self.local) :
                    t = Thread(target=self.confirm_bitcoin_tx_local, args=(tx_id, sender_gid))
                else :
                    t = Thread(target=self.confirm_bitcoin_tx_online, args=(tx_id, sender_gid, network))
                t.start()
Esempio n. 11
0
 def test_segment_json_first_is_valid_explicit_zero_sequence(self):
     json_ser = '{"i": "1000", "t": "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc", "s": 1, "h": "123abc", "c": 0}'
     json_obj = json.loads(json_ser)
     assert TxTennaSegment.segment_json_is_valid(json_obj)
Esempio n. 12
0
    def confirm_bitcoin_tx_local(self, hash, sender_gid):
        """ 
        Confirm bitcoin transaction using local bitcoind instance

        Usage: confirm_bitcoin_tx tx_id gid
        """ 

        ## send transaction to local bitcond
        segments = self.segment_storage.get_by_transaction_id(hash)
        raw_tx = self.segment_storage.get_raw_tx(segments)

        ## pass hex string converted to bytes
        try :
            proxy1 = bitcoin.rpc.Proxy()
            raw_tx_bytes = x(raw_tx)
            tx = CMutableTransaction.stream_deserialize(BytesIO(raw_tx_bytes))
            r1 = proxy1.sendrawtransaction(tx)
        except :
            print("Invalid Transaction! Could not send to network.")
            return

        ## try for 30 minutes to confirm the transaction
        for n in range(0, 30) :
            try :
                proxy2 = bitcoin.rpc.Proxy()
                r2 = proxy2.getrawtransaction(r1, True)

                ## send zero-conf message back to tx sender
                confirmations = r2.get('confirmations', 0)
                rObj = TxTennaSegment('', '', tx_hash=hash, block=confirmations)
                arg = str(sender_gid) + ' ' + rObj.serialize_to_json()
                self.do_send_private(arg)

                print("\nSent to GID: " + str(sender_gid) + ": Transaction " + hash + " added to the mempool.")
                break      
            except IndexError:
                ## tx_id not yet in the global mempool, sleep for a minute and then try again
                sleep(60)
                continue      
            
            ## wait for atleast one confirmation
            for m in range(0, 30):
                sleep(60) # sleep for a minute
                try :
                    proxy3= bitcoin.rpc.Proxy()
                    r3 = proxy3.getrawtransaction(r1, True)
                    confirmations = r3.get('confirmations', 0)
                    ## keep waiting until 1 or more confirmations
                    if confirmations > 0:
                        break
                except :
                    ## unknown RPC error, but keep trying
                    traceback.print_exc()

            if confirmations > 0 :
                ## send confirmations message back to tx sender if confirmations > 0
                rObj = TxTennaSegment('', '', tx_hash=hash, block=confirmations)
                arg = str(sender_gid) + ' ' + rObj.serialize_to_json()
                self.do_send_private(arg)
                print("\nSent to GID: " + str(sender_gid) + ", Transaction " + hash + " confirmed in " + str(confirmations) + " blocks.")
            else :
                print("\CTransaction from GID: " + str(sender_gid) + ", Transaction " + hash + " not confirmed after 30 minutes.")
Esempio n. 13
0
 def test_segment_json_is_invalid_non_zero_sequence_with_segment_count(self):
     json_ser = '{"i": "1000", "t": "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc", "c": 1, "s": 2}'
     json_obj = json.loads(json_ser)
     assert not TxTennaSegment.segment_json_is_valid(json_obj)
Esempio n. 14
0
 def test_deserialize_invalid_segment_raises_exception(self):
     json_ser = '{"i": "1000", "t": "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc", "s": 1, "h": "123abc", "c": 1}'
     with pytest.raises(AttributeError):
         TxTennaSegment.deserialize_from_json(json_ser)
Esempio n. 15
0
    def test_serialize_testnet_segment(self):
        segment = TxTennaSegment("1000", "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc",
                                 tx_hash="123abc", testnet=True, segment_count=2, sequence_num=1)

        json_ser = segment.serialize_to_json()
        assert json_ser == '{"i": "1000", "t": "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc", "c": 1, "n": "t"}'
Esempio n. 16
0
    def test_serialize_first_segment(self):
        segment = TxTennaSegment("1000", "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc",
                                 tx_hash="123abc", testnet=False, segment_count=1, sequence_num=0)

        json_ser = segment.serialize_to_json()
        assert json_ser == '{"i": "1000", "t": "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc", "s": 1, "h": "123abc"}'
Esempio n. 17
0
    def test_repr(self):
        segment = TxTennaSegment("1000", "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc",
                                 tx_hash="123abc", testnet=False, segment_count=1, sequence_num=0)

        segment_repr = repr(segment)
        assert segment_repr == '{"i": "1000", "t": "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc", "s": 1, "h": "123abc"}'
Esempio n. 18
0
 def test_str(self):
     segment = TxTennaSegment("1000", "w]8f<vRG}fayY4]vRG}fayYm#vRG}fayYnc",
                              tx_hash="123abc", testnet=False, segment_count=1, sequence_num=0)
     segment_str = str(segment)
     assert segment_str == "Tx 123abc Part 0"