This commit is contained in:
Julien Maffre 2020-07-07 15:46:44 +01:00 коммит произвёл GitHub
Родитель ce1fe08ae2
Коммит b53a4445ce
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
56 изменённых файлов: 760 добавлений и 179 удалений

Просмотреть файл

@ -79,5 +79,4 @@ jobs:
- template: release.yml
parameters:
env: ${{ parameters.env.Hosted }}
depends_on: 'SGX_Release'
depends_on: 'SGX_Release'

Просмотреть файл

@ -26,4 +26,14 @@ jobs:
isDraft: true
isPreRelease: true
addChangeLog: false
displayName: 'GitHub release (create)'
displayName: 'GitHub release (create)'
# For now, push to test PyPi
- script: |
python3.7 -m venv env
source ./env/bin/activate
python setup.py sdist
python -m pip install twine
twine upload -u __token__ -p $(pypi_test_token) --repository testpypi dist/*
workingDirectory: python
displayName: PyPi https://test.pypi.org/project/ccf/

4
.gitignore поставляемый
Просмотреть файл

@ -20,4 +20,6 @@ getting_started/create_vm/generated
sphinx/env/
html/
latex/
env/
env/
*.egg-info
**/dist

Просмотреть файл

@ -15,7 +15,7 @@ ignore-patterns=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
init-hook='import sys; sys.path.append("python")'
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
# number of processors available to use.

Просмотреть файл

