예제 #1
0
def sometx():
    secret = "A" * 32
    public = rscoin.Key(secret, public=False).id()
    directory = [(public, "127.0.0.1", 8080)]

    factory = RSCFactory(secret, directory, None)

    # Build one transaction
    k1 = rscoin.Key(urandom(32), public=False)
    k2 = rscoin.Key(urandom(32), public=False)

    tx1 = rscoin.Tx([], [rscoin.OutputTx(k1.id(), 100)])
    tx2 = rscoin.Tx([], [rscoin.OutputTx(k2.id(), 150)])

    tx3 = rscoin.Tx([rscoin.InputTx(tx1.id(), 0),
                     rscoin.InputTx(tx2.id(), 0)],
                    [rscoin.OutputTx(k1.id(), 250)])

    for kv, vv in tx1.get_utxo_out_entries() + tx2.get_utxo_out_entries():
        factory.db[kv] = vv

    # Run the protocol
    instance = factory.buildProtocol(None)
    tr = StringTransport()
    instance.makeConnection(tr)

    return (factory, instance, tr), (k1, k2, tx1, tx2, tx3)
예제 #2
0
def test_TxCommit(sometx):
    (factory, instance, tr), (k1, k2, tx1, tx2, tx3) = sometx

    # Check the list is up to date
    for ik in tx3.get_utxo_in_keys():
        assert ik in factory.db

    #data1 = map(b64encode, [tx3.serialize(), tx1.serialize(), tx2.serialize(),
    #            k1.export()[0], k2.export()[0], k1.sign(tx3.id()), k2.sign(tx3.id())])

    #H = sha256(" ".join(data1)).digest()

    #data = " ".join(["Query", str(len(data1))] + data1)
    H, data, dataCore = package_query(tx3, [tx1, tx2], [k1, k2])

    instance.lineReceived(data)
    response = tr.value()

    k, s = map(b64decode, response.split(" ")[1:])
    k2 = rscoin.Key(k)
    assert factory.key.verify(H, s)
    assert k2.verify(H, s)

    ## Now we test the Commit
    tr.clear()
    # data = " ".join(["Commit", str(len(dataCore))] + dataCore + map(b64encode, [k, s]))

    data = package_commit(dataCore, [(k, s)])
    instance.lineReceived(data)

    flag, pub, sig = tr.value().split(" ")
    assert factory.key.verify(tx3.id(), b64decode(sig))

    k3 = rscoin.Key(b64decode(pub))
    assert k3.verify(tx3.id(), b64decode(sig))
예제 #3
0
def test_online_issue(sometx):

    (factory, instance, tr), (k1, k2, tx1, tx2, tx3) = sometx

    kIssue = rscoin.Key(file("secret.key").read(),
                        False)  # rscoin.Key(urandom(32), public=False)
    pubIssue = kIssue.pub.export()
    factory.special_key = kIssue.id()
    print "Public ID: %s" % b64encode(factory.special_key)

    # Build a new coin
    k1 = rscoin.Key(urandom(32), public=False)
    k1pub = k1.pub.export()
    tx3 = rscoin.Tx([], [rscoin.OutputTx(k1.id(), 250)])
    sig1 = kIssue.sign(tx3.id())

    ## Now we test the Commit
    #data1 = map(b64encode, [tx3.serialize(), pubIssue, sig1])
    #data = " ".join(["Commit", str(len(data1))] + data1)

    data = package_issue(tx3, [kIssue, sig1])

    # test on fake
    tr.clear()
    instance.lineReceived(data)

    # Ensure the returned signatures check
    ret, pub, sig = tr.value().split(" ")
    assert ret == "OK"
    kx = rscoin.Key(b64decode(pub))
    assert kx.verify(tx3.id(), b64decode(sig))

    # Second time:
    tr.clear()
    instance.lineReceived(data)
    ret2, pub2, sig2 = tr.value().split(" ")
    assert ret2 == ret
    assert pub2 == pub
    assert sig != sig2
    assert kx.verify(tx3.id(), b64decode(sig2))

    import socket
    HOST = master_ip  # The remote host
    PORT = 8080  # The same port as used by the server
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    s.sendall(data + '\r\n')

    data_rec = ''
    data_rec += s.recv(4096)
    print "Data: '%s'" % data_rec
    s.close()

    # Ensure the returned signatures check
    ret, pub, sig = data_rec.split(" ")
    assert ret == "OK"
    kx = rscoin.Key(b64decode(pub))
    assert kx.verify(tx3.id(), b64decode(sig))
