Beispiel #1
0
def test_base_consensus():
    node = Node('n1', Endpoint('http', 'localhost', 5001))
    consensus_module = get_fba_module('isaac')
    consensus = consensus_module.IsaacConsensus(
        node,
        100,
        tuple(),
    )

    assert hash(consensus) == 183908261690725173

    consensus.save_message(Message('id1', 'message1'))
    consensus.save_message(Message('id2', 'message2'))
    consensus.save_message(Message('id3', 'message3'))
    consensus.save_message(Message('id4', 'message4'))

    assert hash(consensus) == 1841909880308066977

    node2 = Node('n2', Endpoint('http', 'localhost', 5002))
    consensus_module = get_fba_module('isaac')
    consensus_2 = consensus_module.IsaacConsensus(
        node2,
        100,
        tuple(),
    )

    assert hash(consensus_2) == 183908261690725173

    consensus_2.save_message(Message('id1', 'message1'))
    consensus_2.save_message(Message('id2', 'message2'))
    consensus_2.save_message(Message('id3', 'message3'))
    consensus_2.save_message(Message('id4', 'message4'))

    assert hash(consensus_2) == 1841909880308066977
Beispiel #2
0
def main(options):
    config = collections.namedtuple(
        'Config',
        ('node_name', 'port', 'threshold', 'validators', 'faulty_percent'),
    )(uuid.uuid1().hex, 8001, 51, [], 0)

    if not pathlib.Path(options.conf).exists():
        parser.error('conf file, `%s` does not exists.' % options.conf)

    if not pathlib.Path(options.conf).is_file():
        parser.error('conf file, `%s` is not valid file.' % options.conf)

    conf = configparser.ConfigParser()
    conf.read(options.conf)
    log.info('conf file, `%s` was loaded', options.conf)

    config = config._replace(node_name=conf['node']['name'])
    config = config._replace(port=int(conf['node']['port']))
    config = config._replace(threshold=int(conf['node']['threshold_percent']))

    if conf.has_option('faulty', 'faulty_percent'):
        config = config._replace(
            faulty_percent=int(conf['faulty']['faulty_percent']))

    log.debug('loaded conf: %s', config)

    validator_list = []
    for i in filter(lambda x: len(x.strip()) > 0,
                    conf['node']['validator_list'].split(',')):
        validator_list.append(Endpoint.from_uri(i.strip()))

    config = config._replace(validators=validator_list)
    log.debug('Validators: %s' % config.validators)

    node = node_factory(
        config.node_name,
        Endpoint(NETWORK_MODULE.SCHEME, get_local_ipaddress(), config.port),
        config.faulty_percent)

    consensus_module = get_fba_module('isaac')
    consensus = consensus_module.IsaacConsensus(
        node,
        config.threshold,
        tuple(map(lambda x: Node(x.extras['name'], x), config.validators)),
    )

    log.metric(node=node.name, data=node.to_dict())

    transport = NETWORK_MODULE.Transport(bind=('0.0.0.0', config.port))

    blockchain = Blockchain(consensus, transport)

    base_server = BaseServer(blockchain)
    base_server.start()

    return
