From 68a52fe6068827d580b8eb54ead5ec14d78bdf17 Mon Sep 17 00:00:00 2001 From: Yaorong <38514341+leeyr338@users.noreply.github.com> Date: Fri, 18 Oct 2019 17:50:38 +0800 Subject: [PATCH] [skip audit]Pre release 1.0.1 (#873) * Separate bin_dir and work_dir * Add docker diretory for build release images * Bug fix for handling quota used error when Revert. (#870) --- cita-executor/core/src/libexecutor/block.rs | 14 +- docker/README.md | 32 +++ docker/release/Dockerfile | 29 ++ docker/release/entrypoint.sh | 13 + docker/sample/docker-compose.yml | 73 +++++ scripts/cita.sh | 280 ++++++++++---------- scripts/create_cita_config.py | 26 +- 7 files changed, 314 insertions(+), 153 deletions(-) create mode 100644 docker/README.md create mode 100644 docker/release/Dockerfile create mode 100644 docker/release/entrypoint.sh create mode 100644 docker/sample/docker-compose.yml diff --git a/cita-executor/core/src/libexecutor/block.rs b/cita-executor/core/src/libexecutor/block.rs index 9a56628a0..21eb3e81a 100644 --- a/cita-executor/core/src/libexecutor/block.rs +++ b/cita-executor/core/src/libexecutor/block.rs @@ -199,12 +199,14 @@ impl ExecutedBlock { _ => Some(ReceiptError::Internal), }); - let tx_quota_used = - if receipt_error.is_some() && receipt_error != Some(ReceiptError::Internal) { - t.gas - } else { - ret.quota_used - }; + let tx_quota_used = if receipt_error.is_some() + && receipt_error != Some(ReceiptError::Internal) + && receipt_error != Some(ReceiptError::Reverted) + { + t.gas + } else { + ret.quota_used + }; // Note: quota_used in Receipt is self.current_quota_used, this will be // handled by get_rich_receipt() while getting a single transaction receipt. diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 000000000..7090cbf01 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,32 @@ +# Docker image for CITA release + +## Build image + + Script is comming soon! + +## Usage + +### Using docker command + +* Create a CITA chain config. + +```shell +docker run -v `pwd`:/opt/cita-run cita/cita-release:1.0.0-secp256k1-sha3 cita create --super_admin "0x37d1c7449bfe76fe9c445e626da06265e9377601" --nodes "127.0.0.1:4000" +``` + +Tips: CITA image uses `/opt/cita-run` as its default work_dir, so you should mount `pwd` to it. + +* Setup & run CITA + +```shell +docker run -d -p 1337:1337 -v `pwd`:/opt/cita-run cita/cita-release:1.0.0-secp256k1-sha3 /bin/bash -c 'cita setup test-chain/0 && cita start test-chain/0 && sleep infinity' +``` + +Cool! Just two simple command, you have build a CITA blockchain in you computer. +Enjoy it! + +### Using docker-compose + +```shell +cd sample && docker-compose up +``` \ No newline at end of file diff --git a/docker/release/Dockerfile b/docker/release/Dockerfile new file mode 100644 index 000000000..cb5944161 --- /dev/null +++ b/docker/release/Dockerfile @@ -0,0 +1,29 @@ +FROM cita/cita-run:ubuntu-18.04-20190829 +LABEL maintainer="Cryptape Technologies " + +## Install CITA release here +ARG ENCRYPTION_ALG=secp256k1 +ARG HASH_ALG=sha3 +RUN mkdir -p /opt/cita + +WORKDIR /opt/cita +COPY cita_${ENCRYPTION_ALG}_${HASH_ALG}.tar.gz . + +# Keep tar package here for md5 test +RUN tar -xf cita_${ENCRYPTION_ALG}_${HASH_ALG}.tar.gz \ + && mv cita_${ENCRYPTION_ALG}_${HASH_ALG}/* /opt/cita \ + && rm -rf cita_${ENCRYPTION_ALG}_${HASH_ALG} + +# Set CITA_HOME +ENV CITA_HOME=/opt/cita +# Set PATH to cita binary +ENV PATH=/opt/cita/bin:${PATH} +## End of install CITA release + +COPY entrypoint.sh /usr/bin/ +RUN chmod +x /usr/bin/entrypoint.sh + +WORKDIR /opt/cita-run + +ENTRYPOINT ["/usr/bin/entrypoint.sh"] +CMD ["cita", "bebop", "help"] diff --git a/docker/release/entrypoint.sh b/docker/release/entrypoint.sh new file mode 100644 index 000000000..6532d0c34 --- /dev/null +++ b/docker/release/entrypoint.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +if [ "${USER_ID}" = "0" ] || [ "${USER_ID}" = "" ]; then + # Run with "root" + exec "$@" +else + # Add local user(name=user) use USER_ID + useradd --shell /bin/bash -u "${USER_ID}" -o -c "" -d /opt user + # Can use sudo without password + echo "user ALL=(ALL) NOPASSWD:ALL" >>/etc/sudoers + + exec /usr/sbin/gosu user "$@" +fi diff --git a/docker/sample/docker-compose.yml b/docker/sample/docker-compose.yml new file mode 100644 index 000000000..b3db928b5 --- /dev/null +++ b/docker/sample/docker-compose.yml @@ -0,0 +1,73 @@ +version: '3' + +services: + config: + container_name: config + environment: + - USER_ID + - SUPER_ADMIN=0x4b5ae4567ad5d9fb92bc9afd6a657e6fa13a2523 + - NODES_CONFIG=node0:4000, node1:4001 + image: cita/cita-release:1.0.0-secp256k1-sha3 + hostname: config + networks: + main: + aliases: + - config + volumes: + - ./:/opt/cita-run + command: | + bash -c ' + echo "Create config files..."; + cita create --super_admin "$$SUPER_ADMIN" --nodes "$$NODES_CONFIG"; + echo "Done config"' + + node0: + container_name: node0 + depends_on: + - config + environment: + - USER_ID + image: cita/cita-release:1.0.0-secp256k1-sha3 + hostname: node0 + networks: + main: + aliases: + - node0 + volumes: + - ./:/opt/cita-run + ports: + - "1337:1337" + command: | + bash -c ' + while [[ ! -d /opt/cita-run/test-chain ]]; do sleep 1; done; + sleep 10; + cita setup test-chain/0; + cita start test-chain/0; + sleep infinity' + + node1: + container_name: node1 + depends_on: + - config + environment: + - USER_ID + image: cita/cita-release:1.0.0-secp256k1-sha3 + hostname: node1 + networks: + main: + aliases: + - node1 + volumes: + - ./:/opt/cita-run + ports: + - "1338:1338" + command: | + bash -c ' + while [[ ! -d /opt/cita-run/test-chain ]]; do sleep 1; done; + sleep 10; + cita setup test-chain/1; + cita start test-chain/1; + sleep infinity' + +networks: + main: \ No newline at end of file diff --git a/scripts/cita.sh b/scripts/cita.sh index cf99eca75..885e5983e 100755 --- a/scripts/cita.sh +++ b/scripts/cita.sh @@ -15,7 +15,7 @@ fi # Add cita scripts into system executable paths export PATH=$CITA_BIN:$PATH CITA_SCRIPTS=$(dirname "$CITA_BIN")/scripts -SERVICES=( forever auth bft chain executor jsonrpc network ) +SERVICES=(forever auth bft chain executor jsonrpc network) SCRIPT=$(basename "$0") # DIAGNOSTIC COMMANDS PING_STATUS="" @@ -23,7 +23,7 @@ PING_STATUS="" sudo() { set -o noglob - if [ "$(whoami)" == "root" ] ; then + if [ "$(whoami)" == "root" ]; then "$@" else /usr/bin/sudo "$@" @@ -115,17 +115,16 @@ config() { # SERVICE CONTROL COMMANDS start_rabbitmq() { # Config and start RabbitMQ - if [[ $(uname) == 'Darwin' ]] - then - pgrep -f rabbitmq-server > /dev/null || brew services restart rabbitmq > /dev/null + if [[ $(uname) == 'Darwin' ]]; then + pgrep -f rabbitmq-server >/dev/null || brew services restart rabbitmq >/dev/null RABBITMQ_USER=cita_monitor RABBITMQ_PASSWD=cita_monitor - sudo rabbitmqctl list_vhosts | grep "${NODE_NAME}" > /dev/null || sudo rabbitmqctl add_vhost "${NODE_NAME}" > /dev/null - sudo rabbitmqctl set_permissions -p "${NODE_NAME}" guest '.*' '.*' '.*' > /dev/null - sudo rabbitmq-plugins enable rabbitmq_management > /dev/null - sudo rabbitmqctl list_users | grep ${RABBITMQ_USER} > /dev/null || sudo rabbitmqctl add_user ${RABBITMQ_USER} ${RABBITMQ_PASSWD} > /dev/null - sudo rabbitmqctl set_user_tags ${RABBITMQ_USER} monitoring > /dev/null - sudo rabbitmqctl set_permissions -p "${NODE_NAME}" ${RABBITMQ_USER} '.*' '.*' '.*' > /dev/null + sudo rabbitmqctl list_vhosts | grep "${NODE_NAME}" >/dev/null || sudo rabbitmqctl add_vhost "${NODE_NAME}" >/dev/null + sudo rabbitmqctl set_permissions -p "${NODE_NAME}" guest '.*' '.*' '.*' >/dev/null + sudo rabbitmq-plugins enable rabbitmq_management >/dev/null + sudo rabbitmqctl list_users | grep ${RABBITMQ_USER} >/dev/null || sudo rabbitmqctl add_user ${RABBITMQ_USER} ${RABBITMQ_PASSWD} >/dev/null + sudo rabbitmqctl set_user_tags ${RABBITMQ_USER} monitoring >/dev/null + sudo rabbitmqctl set_permissions -p "${NODE_NAME}" ${RABBITMQ_USER} '.*' '.*' '.*' >/dev/null else flock -x -w 30 /tmp/rabbitmq.lock -c "ps -C rabbitmq-server > /dev/null || sudo /etc/init.d/rabbitmq-server restart > /dev/null" RABBITMQ_USER=cita_monitor @@ -140,10 +139,9 @@ start_rabbitmq() { } do_setup() { - for i in {1..3} - do + for i in {1..3}; do start_rabbitmq - if curl http://localhost:15672/ > /dev/null 2>&1; then + if curl http://localhost:15672/ >/dev/null 2>&1; then return 0 fi done @@ -170,15 +168,15 @@ do_start() { if [ -z "${debug}" ]; then cita-forever -c "${config}" start 2>&1 else - RUST_LOG=cita_auth=${debug},cita_chain=${debug},cita_executor=${debug},cita_jsonrpc=${debug},cita_network=${debug},cita_bft=${debug},\ -core_executor=${debug},engine=${debug},jsonrpc_types=${debug},libproto=${debug},proof=${debug},txpool=${debug},core=${debug} \ - cita-forever -c "${config}" start 2>&1 + RUST_LOG=cita_auth=${debug},cita_chain=${debug},cita_executor=${debug},cita_jsonrpc=${debug},cita_network=${debug},cita_bft=${debug},core_executor=${debug},engine=${debug},jsonrpc_types=${debug},libproto=${debug},proof=${debug},txpool=${debug},core=${debug} \ + cita-forever \ + -c "${config}" start 2>&1 fi # Wait for the node to come up WAIT=3 while [ $WAIT -gt 0 ]; do - WAIT="$(( WAIT - 1 ))" + WAIT="$((WAIT - 1))" sleep 1 do_ping if [ "${PING_STATUS}" == "pong" ]; then @@ -192,7 +190,7 @@ core_executor=${debug},engine=${debug},jsonrpc_types=${debug},libproto=${debug}, } do_stop() { - cita-forever stop > /dev/null 2>&1 + cita-forever stop >/dev/null 2>&1 # Make sure node stopped do_ping @@ -234,10 +232,9 @@ do_status() { while IFS= read -r -d '' pid_file; do pid=$(cat "${pid_file}") pgrep -f "${pid}" || true - done < <(find . -name "*.pid") + done < <(find . -name "*.pid") } - # SCRIPTING COMMANDS do_clean() { # Clean empty node always successfully @@ -249,11 +246,11 @@ do_clean() { # Move data/ and logs/ into backup directory backup_dir=$(pwd)/backup.$(date -Iseconds) mkdir -p "${backup_dir}" - if [ -e "${NODE_DATA_DIR}" ] ; then + if [ -e "${NODE_DATA_DIR}" ]; then echo "mv ${NODE_DATA_DIR} ${backup_dir}" mv "${NODE_DATA_DIR}" "${backup_dir}" fi - if [ -e "${NODE_LOGS_DIR}" ] ; then + if [ -e "${NODE_LOGS_DIR}" ]; then echo "mv ${NODE_LOGS_DIR} ${backup_dir}" mv "${NODE_LOGS_DIR}" "${backup_dir}" fi @@ -270,11 +267,11 @@ do_backup() { # Copy data/ and logs/ into backup directory backup_dir="$(pwd)/backup.$(date -Iseconds)" mkdir -p "${backup_dir}" - if [ -e "${NODE_DATA_DIR}" ] ; then + if [ -e "${NODE_DATA_DIR}" ]; then echo "cp -r ${NODE_DATA_DIR} ${backup_dir}/" cp -r "${NODE_DATA_DIR}" "${backup_dir}"/ fi - if [ -e "${NODE_LOGS_DIR}" ] ; then + if [ -e "${NODE_LOGS_DIR}" ]; then echo "cp -r ${NODE_LOGS_DIR} ${backup_dir}/" cp -r "${NODE_LOGS_DIR}" "${backup_dir}"/ fi @@ -291,7 +288,7 @@ do_logs() { fi for service in "${SERVICES[@]}"; do - if [[ $service = "$service0" || cita-"${service}" = "$service0" ]]; then + if [[ $service == "$service0" || cita-"${service}" == "$service0" ]]; then tail -f "${NODE_LOGS_DIR}/cita-${service}.log" exit 0 fi @@ -304,7 +301,7 @@ do_logs() { do_logrotate() { local logs logs=$(ls -1 "${NODE_LOGS_DIR}"/cita-*.log) - cita-forever logrotate > /dev/null 2>&1 + cita-forever logrotate >/dev/null 2>&1 # Wait for services to rotate their logs sleep 2 @@ -319,14 +316,14 @@ clear_rabbit_mq() { local mq_command local mq_command="curl -i -u guest:guest -H content-type:application/json -XDELETE http://localhost:15672/api/queues/${TNODE}" - "$mq_command"/auth > /dev/null 2>&1 || true - "$mq_command"/chain > /dev/null 2>&1 || true - "$mq_command"/consensus > /dev/null 2>&1 || true - "$mq_command"/jsonrpc > /dev/null 2>&1 || true - "$mq_command"/network > /dev/null 2>&1 || true - "$mq_command"/network_tx > /dev/null 2>&1 || true - "$mq_command"/network_consensus > /dev/null 2>&1 || true - "$mq_command"/executor > /dev/null 2>&1 || true + "$mq_command"/auth >/dev/null 2>&1 || true + "$mq_command"/chain >/dev/null 2>&1 || true + "$mq_command"/consensus >/dev/null 2>&1 || true + "$mq_command"/jsonrpc >/dev/null 2>&1 || true + "$mq_command"/network >/dev/null 2>&1 || true + "$mq_command"/network_tx >/dev/null 2>&1 || true + "$mq_command"/network_consensus >/dev/null 2>&1 || true + "$mq_command"/executor >/dev/null 2>&1 || true } node_down_check() { @@ -348,108 +345,117 @@ node_up_check() { parse_command() { local command="$1" case "${command}" in - help) - help - exit 0 - ;; + help) + help + exit 0 + ;; - usage) - usage - exit 0 - ;; + usage) + usage + exit 0 + ;; - create) - config "$@" - exit 0 - ;; + create) + config "$@" + exit 0 + ;; - append) - config "$@" - exit 0 - ;; - - setup) - do_setup - ;; - - start) - # TODO: should not do so, but present tests need this - do_stop - node_down_check - - # Make sure the RabbitMQ fresh - clear_rabbit_mq - - do_start "$3" "$4" - ;; - - stop) - node_up_check - do_stop - ;; - - restart) - node_up_check - do_stop - - # Make sure the RabbitMQ fresh - clear_rabbit_mq - - do_start "$3" "$4" - ;; - - ping) - do_ping - if [ "${PING_STATUS}" == "pong" ]; then - echo "pong" - else - echo "Node '${NODE_NAME}' not responding to pings." - exit 1 - fi - ;; - - top) - node_up_check - do_top - ;; - # deprecated, use 'top' instead - stat) - node_up_check - do_top - ;; - # similar to 'top', but ... ? - status) - do_status - ;; - - logrotate) - do_logrotate - ;; - - logs) - do_logs "$3" - ;; - - backup) - node_down_check - do_backup - ;; - - clean) - node_down_check - do_clean - ;; - - *) - usage - ;; + append) + config "$@" + exit 0 + ;; + + setup) + do_setup + ;; + + start) + # TODO: should not do so, but present tests need this + do_stop + node_down_check + + # Make sure the RabbitMQ fresh + clear_rabbit_mq + + do_start "$3" "$4" + ;; + + stop) + node_up_check + do_stop + ;; + + restart) + node_up_check + do_stop + + # Make sure the RabbitMQ fresh + clear_rabbit_mq + + do_start "$3" "$4" + ;; + + ping) + do_ping + if [ "${PING_STATUS}" == "pong" ]; then + echo "pong" + else + echo "Node '${NODE_NAME}' not responding to pings." + exit 1 + fi + ;; + + top) + node_up_check + do_top + ;; + # deprecated, use 'top' instead + stat) + node_up_check + do_top + ;; + # similar to 'top', but ... ? + status) + do_status + ;; + + logrotate) + do_logrotate + ;; + + logs) + do_logs "$3" + ;; + + backup) + node_down_check + do_backup + ;; + + clean) + node_down_check + do_clean + ;; + + *) + usage + ;; esac } +# Test CITA is running in docker. +cita_in_docker() { + if grep docker /proc/1/cgroup -qa; then + return 0 + else + return 1 + fi +} + main() { - if [ "$1" != "bebop" ]; then - if stat "$CITA_BIN"/cita-env > /dev/null 2>&1; then + if [[ "$1" != "bebop" ]] && ! cita_in_docker; then + if stat "$CITA_BIN"/cita-env >/dev/null 2>&1; then "$CITA_BIN"/cita-env bin/cita bebop "$@" else echo -e "\033[0;31mPlease run this command after build 🎨" @@ -458,12 +464,18 @@ main() { exit 0 fi - # Delete the verbose parameters - set -- "${@:2}" + # Delete the verbose parameters. + # If use the command 'cita bebop', it should delete 2 verbose parameters. + if [[ "$1" == "bebop" ]]; then + set -- "${@:2}" + else + set -- "${@:1}" + fi + local command=$1 # Commands not depend on $NODE_PATH - local indie=( help usage create append ) + local indie=(help usage create append) if [[ "${indie[*]}" =~ $command ]]; then parse_command "$@" fi @@ -490,12 +502,12 @@ main() { fi # Enter the node directory - pushd . > /dev/null + pushd . >/dev/null cd "${NODE_PATH}" parse_command "$@" - popd > /dev/null + popd >/dev/null exit 0 } diff --git a/scripts/create_cita_config.py b/scripts/create_cita_config.py index 1dd034975..62d0e4848 100755 --- a/scripts/create_cita_config.py +++ b/scripts/create_cita_config.py @@ -14,6 +14,9 @@ import time DEFAULT_PREVHASH = '0x{:064x}'.format(0) +CITA_HOME = os.getenv('CITA_HOME', os.path.abspath( + os.path.join(os.path.dirname(__file__), os.pardir))) + def update_search_paths(work_dir): """Add new path to the search path.""" @@ -240,10 +243,11 @@ def create_genesis(self, timestamp, init_token, resource_dir): os.path.join(self.configs_dir, 'resource'), False) prevhash = DEFAULT_PREVHASH if not prevhash else str(prevhash) - timestamp = str(int(time.time() * 1000)) if not timestamp else str(timestamp) + timestamp = str(int(time.time() * 1000) + ) if not timestamp else str(timestamp) - process = subprocess.Popen(["./bin/create-genesis",self.contracts_dir, self.contracts_docs_dir, - self.init_data_file, self.genesis_path, timestamp, init_token, prevhash]) + process = subprocess.Popen([os.path.join(CITA_HOME, 'bin/create-genesis'), self.contracts_dir, self.contracts_docs_dir, + self.init_data_file, self.genesis_path, timestamp, init_token, prevhash]) process.wait() def append_node(self, node): @@ -326,8 +330,8 @@ def append_node(self, node): def run_subcmd_create(args, work_dir): info = ChainInfo(args.chain_name, work_dir) info.template_create_from_arguments( - args, os.path.join(work_dir, 'scripts/contracts'), - os.path.join(work_dir, 'scripts/config_tool/default_config')) + args, os.path.join(CITA_HOME, 'scripts/contracts'), + os.path.join(CITA_HOME, 'scripts/config_tool/default_config')) info.create_init_data(args.super_admin, args.contract_arguments) info.create_genesis(args.timestamp, args.init_token, args.resource_dir) info.enable_tls = args.enable_tls @@ -419,7 +423,7 @@ def parse_arguments(): pcreate.add_argument( '--init_token', - type=lambda x: hex(int(x,16)), + type=lambda x: hex(int(x, 16)), default=hex(int("0xffffffffffffffffffffffffff", 16)), help='Init token for this chain, INIT_TOKEN is a hexadecimal number') @@ -442,8 +446,7 @@ def parse_arguments(): pappend.add_argument( '--address', - help= - 'The address of new node. Will generate a new address (with privkey) if not set.' + help='The address of new node. Will generate a new address (with privkey) if not set.' ) args = parser.parse_args() @@ -501,17 +504,14 @@ def parse_arguments(): def main(): # All source files are relative path. - work_dir = os.path.abspath( - os.path.join(os.path.dirname(__file__), os.pardir)) - - update_search_paths(work_dir) + update_search_paths(CITA_HOME) args = parse_arguments() - funcs_router = { SUBCMD_CREATE: run_subcmd_create, SUBCMD_APPEND: run_subcmd_append, } + work_dir = os.path.abspath(os.curdir) funcs_router[args.subcmd](args, work_dir)