예제 #4
0
def msg_mass():

    secret = "A" * 32
    public = rscoin.Key(secret, public=False).id()
    directory = [(public, "127.0.0.1", 8080)]

    factory = RSCFactory(secret, directory, None)

    # Run the protocol
    instance = factory.buildProtocol(None)
    tr = StringTransport()
    instance.makeConnection(tr)

    sometx = (factory, instance, tr)

    # Make special keys for making coins
    secret_special = "KEYSPECIAL"
    public_special = rscoin.Key(secret_special, public=False).pub.export()

    # Define a number of keys
    all_keys = []
    secret = "KEYX"
    public = rscoin.Key(secret, public=False).id()

    directory = [(public, "127.0.0.1", 8080)]

    # Make a mass of transactions
    k1 = rscoin.Key(urandom(32), public=False)
    k2 = rscoin.Key(urandom(32), public=False)

    all_tx = []

    for _ in range(1000):

        tx1 = rscoin.Tx([], [rscoin.OutputTx(k1.id(), 100)])
        tx2 = rscoin.Tx([], [rscoin.OutputTx(k2.id(), 150)])

        tx3 = rscoin.Tx(
            [rscoin.InputTx(tx1.id(), 0),
             rscoin.InputTx(tx2.id(), 0)], [rscoin.OutputTx(k1.id(), 250)])

        all_tx += [([tx1, tx2], tx3)]

    for intx, _ in all_tx:
        for tx in intx:
            for kv, vv in tx.get_utxo_out_entries():
                factory.db[kv] = vv

    mesages_q = []

    for ([tx1, tx2], tx3) in all_tx:
        H, data, core = package_query(tx3, [tx1, tx2], [k1, k2])
        mesages_q += [(tx3, data, core)]

    return (sometx, mesages_q)
예제 #5
0
def test_factory():
    secret = "A" * 32
    public = rscoin.Key(secret, public=False).id()
    directory = [(public, "127.0.0.1", 8080)]

    factory = RSCFactory(secret, directory, None)
    assert os.path.exists(factory.dbname + ".db") or os.path.exists(
        factory.dbname)
예제 #6
0
def test_setup():
    data = """{
        "special": "AmodBjXyo2bVqyi1h0e5Kf8hSbGCmalnbF8YwJ0=",
        "directory": [ ["A/Sw7CRkoXzB2O0A3WfPMSDIbv/pOxd5Co3u9kM=", "127.0.0.1", 8080] ] 
    }"""

    stuff = load_setup(data)

    secret = "hello1"
    special = "special"
    directory = stuff["directory"]

    public = rscoin.Key(secret, public=False).pub.export()
    print("\nPublic: %s" % b64encode(public))  # , b64decode

    public_special = rscoin.Key(special, public=False).pub.export()
    print("Public (special): %s" % b64encode(public_special))  # , b64decode

    assert public == directory[0][0]
    assert public_special == stuff["special"]
예제 #7
0
def keys():
    if "rsdir" not in env:
        secret = file("secret.key").read()
        public = rscoin.Key(secret, public=False)
        pid = b64encode(public.id())

        env["rsdir"] = {"special": pid, "directory": []}

    [_, host] = env.host_string.split("@")
    with cd('/home/ubuntu/projects/rscoin'):
        run('touch secret.key')
        run('rm secret.key')
        result = run('python derivekey.py --store')
        [_, key] = result.strip().split()

        kid = b64encode(rscoin.Key(b64decode(key)).id())
        env["rsdir"]["directory"] += [[kid, host, 8080]]

    from json import dumps
    file("directory.conf", "w").write(dumps(env["rsdir"]))