Beispiel #3
0
def test_same_message_after_init():
    node_id_1 = 'n1'
    node_id_2 = 'n2'
    node_id_3 = 'n3'

    blockchain1 = simple_blockchain_factory(
        node_id_1,
        'http://localhost:5001',
        100,
        [node_id_2, node_id_3],
    )

    node2 = node_factory(node_id_2, Endpoint.from_uri('http://localhost:5002'))
    node3 = node_factory(node_id_3, Endpoint.from_uri('http://localhost:5003'))

    blockchain1.consensus.add_to_validator_connected(node2)
    blockchain1.consensus.add_to_validator_connected(node3)

    message = Message.new('message')

    ballot1 = Ballot.new(node_id_1, message, IsaacState.INIT, BallotVotingResult.agree)
    ballot2 = copy_ballot(ballot1, node_id_2, IsaacState.INIT)
    ballot3 = copy_ballot(ballot1, node_id_3, IsaacState.INIT)

    blockchain1.receive_ballots(ballot1, ballot2, ballot3)

    assert blockchain1.consensus.slot.get_ballot_state(ballot1) == IsaacState.SIGN

    existing_ballot_ids = set(
        map(lambda x: x.ballot_id, filter(lambda x: x is not None, blockchain1.consensus.slot.get_all_ballots())))

    # send same message in new ballot, which has previous state
    new_ballot1 = Ballot.new(node_id_1, message, IsaacState.INIT, BallotVotingResult.agree)

    assert new_ballot1.ballot_id != ballot1.ballot_id

    ballot1 = copy_ballot(new_ballot1, node_id_1, IsaacState.INIT)
    ballot2 = copy_ballot(new_ballot1, node_id_2, IsaacState.INIT)
    ballot3 = copy_ballot(new_ballot1, node_id_3, IsaacState.INIT)

    blockchain1.receive_ballots(ballot1, ballot2, ballot3)

    # node doesn't have ballot1, so ballot1 in node state is NONE
    assert blockchain1.consensus.slot.get_ballot_state(ballot1) == IsaacState.NONE
    list(filter(
        lambda x: x.ballot_id == ballot1.ballot_id, blockchain1.consensus.slot.get_validator_ballots(ballot1).values()
    ))
    assert len([]) < 1

    current_ballot_ids = set(
        map(lambda x: x.ballot_id, filter(lambda x: x is not None, blockchain1.consensus.slot.get_all_ballots())))

    assert existing_ballot_ids == current_ballot_ids

    return
def blockchain_factory(name, address, threshold, validator_endpoint_uris,
                       slot_size):
    node = node_factory(name, Endpoint.from_uri(address))
    validators = list()
    for uri in validator_endpoint_uris:
        validators.append(node_factory(uri, Endpoint.from_uri(uri)), )

    consensus = IsaacConsensus(node, threshold, validators, slot_size)
    consensus._check_slot_time = check_slot_time_stub
    Blockchain.receive_ballot = receive_copy_ballot
    return Blockchain(consensus, StubTransport())
def simple_blockchain_factory(name, address, threshold,
                              validator_endpoint_uris):
    node = node_factory(name, Endpoint.from_uri(address))

    validators = list()
    for uri in validator_endpoint_uris:
        validators.append(node_factory(uri, Endpoint(uri, uri, 0)), )

    consensus = Consensus(node, threshold, validators)

    transport = StubTransport(bind=('0.0.0.0', 5001))

    return SimpleBlockchain(consensus, transport)
def test_isaac_consensus():
    node = node_factory('n1', Endpoint.from_uri('http://localhost:5001'))

    validator_uris = ('http://localhost:5002', 'http://localhost:5003')
    validators = list()
    for uri in validator_uris:
        validators.append(node_factory(uri, Endpoint.from_uri(uri)), )

    consensus = IsaacConsensus(node, 100, validators)

    assert consensus.minimum == 3
    assert consensus.threshold == 100

    uris = list(map(lambda x: x.endpoint.uri, consensus.validator_candidates))
    assert set(validator_uris) == set(uris)
def blockchain_factory(Consensus, name, address, threshold, validators,
                       slot_size, queue_size):
    node = node_factory(name, Endpoint.from_uri(address))
    consensus = Consensus(node, threshold, validators, slot_size)
    transport = network_module.Transport(node, loop)

    return Blockchain(consensus, transport)