@ -179,6 +179,15 @@ install(
PATTERN "*/test*" EXCLUDE
)
# Install CCF Python tools
install(
DIRECTORY python/ccf
DESTINATION bin/
FILES_MATCHING
PATTERN "*.py"
PATTERN "*/__pycache__*" EXCLUDE
)
# Install CCF Python infrastructure
install(
DIRECTORY tests/infra/

Просмотреть файл

@ -89,20 +89,28 @@ add_custom_command(
COMMENT "Generating code from EDL, and renaming to .cpp"
)
# Copy utilities from tests directory
set(CCF_UTILITIES tests.sh keygenerator.sh cimetrics_env.sh
upload_pico_metrics.py scurl.sh submit_recovery_share.sh
)
# Copy and install CCF utilities
set(CCF_UTILITIES keygenerator.sh scurl.sh submit_recovery_share.sh)
foreach(UTILITY ${CCF_UTILITIES})
configure_file(
${CCF_DIR}/python/utils/${UTILITY} ${CMAKE_CURRENT_BINARY_DIR} COPYONLY
)
install(PROGRAMS ${CCF_DIR}/python/utils/${UTILITY} DESTINATION BIN)
endforeach()
# Copy utilities from tests directory
set(CCF_TEST_UTILITIES tests.sh cimetrics_env.sh upload_pico_metrics.py)
foreach(UTILITY ${CCF_TEST_UTILITIES})
configure_file(
${CCF_DIR}/tests/${UTILITY} ${CMAKE_CURRENT_BINARY_DIR} COPYONLY
)
endforeach()
# Install specific utilities
install(PROGRAMS ${CCF_DIR}/tests/scurl.sh ${CCF_DIR}/tests/keygenerator.sh
${CCF_DIR}/tests/sgxinfo.sh
${CCF_DIR}/tests/submit_recovery_share.sh DESTINATION bin
install(
PROGRAMS ${CCF_DIR}/python/utils/scurl.sh
${CCF_DIR}/python/utils/keygenerator.sh ${CCF_DIR}/tests/sgxinfo.sh
${CCF_DIR}/python/utils/submit_recovery_share.sh DESTINATION bin
)
# Install getting_started scripts for VM creation and setup

3
python/MANIFEST.in Normal file
Просмотреть файл

@ -0,0 +1,3 @@
include utils/scurl.sh
include utils/submit_recovery_share.sh
include utils/keygenerator.sh

3
python/README.md Normal file
Просмотреть файл

@ -0,0 +1,3 @@
# CCF Python
Suite of Python tools for the Confidential Consortium Framework (CCF). For more information, visit https://github.com/Microsoft/python/ccf.

2
python/ccf/__init__.py Normal file
Просмотреть файл

@ -0,0 +1,2 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.

Просмотреть файл

@ -5,7 +5,7 @@ import json
import http
import time
from infra.tx_status import TxStatus
from ccf.tx_status import TxStatus
def wait_for_global_commit(client, seqno, view, mksign=False, timeout=3):

Просмотреть файл

@ -33,6 +33,9 @@ CCF_TX_VIEW_HEADER = "x-ccf-tx-view"
# Deprecated, will be removed
CCF_GLOBAL_COMMIT_HEADER = "x-ccf-global-commit"
DEFAULT_CONNECTION_TIMEOUT_SEC = 3
DEFAULT_REQUEST_TIMEOUT_SEC = 3
class Request:
def __init__(
@ -209,7 +212,15 @@ class CurlClient:
"""
def __init__(
self, host, port, cert, key, ca, binary_dir, request_timeout, *args, **kwargs,
self,
host,
port,
cert=None,
key=None,
ca=None,
binary_dir=".",
request_timeout=DEFAULT_REQUEST_TIMEOUT_SEC,
**kwargs,
):
self.host = host
self.port = port
@ -288,20 +299,30 @@ class CurlClient:
class TlsAdapter(HTTPAdapter):
def __init__(self, ca_file):
self.ca_curve = get_curve(ca_file)
self.ca_curve = None
if ca_file is not None:
self.ca_curve = get_curve(ca_file)
super().__init__()
# pylint: disable=signature-differs
def init_poolmanager(self, *args, **kwargs):
context = create_urllib3_context()
context.set_ecdh_curve(self.ca_curve.name)
kwargs["ssl_context"] = context
if self.ca_curve is not None:
context = create_urllib3_context()
context.set_ecdh_curve(self.ca_curve.name)
kwargs["ssl_context"] = context
return super(TlsAdapter, self).init_poolmanager(*args, **kwargs)
class RequestClient:
def __init__(
self, host, port, cert, key, ca, request_timeout, *args, **kwargs,
self,
host,
port,
cert=None,
key=None,
ca=None,
request_timeout=DEFAULT_REQUEST_TIMEOUT_SEC,
**kwargs,
):
self.host = host
self.port = port
@ -357,7 +378,14 @@ class RequestClient:
class WSClient:
def __init__(
self, host, port, cert, key, ca, request_timeout, *args, **kwargs,
self,
host,
port,
cert=None,
key=None,
ca=None,
request_timeout=DEFAULT_REQUEST_TIMEOUT_SEC,
**kwargs,
):
self.host = host
self.port = port
@ -408,18 +436,24 @@ class WSClient:
class CCFClient:
def __init__(self, *args, **kwargs):
self.description = kwargs.pop("description")
self.connection_timeout = kwargs.pop("connection_timeout")
def __init__(self, host, port, *args, **kwargs):
self.description = (
kwargs.pop("description") if "description" in kwargs else None
)
self.connection_timeout = (
kwargs.pop("connection_timeout")
if "connection_timeout" in kwargs
else DEFAULT_CONNECTION_TIMEOUT_SEC
)
self.rpc_loggers = (RPCLogger(),)
self.name = "[{}:{}]".format(kwargs.get("host"), kwargs.get("port"))
self.name = f"[{host}:{port}]"
if os.getenv("CURL_CLIENT"):
self.client_impl = CurlClient(*args, **kwargs)
self.client_impl = CurlClient(host, port, *args, **kwargs)
elif os.getenv("WEBSOCKETS_CLIENT") or kwargs.get("ws"):
self.client_impl = WSClient(*args, **kwargs)
self.client_impl = WSClient(host, port, *args, **kwargs)
else:
self.client_impl = RequestClient(*args, **kwargs)
self.client_impl = RequestClient(host, port, *args, **kwargs)
def _response(self, response):
for logger in self.rpc_loggers:
@ -481,8 +515,8 @@ def client(
description=None,
log_file=None,
binary_dir=".",
connection_timeout=3,
request_timeout=3,
connection_timeout=DEFAULT_CONNECTION_TIMEOUT_SEC,
request_timeout=DEFAULT_REQUEST_TIMEOUT_SEC,
ws=False,
):
c = CCFClient(

Просмотреть файл

Просмотреть файл

Просмотреть файл

47
python/setup.py Normal file
Просмотреть файл

@ -0,0 +1,47 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
from setuptools import setup
from os import path
PACKAGE_NAME = "ccf"
UTILITIES_PATH = "utils"
path_here = path.abspath(path.dirname(__file__))
with open(path.join(path_here, "README.md"), encoding="utf-8") as f:
long_description = f.read()
setup(
name=PACKAGE_NAME,
version="0.11.7",
description="Set of tools and utilities for the Confidential Consortium Framework (CCF)",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/microsoft/CCF/python/ccf",
license="Apache License 2.0",
author="CCF Team",
author_email="ccfeng@microsoft.com",
classifiers=[
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
],
packages=[PACKAGE_NAME],
python_requires=">=3.7",
install_requires=[
"msgpack",
"loguru",
"requests",
"requests-http-signature",
"websocket-client",
"cryptography",
],
scripts=[
path.join(PACKAGE_NAME, "proposal_generator.py"),
path.join(UTILITIES_PATH, "keygenerator.sh"),
path.join(UTILITIES_PATH, "scurl.sh"),
path.join(UTILITIES_PATH, "submit_recovery_share.sh"),
],
include_package_data=True,
)

103
python/utils/keygenerator.sh Executable file
Просмотреть файл

@ -0,0 +1,103 @@
#!/bin/bash
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
set -e
DEFAULT_CURVE="secp384r1"
EDWARDS_CURVE="ed25519"
ENCRYPTION_CURVE="x25519"
FAST_CURVE="secp256k1"
SUPPORTED_CURVES="$DEFAULT_CURVE|$EDWARDS_CURVE|$FAST_CURVE"
DIGEST_SHA384="sha384"
DIGEST_SHA256="sha256"
DIGEST_SHA512="sha512"
curve=$DEFAULT_CURVE
name=""
generate_encryption_key=false
function usage()
{
echo "Usage:"
echo " $0 --name participant_name [--curve $DEFAULT_CURVE] [--gen-enc-key]"
echo "Generates identity private key and self-signed certificates for CCF participants."
echo "Optionally generates a x25519 key pair for share encryption (required for consortium members)."
echo ""
echo "Supported curves are: $SUPPORTED_CURVES"
}
while [ "$1" != "" ]; do
case $1 in
-h|-\?|--help)
usage
exit 0
;;
-n|--name)
name="$2"
shift
;;
-c|--curve)
curve="$2"
shift
;;
-g|--gen-enc-key)
generate_encryption_key=true
;;
*)
break
esac
shift
done
# Validate parameters
if [ -z "$name" ]; then
echo "Error: The name of the participant should be specified (e.g. member0 or user1)"
exit 1
fi
if ! [[ "$curve" =~ ^($SUPPORTED_CURVES)$ ]]; then
echo "$curve curve is not in $SUPPORTED_CURVES"
exit 1
fi
if [ "$curve" == "$DEFAULT_CURVE" ]; then
digest="$DIGEST_SHA384"
elif [ "$curve" == "$EDWARDS_CURVE" ]; then
digest="$DIGEST_SHA512"
else
digest="$DIGEST_SHA256"
fi
cert="$name"_cert.pem
privk="$name"_privk.pem
echo "-- Generating identity private key and certificate for participant \"$name\"..."
echo "Identity curve: $curve"
# Because openssl CLI interface for ec key differs from Ed, detect which
# interface to use based on first letters of the specified curve
if ! [ "$curve" == $EDWARDS_CURVE ]; then
openssl ecparam -out "$privk" -name "$curve" -genkey
else
openssl genpkey -out "$privk" -algorithm "$curve"
fi
openssl req -new -key "$privk" -x509 -nodes -days 365 -out "$cert" -"$digest" -subj=/CN="$name"
echo "Identity private key generated at: $privk"
echo "Identity certificate generated at: $cert (to be registered in CCF)"
if "$generate_encryption_key"; then
echo "-- Generating encryption key pair for participant \"$name\"..."
enc_priv="$name"_enc_privk.pem
enc_pub="$name"_enc_pubk.pem
openssl genpkey -out "$enc_priv" -algorithm "$ENCRYPTION_CURVE"
openssl pkey -in "$enc_priv" -pubout -out "$enc_pub"
echo "Encryption private key generated at: $enc_priv"
echo "Encryption public key generated at: $enc_pub (to be registered in CCF)"
fi

61
python/utils/scurl.sh Executable file
Просмотреть файл

@ -0,0 +1,61 @@
#!/bin/bash
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
set -e
# Loop through all arguments and find request data and private key
next_is_data=false
next_is_privk=false
for item in "$@" ; do
if [ "$next_is_data" == true ]; then
request=$item
next_is_data=false
fi
if [ "$next_is_privk" == true ]; then
privk=$item
next_is_privk=false
fi
if [ "$item" == "-d" ] || [ "$item" == "--data" ] || [ "$item" == "--data-binary" ]; then
next_is_data=true
fi
if [ "$item" == "--key" ]; then
next_is_privk=true
fi
done
if [ -z "$request" ]; then
echo "Error: No request found in arguments (-d or --data-binary)"
exit 1
fi
if [ -z "$privk" ]; then
echo "Error: No private key found in arguments (--key)"
exit 1
fi
# If the first letter of the request is @, consider it a filename
if [ "$(echo "$request" | cut -c1)" == "@" ]; then
request_path="${request:1}"
req_digest=$(openssl dgst -sha256 -binary "$request_path" | openssl base64)
content_length=$(wc -c "$request_path" | awk '{print $1}' )
else
req_digest=$(printf "%s" "$request" | openssl dgst -sha256 -binary | openssl base64)
content_length=${#request}
fi
date=$(date "+%a, %d %b %Y %H:%M:%S %Z")
# Construct string to sign
string_to_sign="date: $date
digest: SHA-256=$req_digest
content-length: $content_length"
# Compute signature
signed_raw=$(echo -n "$string_to_sign" | openssl dgst -sha256 -sign "$privk" | openssl base64 -A)
curl \
-H "Date: $date" \
-H "Digest: SHA-256=$req_digest" \
-H "Authorization: Signature keyId=\"tls\",algorithm=\"ecdsa-sha256\",headers=\"date digest content-length\",signature=\"$signed_raw\"" \
"$@"

Просмотреть файл

@ -0,0 +1,85 @@
#!/bin/bash
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
set -e
function usage()
{
echo "Usage:"""
echo " $0 --rpc-address rpc_address --member-enc-privk member_enc_privk.pem --network-enc-pubk network_enc_pubk.pem [CURL_OPTIONS]"
echo "Retrieves the encrypted recovery share for a given member, decrypts the share and submits it for recovery."
echo ""
echo "A sufficient number of recovery shares must be submitted by members to initiate the end of recovery procedure."
echo "Note: Requires step CLI."
}
while [ "$1" != "" ]; do
case $1 in
-h|-\?|--help)
usage
exit 0
;;
--rpc-address)
node_rpc_address="$2"
;;
--member-enc-privk)
member_enc_privk="$2"
;;
--network-enc-pubk)
network_enc_pubk="$2"
;;
*)
break
esac
shift
shift
done
if ! [ -x "$(command -v step)" ]; then
echo "Error: step CLI is not installed on your system or not in your path."
echo "See https://microsoft.github.io/CCF/master/members/accept_recovery.html#submitting-recovery-shares"
exit 1
fi
if [ -z "$node_rpc_address" ]; then
echo "Error: No node RPC address in arguments (--rpc-address)"
exit 1
fi
if [ -z "$member_enc_privk" ]; then
echo "Error: No member encryption private key in arguments (--member-enc-privk)"
exit 1
fi
if [ -z "$network_enc_pubk" ]; then
echo "Error: No defunct network encryption public key in arguments (--network-enc-pubk)"
exit 1
fi
# Retrieve encrypted recovery share and nonce
resp=$(curl -sS --fail -X GET https://"${node_rpc_address}"/gov/recovery_share "${@}")
encrypted_share="$(echo "${resp}" | jq -r .encrypted_recovery_share)"
nonce="$(echo "${resp}" | jq -r .nonce)"
# Temporary directory for raw keys
tmp_dir=$(mktemp -d)
function cleanup() {
rm -rf "${tmp_dir}"
}
trap cleanup EXIT
# Parse raw private key from SubjectPublicKeyInfo DER format, as generated by keygenerator.sh --gen-enc-key
der_header_privk_len=14
openssl asn1parse -in "${member_enc_privk}" -strparse "${der_header_privk_len}" -out "${tmp_dir}/member_enc_privk.raw" -noout
# Parse raw public key generated by network
der_header_pubk_len=9
openssl asn1parse -in "${network_enc_pubk}" -i -strparse "${der_header_pubk_len}" -out "${tmp_dir}/network_enc_pubk.raw" -noout
# step CLI base64 standard to URL encoding for input
encrypted_share_b64_url=$(echo "${encrypted_share}" | sed 's/+/-/g; s/\//_/g')
# Decrypt encrypted share with nonce, member private key and defunct network public key and submit share
# All in one line so that the recovery share is not exposed
echo "${encrypted_share_b64_url}" | step crypto nacl box open base64:"${nonce}" "${tmp_dir}/network_enc_pubk.raw" "${tmp_dir}/member_enc_privk.raw" | openssl base64 -A | curl -i -sS --fail https://"${node_rpc_address}"/gov/recovery_share/submit "${@}" -d @-

Просмотреть файл

@ -1,8 +1,9 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.e2e_args
import infra.ccf
import infra.proposal_generator
import infra.network
import ccf.proposal_generator
import ccf.checker
import os
import logging
from time import gmtime, strftime, perf_counter
@ -33,7 +34,7 @@ class AppUser:
def run(args):
hosts = ["localhost"]
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
network.start_and_join(args)
@ -47,7 +48,7 @@ def run(args):
# Give regulators permissions to register regulators and banks
for regulator in regulators:
proposal_body, _ = infra.proposal_generator.set_user_data(
proposal_body, _ = ccf.proposal_generator.set_user_data(
regulator.ccf_id,
{"proposals": {"REGISTER_REGULATORS": True, "REGISTER_BANKS": True}},
)
@ -97,7 +98,7 @@ def run(args):
for regulator in regulators:
with primary.user_client(format="msgpack", user_id=regulator.name) as c:
check = infra.checker.Checker()
check = ccf.checker.Checker()
check(
c.rpc(
@ -124,7 +125,7 @@ def run(args):
with primary.user_client(format="msgpack", user_id=regulators[0].name) as c:
for bank in banks:
check = infra.checker.Checker()
check = ccf.checker.Checker()
check(
c.rpc(

Просмотреть файл

@ -1,7 +1,7 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.e2e_args
import infra.ccf
import infra.network
import logging
import time

Просмотреть файл

@ -1,8 +1,9 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.e2e_args
import infra.ccf
import infra.proposal_generator
import infra.network
import ccf.checker
import ccf.proposal_generator
import logging
from time import gmtime, strftime
@ -37,10 +38,10 @@ def check_status(rc):
def run(args):
hosts = ["localhost"] * (4 if args.consensus == "pbft" else 1)
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
check = infra.checker.Checker()
check = ccf.checker.Checker()
network.start_and_join(args)
primary, others = network.find_nodes()
@ -77,7 +78,7 @@ def run(args):
transactions.append(json_tx)
# Manager is granted special privileges by members, which is later read by app to enforce access restrictions
proposal_body, _ = infra.proposal_generator.set_user_data(
proposal_body, _ = ccf.proposal_generator.set_user_data(
manager.ccf_id,
{"privileges": {"REGISTER_REGULATORS": True, "REGISTER_BANKS": True}},
)
@ -105,7 +106,7 @@ def run(args):
# As permissioned manager, register regulator and banks
with primary.client() as mc:
check_commit = infra.checker.Checker(mc)
check_commit = ccf.checker.Checker(mc)
with primary.client(f"user{manager.name}") as c:
check(

Просмотреть файл

@ -45,13 +45,13 @@ pip --disable-pip-version-check install black pylint 1>/dev/null
echo "Python format"
if [ $FIX -ne 0 ]; then
black tests/ scripts/*.py
black python/ tests/ scripts/*.py
else
black --check tests/ scripts/*.py
black --check python/ tests/ scripts/*.py
fi
# Install test dependencies before linting
pip --disable-pip-version-check install -U -r tests/requirements.txt 1>/dev/null
echo "Python lint"
find tests/ -type f -name "*.py" -exec python -m pylint {} +
find tests/ python/ -type f -name "*.py" -exec python -m pylint {} +

Просмотреть файл

@ -13,6 +13,7 @@ source env/bin/activate
PATH_HERE=$(dirname "$(realpath -s "$0")")
pip install -q -U -e "${PATH_HERE}"/python/
pip install -q -U -r "${PATH_HERE}"/tests/requirements.txt
echo "Python environment successfully setup"

Просмотреть файл

@ -1,7 +1,7 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.e2e_args
import infra.ccf
import infra.network
import infra.path
import infra.proc
import os
@ -27,7 +27,7 @@ def get_code_id(lib_path):
def run(args):
hosts = ["localhost", "localhost"]
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
network.start_and_join(args)
@ -57,7 +57,7 @@ def run(args):
network.create_and_add_pending_node(
args.patched_file_name, "localhost", args, timeout=3
)
except infra.ccf.CodeIdNotFound as err:
except infra.network.CodeIdNotFound as err:
code_not_found_exception = err
assert (

Просмотреть файл

@ -2,8 +2,9 @@
# Licensed under the Apache 2.0 License.
import infra.e2e_args
import time
import infra.ccf
import infra.network
import infra.proc
import ccf.checker
import contextlib
import resource
import psutil
@ -15,10 +16,10 @@ from loguru import logger as LOG
def run(args):
hosts = ["localhost"] * (4 if args.consensus == "pbft" else 1)
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
check = infra.checker.Checker()
check = ccf.checker.Checker()
network.start_and_join(args)
primary, _ = network.find_nodes()

Просмотреть файл

@ -4,10 +4,11 @@ from hashlib import md5
import itertools
import time
import infra.ccf
import infra.network
import infra.proc
import infra.notification
import infra.net
import ccf.checker
import suite.test_requirements as reqs
import infra.e2e_args
@ -24,7 +25,7 @@ def test(network, args, batch_size=100, write_key_divisor=1, write_size_multipli
# Set extended timeout, since some of these successful transactions will take many seconds
with primary.client("user0", request_timeout=30) as c:
check = infra.checker.Checker()
check = ccf.checker.Checker()
message_ids = [next(id_gen) for _ in range(batch_size)]
messages = [
@ -60,7 +61,7 @@ def test(network, args, batch_size=100, write_key_divisor=1, write_size_multipli
def run(args):
hosts = ["localhost", "localhost", "localhost"]
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
network.start_and_join(args)
@ -94,7 +95,7 @@ def run(args):
def run_to_destruction(args):
hosts = ["localhost", "localhost", "localhost"]
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
network.start_and_join(args)

Просмотреть файл

@ -1,11 +1,12 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.ccf
import infra.network
import infra.notification
import suite.test_requirements as reqs
import infra.logging_app as app
import infra.e2e_args
from infra.tx_status import TxStatus
from ccf.tx_status import TxStatus
import ccf.checker
import inspect
import http
import ssl
@ -13,7 +14,7 @@ import socket
import os
from collections import defaultdict
import time
import infra.clients
import ccf.clients
from loguru import logger as LOG
@ -44,7 +45,7 @@ def test_illegal(network, args, notifications_queue=None, verify=True):
# Send malformed HTTP traffic and check the connection is closed
cafile = cafile = os.path.join(network.common_dir, "networkcert.pem")
context = ssl.create_default_context(cafile=cafile)
context.set_ecdh_curve(infra.clients.get_curve(cafile).name)
context.set_ecdh_curve(ccf.clients.get_curve(cafile).name)
context.load_cert_chain(
certfile=os.path.join(network.common_dir, "user0_cert.pem"),
keyfile=os.path.join(network.common_dir, "user0_privk.pem"),
@ -79,8 +80,8 @@ def test_large_messages(network, args):
primary, _ = network.find_primary()
with primary.client() as nc:
check_commit = infra.checker.Checker(nc)
check = infra.checker.Checker()
check_commit = ccf.checker.Checker(nc)
check = ccf.checker.Checker()
with primary.client("user0") as c:
log_id = 44
@ -106,8 +107,8 @@ def test_remove(network, args):
primary, _ = network.find_primary()
with primary.client() as nc:
check_commit = infra.checker.Checker(nc)
check = infra.checker.Checker()
check_commit = ccf.checker.Checker(nc)
check = ccf.checker.Checker()
with primary.client("user0") as c:
log_id = 44
@ -234,8 +235,8 @@ def test_historical_query(network, args):
primary, _ = network.find_primary()
with primary.client() as nc:
check_commit = infra.checker.Checker(nc)
check = infra.checker.Checker()
check_commit = ccf.checker.Checker(nc)
check = ccf.checker.Checker()
with primary.client("user0") as c:
log_id = 10
@ -254,8 +255,8 @@ def test_historical_query(network, args):
timeout = 15
found = False
headers = {
infra.clients.CCF_TX_VIEW_HEADER: str(view),
infra.clients.CCF_TX_SEQNO_HEADER: str(seqno),
ccf.clients.CCF_TX_VIEW_HEADER: str(view),
ccf.clients.CCF_TX_SEQNO_HEADER: str(seqno),
}
params = {"id": log_id}
end_time = time.time() + timeout
@ -307,7 +308,7 @@ def test_forwarding_frontends(network, args):
primary, backup = network.find_primary_and_any_backup()
with primary.client() as nc:
check_commit = infra.checker.Checker(nc)
check_commit = ccf.checker.Checker(nc)
ack = network.consortium.get_any_active_member().ack(backup)
check_commit(ack)
@ -321,7 +322,7 @@ def test_update_lua(network, args):
LOG.info("Updating Lua application")
primary, _ = network.find_primary()
check = infra.checker.Checker()
check = ccf.checker.Checker()
# Create a new lua application file (minimal app)
new_app_file = "new_lua_app.lua"
@ -370,7 +371,7 @@ def test_view_history(network, args):
LOG.warning("Skipping view reconstruction in PBFT")
return network
check = infra.checker.Checker()
check = ccf.checker.Checker()
for node in network.get_joined_nodes():
with node.client("user0") as c:
@ -474,7 +475,7 @@ def test_tx_statuses(network, args):
primary, _ = network.find_primary()
with primary.client("user0") as c:
check = infra.checker.Checker()
check = ccf.checker.Checker()
r = c.rpc("/app/log/private", {"id": 0, "msg": "Ignored"})
check(r)
# Until this tx is globally committed, poll for the status of this and some other
@ -524,7 +525,7 @@ def run(args):
else None
)
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb,
) as network:
network.start_and_join(args)

Просмотреть файл

@ -4,9 +4,10 @@ import os
import json
import http
import random
import infra.ccf
import infra.network
import infra.proc
import infra.e2e_args
import ccf.checker
from loguru import logger as LOG
@ -25,7 +26,7 @@ def run(args):
scenario_dir = os.path.dirname(args.scenario)
# SNIPPET_START: create_network
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes
) as network:
network.start_and_join(args)
@ -35,8 +36,8 @@ def run(args):
with primary.client() as mc:
check = infra.checker.Checker()
check_commit = infra.checker.Checker(mc)
check = ccf.checker.Checker()
check_commit = ccf.checker.Checker(mc)
for connection in scenario["connections"]:
with (

Просмотреть файл

@ -2,7 +2,7 @@
# Licensed under the Apache 2.0 License.
import infra.e2e_args
import infra.ccf
import infra.network
import suite.test_suite as s
import suite.test_requirements as reqs
import infra.logging_app as app
@ -51,7 +51,7 @@ def run(args):
hosts = ["localhost", "localhost"]
txs = app.LoggingTxs()
network = infra.ccf.Network(
network = infra.network.Network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, txs=txs
)
network.start_and_join(args)

Просмотреть файл

@ -2,13 +2,14 @@
# Licensed under the Apache 2.0 License.
import time
import math
import infra.ccf
import infra.network
import infra.proc
import infra.e2e_args
import ccf.checker
import http
import suite.test_requirements as reqs
from infra.tx_status import TxStatus
from ccf.tx_status import TxStatus
from loguru import logger as LOG
# This test starts from a given number of nodes (hosts), commits
@ -37,7 +38,7 @@ def wait_for_seqno_to_commit(seqno, view, nodes):
"""
Wait for a specific seqno at a specific view to be committed on all nodes.
"""
for _ in range(infra.ccf.Network.replication_delay * 10):
for _ in range(infra.network.Network.replication_delay * 10):
up_to_date_f = []
for f in nodes:
with f.client() as c:
@ -67,10 +68,10 @@ def run(args):
# if one node stops
hosts = ["localhost"] * (4 if args.consensus == "pbft" else 3)
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
check = infra.checker.Checker()
check = ccf.checker.Checker()
network.start_and_join(args)
current_view = None
@ -118,7 +119,7 @@ def run(args):
try:
primary, _ = network.find_primary()
assert False, "Primary should not be found"
except infra.ccf.PrimaryNotFound:
except infra.network.PrimaryNotFound:
pass
LOG.success(

Просмотреть файл

@ -3,7 +3,7 @@
import os
import sys
import subprocess
import infra.ccf
import infra.network
import infra.path
import infra.proc
import infra.notification
@ -90,7 +90,7 @@ def run(args):
else None
)
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
network.start_and_join(args)

Просмотреть файл

@ -1,11 +1,11 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.e2e_args
import infra.ccf
import infra.network
import infra.proc
import infra.remote
import infra.crypto
import infra.ledger
import ccf.ledger
from infra.proposal import ProposalState
import http
import os
@ -55,7 +55,7 @@ def run(args):
votes_issued = 0
withdrawals_issued = 0
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
network.start_and_join(args)
@ -66,7 +66,7 @@ def run(args):
for l in os.listdir(ledger_directory):
if l.endswith("_1"):
ledger_filename = os.path.join(ledger_directory, l)
ledger = infra.ledger.Ledger(ledger_filename)
ledger = ccf.ledger.Ledger(ledger_filename)
(
original_proposals,
original_votes,
@ -75,7 +75,7 @@ def run(args):
LOG.info("Add new member proposal (implicit vote)")
new_member_proposal, _ = network.consortium.generate_and_propose_new_member(
primary, curve=infra.ccf.ParticipantsCurve.secp256k1
primary, curve=infra.network.ParticipantsCurve.secp256k1
)
proposals_issued += 1
@ -92,7 +92,7 @@ def run(args):
LOG.info("Create new proposal but withdraw it before it is accepted")
new_member_proposal, _ = network.consortium.generate_and_propose_new_member(
primary, curve=infra.ccf.ParticipantsCurve.secp256k1
primary, curve=infra.network.ParticipantsCurve.secp256k1
)
proposals_issued += 1

202
tests/infra/LICENSE Normal file
Просмотреть файл

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Просмотреть файл

@ -6,13 +6,13 @@ import os
import time
import http
import random
import infra.ccf
import infra.network
import infra.proc
import infra.checker
import ccf.checker
import infra.node
import infra.crypto
import infra.member
import infra.proposal_generator
import ccf.proposal_generator
from infra.proposal import ProposalState
from loguru import logger as LOG
@ -96,7 +96,7 @@ class Consortium:
new_member_id, curve, self.common_dir, self.share_script, self.key_generator
)
proposal, vote = infra.proposal_generator.new_member(
proposal, vote = ccf.proposal_generator.new_member(
os.path.join(self.common_dir, f"member{new_member_id}_cert.pem"),
os.path.join(self.common_dir, f"member{new_member_id}_enc_pubk.pem"),
)
@ -195,9 +195,7 @@ class Consortium:
return proposals
def retire_node(self, remote_node, node_to_retire):
proposal_body, vote = infra.proposal_generator.retire_node(
node_to_retire.node_id
)
proposal_body, vote = ccf.proposal_generator.retire_node(node_to_retire.node_id)
proposal = self.get_any_active_member().propose(remote_node, proposal_body)
self.vote_using_majority(remote_node, proposal)
@ -213,7 +211,7 @@ class Consortium:
):
raise ValueError(f"Node {node_id} does not exist in state PENDING")
proposal_body, vote = infra.proposal_generator.trust_node(node_id)
proposal_body, vote = ccf.proposal_generator.trust_node(node_id)
proposal = self.get_any_active_member().propose(remote_node, proposal_body)
self.vote_using_majority(remote_node, proposal)
@ -224,7 +222,7 @@ class Consortium:
raise ValueError(f"Node {node_id} does not exist in state TRUSTED")
def retire_member(self, remote_node, member_to_retire):
proposal_body, vote = infra.proposal_generator.retire_member(
proposal_body, vote = ccf.proposal_generator.retire_member(
member_to_retire.member_id
)
proposal = self.get_any_active_member().propose(remote_node, proposal_body)
@ -237,26 +235,26 @@ class Consortium:
proposal and make members vote to transition the network to state
OPEN.
"""
proposal_body, vote = infra.proposal_generator.open_network()
proposal_body, vote = ccf.proposal_generator.open_network()
proposal = self.get_any_active_member().propose(remote_node, proposal_body)
self.vote_using_majority(
remote_node, proposal, wait_for_global_commit=(not pbft_open)
)
self.check_for_service(remote_node, infra.ccf.ServiceStatus.OPEN, pbft_open)
self.check_for_service(remote_node, infra.network.ServiceStatus.OPEN, pbft_open)
def rekey_ledger(self, remote_node):
proposal_body, vote = infra.proposal_generator.rekey_ledger()
proposal_body, vote = ccf.proposal_generator.rekey_ledger()
proposal = self.get_any_active_member().propose(remote_node, proposal_body)
return self.vote_using_majority(remote_node, proposal)
def update_recovery_shares(self, remote_node):
proposal_body, vote = infra.proposal_generator.update_recovery_shares()
proposal_body, vote = ccf.proposal_generator.update_recovery_shares()
proposal = self.get_any_active_member().propose(remote_node, proposal_body)
return self.vote_using_majority(remote_node, proposal)
def add_user(self, remote_node, user_id):
user_cert = []
proposal, vote = infra.proposal_generator.new_user(
proposal, vote = ccf.proposal_generator.new_user(
os.path.join(self.common_dir, f"user{user_id}_cert.pem")
)
@ -268,30 +266,30 @@ class Consortium:
self.add_user(remote_node, u)
def remove_user(self, remote_node, user_id):
proposal, vote = infra.proposal_generator.remove_user(user_id)
proposal, vote = ccf.proposal_generator.remove_user(user_id)
proposal = self.get_any_active_member().propose(remote_node, proposal)
self.vote_using_majority(remote_node, proposal)
def set_lua_app(self, remote_node, app_script_path):
proposal_body, vote = infra.proposal_generator.set_lua_app(app_script_path)
proposal_body, vote = ccf.proposal_generator.set_lua_app(app_script_path)
proposal = self.get_any_active_member().propose(remote_node, proposal_body)
return self.vote_using_majority(remote_node, proposal)
def set_js_app(self, remote_node, app_script_path):
proposal_body, vote = infra.proposal_generator.set_js_app(app_script_path)
proposal_body, vote = ccf.proposal_generator.set_js_app(app_script_path)
proposal = self.get_any_active_member().propose(remote_node, proposal_body)
return self.vote_using_majority(remote_node, proposal)
def accept_recovery(self, remote_node):
proposal_body, vote = infra.proposal_generator.accept_recovery()
proposal_body, vote = ccf.proposal_generator.accept_recovery()
proposal = self.get_any_active_member().propose(remote_node, proposal_body)
return self.vote_using_majority(remote_node, proposal)
def recover_with_shares(self, remote_node, defunct_network_enc_pubk):
submitted_shares_count = 0
with remote_node.client() as nc:
check_commit = infra.checker.Checker(nc)
check_commit = ccf.checker.Checker(nc)
for m in self.get_active_members():
r = m.get_and_submit_recovery_share(
@ -307,7 +305,7 @@ class Consortium:
assert "End of recovery procedure initiated" not in r.result
def set_recovery_threshold(self, remote_node, recovery_threshold):
proposal_body, vote = infra.proposal_generator.set_recovery_threshold(
proposal_body, vote = ccf.proposal_generator.set_recovery_threshold(
recovery_threshold
)
proposal = self.get_any_active_member().propose(remote_node, proposal_body)
@ -315,12 +313,12 @@ class Consortium:
return self.vote_using_majority(remote_node, proposal)
def add_new_code(self, remote_node, new_code_id):
proposal_body, vote = infra.proposal_generator.new_node_code(new_code_id)
proposal_body, vote = ccf.proposal_generator.new_node_code(new_code_id)
proposal = self.get_any_active_member().propose(remote_node, proposal_body)
return self.vote_using_majority(remote_node, proposal)
def add_new_user_code(self, remote_node, new_code_id):
proposal_body, vote = infra.proposal_generator.new_user_code(new_code_id)
proposal_body, vote = ccf.proposal_generator.new_user_code(new_code_id)
proposal = self.get_any_active_member().propose(remote_node, proposal_body)
return self.vote_using_majority(remote_node, proposal)

Просмотреть файл

@ -3,7 +3,7 @@
import argparse
import os
import infra.path
import infra.ccf
import infra.network
import sys
@ -123,9 +123,9 @@ def cli_args(add=lambda x: None, parser=None, accept_unknown=False):
parser.add_argument(
"--participants-curve",
help="Curve to use for member and user identities",
default=infra.ccf.ParticipantsCurve.secp384r1.name,
type=lambda curve: infra.ccf.ParticipantsCurve[curve],
choices=list(infra.ccf.ParticipantsCurve),
default=infra.network.ParticipantsCurve.secp384r1.name,
type=lambda curve: infra.network.ParticipantsCurve[curve],
choices=list(infra.network.ParticipantsCurve),
)
parser.add_argument(
"--join-timer",

Просмотреть файл

@ -1,7 +1,8 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.checker
import ccf.checker
import ccf.clients
import suite.test_requirements as reqs
import time
@ -88,8 +89,8 @@ class LoggingTxs:
):
LOG.success(f"Applying {number_txs} logging txs to node {remote_node.node_id}")
with remote_node.client() as mc:
check_commit = infra.checker.Checker(mc)
check_commit_n = infra.checker.Checker(mc, self.notifications_queue)
check_commit = ccf.checker.Checker(mc)
check_commit_n = ccf.checker.Checker(mc, self.notifications_queue)
with remote_node.client(self.user) as uc:
for _ in range(number_txs):
@ -118,7 +119,7 @@ class LoggingTxs:
break
except (
TimeoutError,
infra.clients.CCFConnectionException,
ccf.clients.CCFConnectionException,
):
LOG.debug("Network is unavailable")
if not ignore_failures:
@ -133,7 +134,7 @@ class LoggingTxs:
try:
network.wait_for_node_commit_sync(consensus)
break
except (TimeoutError, infra.clients.CCFConnectionException):
except (TimeoutError, ccf.clients.CCFConnectionException):
LOG.error("Timeout error while waiting for nodes to sync")
if not ignore_failures:
raise
@ -165,7 +166,7 @@ class LoggingTxs:
LOG.warning("User frontend is not yet opened")
time.sleep(0.1)
else:
check = infra.checker.Checker(uc)
check = ccf.checker.Checker(uc)
check(
rep, result={"msg": txs[idx]},
)

Просмотреть файл

@ -6,6 +6,8 @@ import infra.proc
import infra.node
import infra.proposal
import infra.crypto
import ccf.clients
import ccf.checker
import http
import os
import base64
@ -110,9 +112,7 @@ class Member:
# can only commit after it has successfully joined and caught up.
# Given that the retry timer on join RPC is 4 seconds, anything less is very
# likely to time out!
infra.checker.wait_for_global_commit(
mc, r.seqno, r.view, True, timeout=6
)
ccf.checker.wait_for_global_commit(mc, r.seqno, r.view, True, timeout=6)
return r
@ -175,4 +175,4 @@ class Member:
log_output=True,
)
res.check_returncode()
return infra.clients.Response.from_raw(res.stdout)
return ccf.clients.Response.from_raw(res.stdout)

Просмотреть файл

@ -5,12 +5,12 @@ import time
import logging
from contextlib import contextmanager
from enum import Enum, IntEnum
import infra.clients
from ccf.clients import CCFConnectionException
import infra.path
import infra.proc
import infra.node
import infra.consortium
from infra.tx_status import TxStatus
from ccf.tx_status import TxStatus
import random
from math import ceil
@ -158,7 +158,8 @@ class Network:
def _add_node(self, node, lib_name, args, target_node=None, recovery=False):
forwarded_args = {
arg: getattr(args, arg) for arg in infra.ccf.Network.node_args_to_forward
arg: getattr(args, arg)
for arg in infra.network.Network.node_args_to_forward
}
# Contact primary if no target node is set
@ -196,7 +197,8 @@ class Network:
LOG.info("Opening CCF service on {}".format(hosts))
forwarded_args = {
arg: getattr(args, arg) for arg in infra.ccf.Network.node_args_to_forward
arg: getattr(args, arg)
for arg in infra.network.Network.node_args_to_forward
}
for i, node in enumerate(self.nodes):
@ -522,7 +524,7 @@ class Network:
break
else:
assert "Primary unknown" in res.error, res.error
except infra.clients.CCFConnectionException:
except CCFConnectionException:
pass
if primary_id is not None:
break

Просмотреть файл

@ -6,7 +6,7 @@ from enum import Enum
import infra.remote
import infra.net
import infra.path
import infra.clients
import ccf.clients
import os
import socket
@ -238,7 +238,7 @@ class Node:
assert (
rep.error is None and rep.result is not None
), f"An error occured after node {self.node_id} joined the network: {rep.error}"
except infra.clients.CCFConnectionException:
except ccf.clients.CCFConnectionException:
raise TimeoutError(f"Node {self.node_id} failed to join the network")
def get_ledger(self):
@ -257,7 +257,7 @@ class Node:
"binary_dir": self.binary_dir,
}
akwargs.update(kwargs)
return infra.clients.client(self.pubhost, self.rpc_port, **akwargs)
return ccf.clients.client(self.pubhost, self.rpc_port, **akwargs)
def suspend(self):
self.remote.suspend()

Просмотреть файл

@ -1,7 +1,7 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import os
import infra.ccf
import infra.network
import infra.remote
from loguru import logger as LOG
@ -34,7 +34,7 @@ class CCFRemoteClient(object):
self.BIN = infra.path.build_bin_path(bin_path)
# strip out the config from the path
self.common_dir = infra.ccf.get_common_folder_name(workspace, label)
self.common_dir = infra.network.get_common_folder_name(workspace, label)
self.DEPS = [
os.path.join(self.common_dir, "user1_cert.pem"),

Просмотреть файл

@ -4,7 +4,7 @@ import getpass
import time
import logging
from random import seed
import infra.ccf
import infra.network
import infra.proc
import infra.remote_client
import infra.rates
@ -81,7 +81,7 @@ def run(get_command, args):
LOG.info("Starting nodes on {}".format(hosts))
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
network.start_and_join(args)

Просмотреть файл

@ -3,8 +3,8 @@
from threading import Timer
import time
import suite.test_requirements as reqs
import infra.ccf
import random
import ccf.clients
from enum import Enum
from loguru import logger as LOG
@ -62,7 +62,7 @@ def wait_for_late_joiner(old_node, late_joiner, strict=False, timeout=60):
if local_commit >= old_node_lc:
return LateJoinerStatus.Ready
time.sleep(1)
except (TimeoutError, infra.clients.CCFConnectionException,) as exc:
except (TimeoutError, ccf.clients.CCFConnectionException,) as exc:
LOG.warning(
f"late joiner with node id {late_joiner.node_id} isn't quite ready yet: {exc}"
)

Просмотреть файл

@ -3,9 +3,9 @@
import http
import infra.e2e_args
import infra.ccf
import infra.network
import infra.consortium
import infra.proposal_generator
import ccf.proposal_generator
from infra.proposal import ProposalState
import random
@ -39,7 +39,7 @@ def test_add_member(network, args):
primary, _ = network.find_primary()
new_member = network.consortium.generate_and_add_new_member(
primary, curve=infra.ccf.ParticipantsCurve(args.participants_curve).next()
primary, curve=infra.network.ParticipantsCurve(args.participants_curve).next()
)
try:
@ -113,7 +113,7 @@ def assert_recovery_shares_update(func, network, args, **kwargs):
def run(args):
hosts = ["localhost"] * (4 if args.consensus == "pbft" else 2)
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
network.start_and_join(args)
@ -134,7 +134,7 @@ def run(args):
new_member,
) = network.consortium.generate_and_propose_new_member(
remote_node=primary,
curve=infra.ccf.ParticipantsCurve(args.participants_curve).next(),
curve=infra.network.ParticipantsCurve(args.participants_curve).next(),
)
LOG.info("Check proposal has been recorded in open state")
@ -189,7 +189,7 @@ def run(args):
assert response.status == params_error
LOG.info("New non-active member should get insufficient rights response")
proposal_trust_0, _ = infra.proposal_generator.trust_node(0)
proposal_trust_0, _ = ccf.proposal_generator.trust_node(0)
try:
new_member.propose(primary, proposal_trust_0)
assert (
@ -209,7 +209,7 @@ def run(args):
assert trust_node_proposal_0.state == infra.proposal.ProposalState.Accepted
LOG.info("New member makes a new proposal")
proposal_trust_1, _ = infra.proposal_generator.trust_node(1)
proposal_trust_1, _ = ccf.proposal_generator.trust_node(1)
trust_node_proposal = new_member.propose(primary, proposal_trust_1)
LOG.debug("Other members (non proposer) are unable to withdraw new proposal")

Просмотреть файл

@ -1,11 +1,12 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.ccf
import infra.network
import infra.proc
import infra.notification
import infra.net
import suite.test_requirements as reqs
import infra.e2e_args
import ccf.checker
from loguru import logger as LOG
@ -17,8 +18,8 @@ def test(network, args, notifications_queue=None):
primary, _ = network.find_primary_and_any_backup()
with primary.client() as mc:
check_commit = infra.checker.Checker(mc, notifications_queue)
check = infra.checker.Checker()
check_commit = ccf.checker.Checker(mc, notifications_queue)
check = ccf.checker.Checker()
msg = "Hello world"
@ -60,7 +61,7 @@ def run(args):
else None
)
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
network.start_and_join(args)

Просмотреть файл

@ -1,7 +1,7 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.e2e_args
import infra.ccf
import infra.network
import infra.proc
import suite.test_requirements as reqs
import time
@ -62,7 +62,7 @@ def test_add_node_untrusted_code(network, args):
network.create_and_add_pending_node(
"liblua_generic", "localhost", args, timeout=3
)
except infra.ccf.CodeIdNotFound as err:
except infra.network.CodeIdNotFound as err:
code_not_found_exception = err
assert (
@ -87,7 +87,7 @@ def test_retire_node(network, args):
def run(args):
hosts = ["localhost", "localhost"]
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
network.start_and_join(args)

Просмотреть файл

@ -1,8 +1,9 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.e2e_args
import infra.ccf
import infra.network
import infra.logging_app as app
import ccf.checker
import suite.test_requirements as reqs
import time
@ -16,7 +17,7 @@ def test(network, args):
ledger = primary.get_ledger()
defunct_network_enc_pubk = network.store_current_network_encryption_key()
recovered_network = infra.ccf.Network(
recovered_network = infra.network.Network(
network.hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, network
)
recovered_network.start_in_recovery(args, ledger)
@ -31,7 +32,7 @@ def test_share_resilience(network, args):
ledger = old_primary.get_ledger()
defunct_network_enc_pubk = network.store_current_network_encryption_key()
recovered_network = infra.ccf.Network(
recovered_network = infra.network.Network(
network.hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, network
)
recovered_network.start_in_recovery(args, ledger)
@ -50,7 +51,7 @@ def test_share_resilience(network, args):
last_member_to_submit = m
break
check_commit = infra.checker.Checker(nc)
check_commit = ccf.checker.Checker(nc)
check_commit(
m.get_and_submit_recovery_share(primary, defunct_network_enc_pubk)
)
@ -88,7 +89,7 @@ def test_share_resilience(network, args):
)
recovered_network.consortium.check_for_service(
new_primary, infra.ccf.ServiceStatus.OPEN,
new_primary, infra.network.ServiceStatus.OPEN,
)
return recovered_network
@ -98,7 +99,7 @@ def run(args):
txs = app.LoggingTxs()
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb, txs=txs
) as network:
network.start_and_join(args)

Просмотреть файл

@ -1,6 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.ccf
import infra.network
import infra.notification
import suite.test_requirements as reqs
import infra.logging_app as app
@ -19,7 +19,7 @@ def test(network, args):
def run(args):
hosts = ["localhost", "localhost"]
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb,
) as network:
network.start_and_join(args)

Просмотреть файл

@ -1,6 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.ccf
import infra.network
import infra.proc
import infra.notification
import infra.net
@ -21,7 +21,7 @@ def run(args):
random.seed(args.seed)
txs = app.LoggingTxs()
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb, txs=txs
) as network:
network.start_and_join(args)

Просмотреть файл

@ -1,5 +1,4 @@
wheel
netifaces
paramiko
msgpack
loguru

Просмотреть файл

@ -4,9 +4,10 @@ import os
import sys
import json
import http
import infra.ccf
import infra.network
import infra.proc
import infra.e2e_args
import ccf.checker
from loguru import logger as LOG
@ -82,13 +83,13 @@ def run(args):
else:
methods_without_schema.add(method)
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes
) as network:
network.start_and_join(args)
primary, _ = network.find_primary()
check = infra.checker.Checker()
check = ccf.checker.Checker()
with primary.client("user0") as user_client:
LOG.info("user frontend")

Просмотреть файл

@ -1,7 +1,7 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.e2e_args
import infra.ccf
import infra.network
import time
import sys
@ -18,12 +18,13 @@ def run(args):
format="<green>[{time:YYYY-MM-DD HH:mm:ss.SSS}]</green> {message}",
)
LOG.disable("infra")
LOG.disable("ccf")
LOG.info("Starting {} CCF nodes...".format(len(hosts)))
if args.enclave_type == "virtual":
LOG.warning("Virtual mode enabled")
with infra.ccf.network(
with infra.network.network(
hosts=hosts, binary_directory=args.binary_dir, dbg_nodes=args.debug_nodes
) as network:
if args.recover:

Просмотреть файл

@ -1,7 +1,7 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.ccf
import infra.network
import functools
from loguru import logger as LOG

Просмотреть файл

@ -1,6 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.ccf
import infra.network
import infra.proc
import infra.notification
import infra.net
@ -25,7 +25,7 @@ def run(args):
random.seed(args.seed)
txs = app.LoggingTxs()
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb, txs=txs
) as network:
network.start_and_join(args)

Просмотреть файл

@ -10,6 +10,7 @@ if [ ! -f "env/bin/activate" ]
fi
source env/bin/activate
pip install -q -U -e ../python/
pip install -q -U -r ../tests/requirements.txt
ctest "$@"

Просмотреть файл

@ -1,6 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.ccf
import infra.network
import infra.proc
import infra.notification
import infra.net
@ -30,7 +30,7 @@ def run(args):
else None
)
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
network.start_and_join(args)

Просмотреть файл

@ -1,6 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
import infra.ccf
import infra.network
import infra.proc
import infra.notification
import infra.net
@ -56,7 +56,7 @@ def run(args):
else None
)
with infra.ccf.network(
with infra.network.network(
hosts, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb
) as network:
network.start_and_join(args)