예제 #8
0
def test_TxCommit_Issued(sometx):
    (factory, instance, tr), (k1, k2, tx1, tx2, tx3) = sometx

    kIssue = rscoin.Key(urandom(32), public=False)
    pubIssue = kIssue.export()[0]

    factory.special_key = kIssue.id()  # Asssign this as the special key

    tx3 = rscoin.Tx([], [rscoin.OutputTx(k1.id(), 250)])

    sig1 = kIssue.sign(tx3.id())
    assert tx3.check_transaction_utxo([], [pubIssue], [sig1], kIssue.id())
    assert tx3.check_transaction([], [pubIssue], [sig1], kIssue.id())

    ## Now we test the Commit

    # Ensure the entries are not in before sending message
    for k, v in tx3.get_utxo_out_entries():
        assert k not in factory.db

    # Send message
    tr.clear()

    data = package_issue(tx3, [kIssue, sig1])

    instance.lineReceived(data)

    # Ensure the returned signatures check
    ret, pub, sig = tr.value().split(" ")
    assert ret == "OK"
    kx = rscoin.Key(b64decode(pub))
    assert kx.verify(tx3.id(), b64decode(sig))

    # Ensure the entries are now in
    for k, v in tx3.get_utxo_out_entries():
        assert factory.db[k] == v
예제 #9
0
파일: rsc.py 프로젝트: dazhxu/rscoin
            def r_process(results):
                for msg in results:
                    parsed = unpackage_commit_response(msg)
                    if parsed[0] != "OK":
                        raise Exception("Response not OK.")

                    pub, sig = parsed[1:]
                    kx = rscoin.Key(pub)

                    if not (kx.verify(tx.id(), sig) and kx.id() in auths):
                        raise Exception("Invalid Signature.")

                    auths.remove(kx.id())

                active = ActiveTx("activetx.log", keys)
                active.add(tx_ser)
                active.save(reactor)

                print " ".join(core)
예제 #10
0
    def __init__(self, secret, directory, special_key, conf_dir=None, N=3):
        """ Initialize the RSCoin server"""
        self.special_key = special_key
        self.key = rscoin.Key(secret, public=False)
        self.directory = sorted(directory)
        keyID = self.key.id()[:10]
        self.N = N

        # Open the databases
        self.dbname = 'keys-%s' % hexlify(keyID)
        self.logname = 'log-%s' % hexlify(keyID)

        if conf_dir:
            self.dbname = join(conf_dir, self.dbname)
            self.logname = join(conf_dir, self.logname)

        if RSCFactory._sync:
            self.db = dbm.open(self.dbname, 'c')
            self.log = dbm.open(self.logname, 'c')
        else:
            self.db = {}
            self.log = {}