def test_confirm_stuck_ballot():
    node_name_1 = 'http://localhost:5001'
    node_name_2 = 'http://localhost:5002'
    node_name_3 = 'http://localhost:5003'

    bc1 = simple_blockchain_factory(
        node_name_1,
        'http://localhost:5001',
        100,
        [node_name_2, node_name_3],
    )

    node2 = node_factory(node_name_2,
                         Endpoint.from_uri('http://localhost:5002'))
    node3 = node_factory(node_name_3,
                         Endpoint.from_uri('http://localhost:5003'))

    bc1.consensus.add_to_validator_connected(node2)
    bc1.consensus.add_to_validator_connected(node3)

    message = Message.new('message')

    ballot_init_1 = Ballot.new(node_name_1, message, IsaacState.INIT,
                               BallotVotingResult.agree)
    ballot_id = ballot_init_1.ballot_id
    ballot_init_2 = Ballot(ballot_id, node_name_2, message, IsaacState.INIT,
                           BallotVotingResult.agree, ballot_init_1.timestamp)
    ballot_init_3 = Ballot(ballot_id, node_name_3, message, IsaacState.INIT,
                           BallotVotingResult.agree, ballot_init_1.timestamp)

    bc1.receive_ballot(ballot_init_1)
    bc1.receive_ballot(ballot_init_2)
    bc1.receive_ballot(ballot_init_3)

    assert bc1.consensus.slot.get_ballot_state(
        ballot_init_1) == IsaacState.SIGN

    time.sleep(LIMIT_TIME + 0.1)

    assert bc1.consensus.slot.get_ballot_state(
        ballot_init_1) == IsaacState.NONE

    return
def generate_blockchains(Consensus,
                         node_names,
                         node_endpoints,
                         threshold,
                         slot_size=5,
                         queue_size=100):
    blockchains = list()
    nodes = list()
    for i in range(len(node_names)):
        nodes.append(
            node_factory(node_names[i], Endpoint.from_uri(node_endpoints[i])))

    for i in range(len(node_names)):
        validators = copy.deepcopy(nodes)
        del validators[i]
        blockchain = blockchain_factory(Consensus, node_names[i],
                                        node_endpoints[i], 100, validators,
                                        slot_size, queue_size)
        blockchains.append(blockchain)

    return blockchains
Beispiel #10
0
    help='Messages you want to send to the server',
    type=str,
)

if __name__ == '__main__':
    options = parser.parse_args()
    logger.from_argparse(logger, options)
    log = logger.get_logger(__name__)

    log.debug('options: %s', options)

    message = None
    endpoints = list()
    for n, i in enumerate(options.endpoints):
        try:
            endpoints.append(Endpoint.from_uri(i))
        except AssertionError as e:
            if n < len(options.endpoints) - 1:
                parser.error('invalid endpoint: %s' % i)

                sys.exit(1)

            message = Message.new(i)

    log.debug('trying to send message, %s to %s', message, endpoints)
    messages = send_message_multiple(message, *endpoints)
    for (message, endpoint) in messages:
        log.debug('sent message, %s to %s', message.serialize(to_string=False),
                  endpoint)

    sys.exit(0)
Beispiel #11
0
def test_same_message_after_allconfirm():
    node_id_1 = 'n1'
    node_id_2 = 'n2'
    node_id_3 = 'n3'

    blockchain1 = simple_blockchain_factory(
        node_id_1,
        'http://localhost:5001',
        100,
        [node_id_2, node_id_3],
    )

    node2 = node_factory(node_id_2, Endpoint.from_uri('http://localhost:5002'))
    node3 = node_factory(node_id_3, Endpoint.from_uri('http://localhost:5003'))

    blockchain1.consensus.add_to_validator_connected(node2)
    blockchain1.consensus.add_to_validator_connected(node3)

    message = Message.new('message')

    ballot1 = Ballot.new(node_id_1, message, IsaacState.INIT, BallotVotingResult.agree)
    ballot2 = copy_ballot(ballot1, node_id_2, IsaacState.INIT)
    ballot3 = copy_ballot(ballot1, node_id_3, IsaacState.INIT)

    blockchain1.receive_ballots(ballot1, ballot2, ballot3)

    assert blockchain1.consensus.slot.get_ballot_state(ballot1) == IsaacState.SIGN

    ballot1 = copy_ballot(ballot1, node_id_1, IsaacState.SIGN)
    ballot2 = copy_ballot(ballot1, node_id_2, IsaacState.SIGN)
    ballot3 = copy_ballot(ballot1, node_id_3, IsaacState.SIGN)

    blockchain1.receive_ballots(ballot1, ballot2, ballot3)

    assert blockchain1.consensus.slot.get_ballot_state(ballot1) == IsaacState.ACCEPT

    ballot1 = copy_ballot(ballot1, node_id_1, IsaacState.ACCEPT)
    ballot2 = copy_ballot(ballot1, node_id_2, IsaacState.ACCEPT)
    ballot3 = copy_ballot(ballot1, node_id_3, IsaacState.ACCEPT)

    blockchain1.receive_ballots(ballot1, ballot2, ballot3)

    assert message in blockchain1.consensus.messages

    # send same message in new ballot
    new_ballot1 = Ballot.new(node_id_1, message, IsaacState.INIT, BallotVotingResult.agree)

    assert new_ballot1.ballot_id != ballot1.ballot_id

    ballot1 = copy_ballot(new_ballot1, node_id_1, IsaacState.INIT)
    ballot2 = copy_ballot(new_ballot1, node_id_2, IsaacState.INIT)
    ballot3 = copy_ballot(new_ballot1, node_id_3, IsaacState.INIT)

    blockchain1.receive_ballots(ballot1, ballot2, ballot3)

    # node state still remains the previous state
    assert message in blockchain1.consensus.messages
    ballots = blockchain1.consensus.slot.get_validator_ballots(new_ballot1).values()
    assert not ballots

    return