예제 #11
0
def test_multiple():

    import os
    try:
        os.mkdir("testscratch")
    except:
        pass

    # Make special keys for making coins
    secret_special = "KEYSPECIAL"
    public_special = rscoin.Key(secret_special, public=False).id()

    # Define a number of keys
    all_keys = []
    for x in range(100):
        secret = "KEY%s" % x
        public = rscoin.Key(secret, public=False).id()
        all_keys += [(public, secret)]

    # Make up the directory
    directory = []
    for x, (pub, _) in enumerate(all_keys):
        directory += [(pub, "127.0.0.1", 8080 + x)]

    # Build the factories
    factories = {}
    for pub, sec in all_keys:
        factory = RSCFactory(sec,
                             directory,
                             public_special,
                             conf_dir="testscratch",
                             N=5)
        factories[pub] = factory

    # Make a mass of transactions
    k1 = rscoin.Key(urandom(32), public=False)
    k2 = rscoin.Key(urandom(32), public=False)

    all_tx_in = []
    all_tx_out = []

    for _ in range(10):

        tx1 = rscoin.Tx([], [rscoin.OutputTx(k1.id(), 100)])
        tx2 = rscoin.Tx([], [rscoin.OutputTx(k2.id(), 150)])

        tx3 = rscoin.Tx(
            [rscoin.InputTx(tx1.id(), 0),
             rscoin.InputTx(tx2.id(), 0)], [rscoin.OutputTx(k1.id(), 250)])

        all_tx_in += [tx1, tx2]
        all_tx_out += [tx3]

    print "Lens: all_tx_in: %s all_tx_out: %s" % (len(all_tx_in),
                                                  len(all_tx_out))

    for tx in all_tx_in:
        for kv, vv in tx.get_utxo_out_entries():
            for f in factories.values():
                f.db[kv] = vv

    data = (tx3, [tx1.serialize(),
                  tx2.serialize()], [k1.export()[0],
                                     k2.export()[0]],
            [k1.sign(tx3.id()), k2.sign(tx3.id())])

    # Put the transaction through
    total = 0

    [kid1, kid2] = tx3.get_utxo_in_keys()
    au1 = get_authorities(directory, kid1, N=5)
    au2 = get_authorities(directory, kid2, N=5)

    auxes = set(au1 + au2)

    assert len(auxes) == 10
    for aid in auxes:
        assert isinstance(aid, str) and len(aid) == 32
        assert aid in factories

    H, msg, dataCore = package_query(tx3, [tx1, tx2], [k1, k2])

    xset = []
    rss = []
    for kid, f in factories.iteritems():
        # resp = f.process_TxQuery(data)

        instance = f.buildProtocol(None)
        tr = StringTransport()
        instance.makeConnection(tr)
        instance.lineReceived(msg)

        resp_msg = unpackage_query_response(tr.value().strip())

        assert kid == f.key.id()
        if resp_msg[0] == "OK":
            [r, s] = resp_msg[1:]

            total += 1
            xset += [f.key.id()]
            rss += [(r, s)]
        else:
            pass

    assert 5 <= total <= 10
    assert set(auxes) == set(xset)

    ## Now test the commit phase
    assert 5 <= len(rss) <= 10
    msg_commit = package_commit(dataCore, rss)

    #from twisted.python import log
    #import sys
    #log.startLogging(sys.stdout)

    total = 0
    for kid, f in factories.iteritems():

        instance = f.buildProtocol(None)
        tr = StringTransport()
        instance.makeConnection(tr)
        instance.lineReceived(msg_commit)

        resp_commit = tr.value().strip()
        resp_l = unpackage_commit_response(resp_commit)
        if resp_l[0] == "OK":
            total += 1
    assert total == 5
예제 #12
0
파일: derivekey.py 프로젝트: wybosys/rscoin
import rscoin
from base64 import b64encode, b64decode


if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser(description='Derive the public key from a secret password.')
    parser.add_argument('--password', type=str, help='The password that acts as a private key.')    
    parser.add_argument('--store', action='store_true', help='Make up a password and store it.')    

    args = parser.parse_args()

    if args.password:
        secret = args.password
        public = rscoin.Key(secret, public=False).pub.export()
        print("Public: %s" % b64encode(public)) # , b64decode

    if args.store:
        import os

        if not os.path.exists("secret.key"):
            key = os.urandom(32)
            f = file("secret.key", "w")
            f.write(key)
            f.close()
        else:
            key = file("secret.key", "r").read()

        public = rscoin.Key(key, public = False).pub.export()
        print("Public: %s" % b64encode(public)) # , b64decode
예제 #13
0
파일: rsc.py 프로젝트: dazhxu/rscoin
def main():
    dir_data = load_setup(file("directory.conf").read())
    # directory = dir_data["directory"]

    directory = [(kid, socket.gethostbyname(ip), port)
                 for (kid, ip, port) in dir_data["directory"]]

    special_id = dir_data["special"]

    # Options
    parser = argparse.ArgumentParser(description='RSCoin client.')
    parser.add_argument('--dir', action='store_true', help='List mintettes.')
    parser.add_argument('--mock',
                        action='store_true',
                        help='Do not connect to the network.')
    parser.add_argument('--balances',
                        action='store_true',
                        help='List balances of all addresses.')

    parser.add_argument('--issue',
                        nargs=2,
                        metavar=("VALUE", "ADDRESS"),
                        help='Issue a coin to an address.')
    parser.add_argument('--pay',
                        nargs=3,
                        metavar=("VALUE", "ADDRESS", "CHANGEADDRESS"),
                        help='Pay and address some amount, and return change')

    parser.add_argument('--newaddress',
                        nargs=1,
                        metavar="NAME",
                        help='Make a new address with a specific name.')
    parser.add_argument('--storeaddress',
                        nargs=2,
                        metavar=("NAME", "KEYID"),
                        help='Load an address ID with a specific name.')
    parser.add_argument('--listaddress',
                        action='store_true',
                        help='List all known addresses.')

    parser.add_argument('--play',
                        nargs=1,
                        metavar="FILE",
                        help='Play a set of transaction cores.')

    parser.add_argument('--conn',
                        default=20,
                        type=int,
                        metavar="CONNECTIONS",
                        help='Number of simultaneaous connections.')

    args = parser.parse_args()

    if args.dir:
        for (kid, ip, port) in directory:
            print "%s\t%s\t%s" % (ip, port, b64encode(kid))

    elif args.balances:
        keys = load_keys()
        active = ActiveTx("activetx.log", keys)
        for (k, v) in active.balances().iteritems():
            print "%s\t%s RSC" % (k, v)

    elif args.listaddress:
        keys = load_keys()

        for k in keys:
            if k[0] == "#":
                print "%s\t%s (%s)" % (k, keys[k][2], keys[k][1])

    elif args.newaddress:
        sec_str = urandom(32)
        k_sec = rscoin.Key(sec_str, public=False)
        k_pub = k_sec.pub.export()
        k_id = k_sec.id()

        f = file("keychain.txt", "a")
        data = "#%s sec %s %s" % (args.newaddress[0], b64encode(k_id),
                                  b64encode(sec_str))
        print data
        f.write(data + "\n")
        f.close()

    elif args.storeaddress:
        f = file("keychain.txt", "a")
        data = "#%s pub %s" % (args.storeaddress[0], args.storeaddress[1])
        f.write(data + "\n")
        f.close()

    elif args.play:

        threads = [None] * args.conn
        cores = []

        for core in file(args.play[0]):
            c = core.strip().split()
            cores += [c]

        def play_another_song(var):
            if var is not None and (not isinstance(var, float)
                                    or not isinstance(var, float)):
                print "ERROR", var

            if cores != []:
                c = cores.pop()
                d = play(c, directory)
                d.addCallback(play_another_song)

                def replay():
                    cores += [c]

                d.addErrback(replay)
                d.addErrback(play_another_song)

            else:
                threads.pop()
                if threads == []:
                    reactor.stop()

        for _ in threads:
            play_another_song(None)

        t0 = default_timer()
        reactor.run()
        t1 = default_timer()

        print "Overall time: %s" % (t1 - t0)
        for (ip, v) in sorted(_stats.iteritems()):
            print "Stats: %s %s" % (ip, v)

    elif args.pay:

        (val, dest_addr, change_addr) = args.pay
        val = int(val)
        assert isinstance(val, int) and 0 < val

        keys = load_keys()
        dest_addr = b64decode(keys["#" + dest_addr][2])
        change_addr = b64decode(keys["#" + change_addr][2])

        active = ActiveTx("activetx.log", keys)

        print val
        xval, txs = active.get_value(int(val))
        assert len(txs) > 0

        if val <= xval:
            # build the transactions
            inTx = []
            outTx = [rscoin.OutputTx(dest_addr, val)]
            if xval - val > 0:
                outTx += [rscoin.OutputTx(change_addr, xval - val)]

            inTx_list = []
            keys_list = []
            for (tx_id, i, key_id, value) in txs:
                inTx_list += [
                    rscoin.Tx.parse(active.Tx[(tx_id, i, key_id, value)])
                ]
                keys_list += [rscoin.Key(b64decode(keys[key_id][3]), False)]
                inTx += [rscoin.InputTx(tx_id, i)]

            newtx = rscoin.Tx(inTx, outTx)
            newtx_ser = newtx.serialize()

            ## Now we sign and remove from the list
            active.add(newtx_ser)
            for k in txs:
                active.remove(k)

            active.save(reactor)

            ## Now run the on-line checking
            sechash, query_string, core = package_query(
                newtx, inTx_list, keys_list)
            print " ".join(core)

            d = play(core, directory)
            d.addBoth(r_stop)

            reactor.run()

        else:
            print "Insufficient balance: %s ( < %s)" % (val, xval)

    elif args.issue:

        # Parse the basic files.
        secret = file("secret.key").read()
        mykey = rscoin.Key(secret, public=False)

        # Ensure the secret key corresponds to the special public key.
        assert special_id == mykey.id()

        [value_str, key_name] = args.issue

        keys = load_keys()
        key_id = b64decode(keys["#" + key_name][2])

        tx = rscoin.Tx([], [rscoin.OutputTx(key_id, int(value_str))])
        sig = mykey.sign(tx.id())

        ## Now we test the Commit
        tx_ser = tx.serialize()
        #core = map(b64encode, [tx_ser, mykey.pub.export(), sig])
        #data = " ".join(["Commit", str(len(core))] + core)

        data = package_issue(tx, [mykey, sig])

        if args.mock:
            print data
        else:

            auths = set(get_authorities(directory, tx.id()))
            small_dir = [(kid, ip, port) for (kid, ip, port) in directory
                         if kid in auths]

            d = broadcast(small_dir, data)

            def r_process(results):
                for msg in results:
                    parsed = unpackage_commit_response(msg)
                    if parsed[0] != "OK":
                        raise Exception("Response not OK.")

                    pub, sig = parsed[1:]
                    kx = rscoin.Key(pub)

                    if not (kx.verify(tx.id(), sig) and kx.id() in auths):
                        raise Exception("Invalid Signature.")

                    auths.remove(kx.id())

                active = ActiveTx("activetx.log", keys)
                active.add(tx_ser)
                active.save(reactor)

                print " ".join(core)

            d.addCallback(r_process)
            d.addBoth(r_stop)
            reactor.run()