def test_use_fake():
    node = node_factory('n1', Endpoint.from_uri('http://localhost:5001'))
    consensus = FakeConsensus(node)
    assert consensus.node_name == 'n1'
def load_design(filename):
    design = None

    with open(filename) as f:
        if filename.split('.')[-1] == 'yml':
            design = convert_dict_to_namedtuple(yaml.load(f.read()))
        elif filename.split('.')[-1] == 'json':
            temp_design = convert_json_config(json.load(f))
            design = convert_dict_to_namedtuple(temp_design)
        else:
            print(
                '# error: \"file `%s` is not valid file. yml or json type is needed\"'
                % filename)
            sys.exit(1)

    defined_ports = list()
    for name, config in design.nodes._asdict().items():
        port = getattr(config, 'port', None)
        if port is None:
            continue

        defined_ports.append(port)

    faulty_nodes = dict()
    nodes = dict()
    for name, config in design.nodes._asdict().items():
        port = getattr(config, 'port', None)
        if port is None:
            port = get_free_port(defined_ports)

        endpoint = Endpoint(NETWORK_MODULE.SCHEME,
                            get_local_ipaddress(),
                            port,
                            name=name)
        node = node_factory(name, endpoint, 0)

        if hasattr(config.quorum, 'threshold'):
            threshold = config.quorum.threshold
        else:
            threshold = design.common.threshold

        nodes[name] = dict(node=node,
                           quorum=dict(validators=list(), threshold=threshold))

        faulties = list()
        faulty = getattr(getattr(design, 'faulties', None), name, None)
        if faulty is not None:
            for case in faulty:
                kind = FaultyNodeKind.get_from_name(case.case.kind)
                if kind in (FaultyNodeKind.Unknown, ):
                    continue

                dict_case = convert_namedtuple_to_dict(case.case)
                dict_case['kind'] = kind
                faulties.append(dict_case)

        if len(faulties) > 0:
            faulty_nodes[name] = faulties

    for name, config in design.nodes._asdict().items():
        for node_name in config.quorum.validators:
            nodes[name]['quorum']['validators'].append(
                nodes[node_name]['node'])

    design_dict = convert_namedtuple_to_dict(design)

    if 'audit_waiting' not in design_dict['common']:
        design_dict['common']['audit_waiting'] = 1
    if 'audit_time_limit' not in design_dict['common']:
        design_dict['common']['audit_time_limit'] = 2
    design_dict['common']['network_module'] = NETWORK_MODULE
    design_dict['nodes'] = list(nodes.values())
    design_dict['nodes_by_name'] = nodes
    design_dict['faulties'] = faulty_nodes

    return convert_dict_to_namedtuple(design_dict)