예제 #14
0
    def process_TxCommit(self, data):
        """ Provides a Tx and a list of responses, and commits the transaction. """
        H, mainTx, otherTx, keys, sigs, auth_pub, auth_sig = data

        # Check that this Tx is handled by this server
        ik = mainTx.id()
        lst = self.get_authorities(ik)
        should_handle = (self.key.id() in lst)

        if not should_handle:
            log.msg('Failed Tx ID range ownership')
            return False

        # First check all signatures
        all_good = True
        pub_set = []
        for pub, sig in zip(auth_pub, auth_sig):
            key = rscoin.Key(pub)
            pub_set += [key.id()]
            all_good &= key.verify(H, sig)

        if not all_good:
            log.msg('Failed Tx Signatures')
            return False

        # Check the transaction is well formed
        all_good = mainTx.check_transaction(otherTx,
                                            keys,
                                            sigs,
                                            masterkey=self.special_key)
        if not all_good:
            log.msg('Failed Tx Validity')
            return False

        pub_set = set(pub_set)

        # Now check all authorities are involved
        mid = mainTx.id()
        inTxo = mainTx.get_utxo_in_keys()
        for itx in inTxo:
            ## Ensure we have a Quorum for each input
            aut = set(self.get_authorities(itx))
            all_good &= (len(aut & pub_set) > len(aut) / 2)

        if not all_good:
            log.msg('Failed Tx Authority Consensus')
            return False

        # Now check we have not already spent the transaction
        all_good &= (mid not in self.log)

        if not all_good:
            log.msg('Failed Tx Doublespending')
            return False

        ## TODO: Log all information about the transaction

        # Update the outTx entries
        for k, v in mainTx.get_utxo_out_entries():
            self.db[k] = v

        if RSCFactory._sync:
            self.db.sync()

        return all_good
예제 #15
0
from twisted.application import internet, service
from rscoin.rscservice import RSCFactory, load_setup

import rscoin
from base64 import b64encode, b64decode

secret = file("secret.key").read()
public = rscoin.Key(secret, public=False)
print "Public keys: %s" % b64encode(public.pub.export())

dir_data = file("directory.conf").read()
directory = load_setup(dir_data)  # [(public.id(), "127.0.0.1", 8080)]

application = service.Application("rscoin")
echoService = internet.TCPServer(
    8080, RSCFactory(secret, directory["directory"], directory["special"],
                     N=3))
echoService.setServiceParent(application)