diff --git a/.github/workflows/create-release.yaml b/.github/workflows/create-release.yaml new file mode 100644 index 0000000..ab29265 --- /dev/null +++ b/.github/workflows/create-release.yaml @@ -0,0 +1,185 @@ +name: Create release + +on: + push: + branches: [ main ] + tags: + - "v*.*.*" + pull_request: + branches: [ main ] + +jobs: + create_release: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-22.04 ] + + python-version: [ 3.11 ] + node-version: [ 18.16.0 ] + + ganache-version: [ 7.8.0 ] + + solc-version: [ v0.8.20 ] + + env: + SOLC_BIN: ${{ github.workspace }}/build/solc-static-linux + SOLC_FLAGS: >- + --optimize --optimize-runs 200 + --revert-strings strip + --via-ir + --overwrite + --base-path ${{ github.workspace }} + --output-dir ${{ github.workspace }}/build/ + SOLC_VER_CMD: >- + ${{ github.workspace }}/build/solc-static-linux + --version | tail -n 1 | sed -e "s/^Version: //g" + RELE_NOTE: ${{ github.workspace }}/build/release_note.md + + name: A job to create a release + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Installing Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Installing Python packages + run: | + python3 -m pip install --requirement ${{ github.workspace }}/utils/gas_cost_eval_requirements.txt + + - name: Installing Node ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + + - name: Installing NPM packages + run: | + npm install -g ganache@${{ matrix.ganache-version }} + + - name: Installing Solc compiler + run: | + mkdir -p ${{ github.workspace }}/build/ + curl -fsSL -o ${SOLC_BIN} \ + https://github.com/ethereum/solidity/releases/download/${{ matrix.solc-version }}/solc-static-linux + chmod +x ${SOLC_BIN} + + - name: Compiling contracts for contracts/IASRootCertMgr.sol + run: | + ${SOLC_BIN} ${SOLC_FLAGS} --bin ${{ github.workspace }}/contracts/IASRootCertMgr.sol + ${SOLC_BIN} ${SOLC_FLAGS} --abi ${{ github.workspace }}/contracts/IASRootCertMgr.sol + + - name: Compiling contracts for contracts/IASReportCertMgr.sol + run: | + ${SOLC_BIN} ${SOLC_FLAGS} --bin ${{ github.workspace }}/contracts/IASReportCertMgr.sol + ${SOLC_BIN} ${SOLC_FLAGS} --abi ${{ github.workspace }}/contracts/IASReportCertMgr.sol + + - name: Compiling contracts for contracts/DecentServerCertMgr.sol + run: | + ${SOLC_BIN} ${SOLC_FLAGS} --bin ${{ github.workspace }}/contracts/DecentServerCertMgr.sol + ${SOLC_BIN} ${SOLC_FLAGS} --abi ${{ github.workspace }}/contracts/DecentServerCertMgr.sol + + - name: Compiling contracts for tests/HelloWorldApp.sol + run: | + ${SOLC_BIN} ${SOLC_FLAGS} --bin ${{ github.workspace }}/tests/HelloWorldApp.sol + ${SOLC_BIN} ${SOLC_FLAGS} --abi ${{ github.workspace }}/tests/HelloWorldApp.sol + + - name: Prepare binaries for gas cost evaluation + working-directory: ${{ github.workspace }}/build + run: | + mkdir -p contracts + cp IASRootCertMgr.bin contracts/IASRootCertMgr.bin + cp IASRootCertMgr.abi contracts/IASRootCertMgr.abi + cp IASReportCertMgr.bin contracts/IASReportCertMgr.bin + cp IASReportCertMgr.abi contracts/IASReportCertMgr.abi + cp DecentServerCertMgr.bin contracts/DecentServerCertMgr.bin + cp DecentServerCertMgr.abi contracts/DecentServerCertMgr.abi + mkdir -p tests + cp HelloWorldApp.bin tests/HelloWorldApp.bin + cp HelloWorldApp.abi tests/HelloWorldApp.abi + + - name: Run gas cost evaluation + run: | + python3 ${{ github.workspace }}/utils/GanacheContractTests.py eval + + - name: Calculating checksums of the binary + working-directory: ${{ github.workspace }}/build + run: | + sha256sum solc-static-linux >> checksums.txt + sha256sum IASRootCertMgr.bin >> checksums.txt + sha256sum IASRootCertMgr.abi >> checksums.txt + sha256sum IASReportCertMgr.bin >> checksums.txt + sha256sum IASReportCertMgr.abi >> checksums.txt + sha256sum DecentServerCertMgr.bin >> checksums.txt + sha256sum DecentServerCertMgr.abi >> checksums.txt + sha256sum HelloWorldApp.bin >> checksums.txt + sha256sum HelloWorldApp.abi >> checksums.txt + + - name: Generate release note + working-directory: ${{ github.workspace }}/build + run: | + echo "# Release note" >> ${RELE_NOTE} + echo "" >> ${RELE_NOTE} + echo "## Contracts" >> ${RELE_NOTE} + echo "- contracts/IASRootCertMgr.sol" >> ${RELE_NOTE} + echo "- contracts/IASReportCertMgr.sol" >> ${RELE_NOTE} + echo "- contracts/DecentServerCertMgr.sol" >> ${RELE_NOTE} + echo "- tests/HelloWorldApp.sol" >> ${RELE_NOTE} + echo "" >> ${RELE_NOTE} + echo "## Build configurations" >> ${RELE_NOTE} + echo "- OS: \`${{ matrix.os }}\`" >> ${RELE_NOTE} + echo "- Solc version: \`$(bash -c "${SOLC_VER_CMD}")\`" >> ${RELE_NOTE} + echo "- Compiler Flags: \`${SOLC_FLAGS}\`" >> ${RELE_NOTE} + echo "" >> ${RELE_NOTE} + echo "## Checksums" >> ${RELE_NOTE} + echo "\`\`\`" >> ${RELE_NOTE} + cat checksums.txt >> ${RELE_NOTE} + echo "\`\`\`" >> ${RELE_NOTE} + echo "" >> ${RELE_NOTE} + echo "## Gas Cost Evaluations" >> ${RELE_NOTE} + echo "\`\`\`json" >> ${RELE_NOTE} + cat gas_costs.json >> ${RELE_NOTE} + echo "" >> ${RELE_NOTE} + echo "\`\`\`" >> ${RELE_NOTE} + echo "" >> ${RELE_NOTE} + + - name: Echo release note + run: | + cat ${{ github.workspace }}/build/release_note.md + + - name: Release for non-tagged commit + uses: actions/upload-artifact@v3 + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + with: + name: non_tagged_release + path: | + ${{ github.workspace }}/build/release_note.md + ${{ github.workspace }}/build/IASRootCertMgr.bin + ${{ github.workspace }}/build/IASRootCertMgr.abi + ${{ github.workspace }}/build/IASReportCertMgr.bin + ${{ github.workspace }}/build/IASReportCertMgr.abi + ${{ github.workspace }}/build/DecentServerCertMgr.bin + ${{ github.workspace }}/build/DecentServerCertMgr.abi + ${{ github.workspace }}/build/HelloWorldApp.bin + ${{ github.workspace }}/build/HelloWorldApp.abi + ${{ github.workspace }}/build/gas_costs.json + + - name: Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + body_path: ${{ github.workspace }}/build/release_note.md + files: | + ${{ github.workspace }}/build/IASRootCertMgr.bin + ${{ github.workspace }}/build/IASRootCertMgr.abi + ${{ github.workspace }}/build/IASReportCertMgr.bin + ${{ github.workspace }}/build/IASReportCertMgr.abi + ${{ github.workspace }}/build/DecentServerCertMgr.bin + ${{ github.workspace }}/build/DecentServerCertMgr.abi + ${{ github.workspace }}/build/HelloWorldApp.bin + ${{ github.workspace }}/build/HelloWorldApp.abi + ${{ github.workspace }}/build/gas_costs.json diff --git a/.github/workflows/solidity-unittesting.yaml b/.github/workflows/solidity-unittesting.yaml new file mode 100644 index 0000000..d292fd9 --- /dev/null +++ b/.github/workflows/solidity-unittesting.yaml @@ -0,0 +1,108 @@ +name: Running Solidity Unit Tests for Decent RA contracts + + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + + +jobs: + run_sol_contracts_job: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-22.04 ] + solc-version: [ 0.8.20 ] + chain-fork: [ shanghai ] + opt-runs: [ 200 ] + + name: A job to run solidity unit tests on github actions CI + steps: + + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Run Solidity Unit Testing for ens-contracts Tests + uses: EthereumRemix/sol-test@v1.1 + with: + test-path: 'tests/ens-contracts' + compiler-version: ${{ matrix.solc-version }} + optimize: true + optimizer-runs: ${{ matrix.opt-runs }} + hard-fork: ${{ matrix.chain-fork }} + + - name: Run Solidity Unit Testing for RSA Tests + uses: EthereumRemix/sol-test@v1.1 + with: + test-path: 'tests/RSA' + compiler-version: ${{ matrix.solc-version }} + optimize: true + optimizer-runs: ${{ matrix.opt-runs }} + hard-fork: ${{ matrix.chain-fork }} + + - name: Run Solidity Unit Testing for ECDSA Tests + uses: EthereumRemix/sol-test@v1.1 + with: + test-path: 'tests/Ecdsa' + compiler-version: ${{ matrix.solc-version }} + optimize: true + optimizer-runs: ${{ matrix.opt-runs }} + hard-fork: ${{ matrix.chain-fork }} + + - name: Run Solidity Unit Testing for RLP Tests + uses: EthereumRemix/sol-test@v1.1 + with: + test-path: 'tests/RLP' + compiler-version: ${{ matrix.solc-version }} + optimize: true + optimizer-runs: ${{ matrix.opt-runs }} + hard-fork: ${{ matrix.chain-fork }} + + - name: Run Solidity Unit Testing for x509-forest-of-trust Tests + uses: EthereumRemix/sol-test@v1.1 + with: + test-path: 'tests/x509-forest-of-trust' + compiler-version: ${{ matrix.solc-version }} + optimize: true + optimizer-runs: ${{ matrix.opt-runs }} + hard-fork: ${{ matrix.chain-fork }} + + - name: Run Solidity Unit Testing for Decent Common Tests + uses: EthereumRemix/sol-test@v1.1 + with: + test-path: 'tests/DecentCommon' + compiler-version: ${{ matrix.solc-version }} + optimize: true + optimizer-runs: ${{ matrix.opt-runs }} + hard-fork: ${{ matrix.chain-fork }} + + - name: Run Solidity Unit Testing for Decent IAS Tests + uses: EthereumRemix/sol-test@v1.1 + with: + test-path: 'tests/DecentIAS' + compiler-version: ${{ matrix.solc-version }} + optimize: true + optimizer-runs: ${{ matrix.opt-runs }} + hard-fork: ${{ matrix.chain-fork }} + + - name: Run Solidity Unit Testing for Decent Server Tests + uses: EthereumRemix/sol-test@v1.1 + with: + test-path: 'tests/DecentServer' + compiler-version: ${{ matrix.solc-version }} + optimize: true + optimizer-runs: ${{ matrix.opt-runs }} + hard-fork: ${{ matrix.chain-fork }} + + - name: Run Solidity Unit Testing for Decent App Tests + uses: EthereumRemix/sol-test@v1.1 + with: + test-path: 'tests/DecentApp' + compiler-version: ${{ matrix.solc-version }} + optimize: true + optimizer-runs: ${{ matrix.opt-runs }} + hard-fork: ${{ matrix.chain-fork }} diff --git a/Makefile b/Makefile index d69a5ce..eaecf5f 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,24 @@ -NODEENV_CONFIG := ./utils/nodeenv.ini -NODEENV_REQ := ./utils/nodeenv-requirements.txt MODULES := \ contracts \ tests +SOLC_VERSION := v0.8.20 +MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) +CURRENT_DIR := $(dir $(MKFILE_PATH)) +SOLC_BIN := $(CURRENT_DIR)/build/solc-static-linux -all: build/nodeenv.state $(MODULES) +all: $(SOLC_BIN) $(MODULES) -build/nodeenv.state: $(NODEENV_CONFIG) $(NODEENV_REQ) - which nodeenv || (echo "ERROR: nodeenv is not installed" && exit 1) - nodeenv \ - --config=$(NODEENV_CONFIG) \ - --requirements=$(NODEENV_REQ) \ - build/nodeenv - touch $@ +$(SOLC_BIN): + mkdir -p $(dir $(SOLC_BIN)) && \ + curl -fsSL -o $(SOLC_BIN) \ + https://github.com/ethereum/solidity/releases/download/$(SOLC_VERSION)/solc-static-linux \ + && \ + chmod +x $(SOLC_BIN) + + +solc_bin: $(SOLC_BIN) $(MODULES): @@ -26,7 +30,7 @@ $(addprefix clean_,$(MODULES)): clean: $(addprefix clean_,$(MODULES)) - rm -rf build/nodeenv build/nodeenv.state + rm -rf $(SOLC_BIN) -.PHONY: all clean $(MODULES) $(addprefix clean_,$(MODULES)) +.PHONY: all clean solc_bin $(MODULES) $(addprefix clean_,$(MODULES)) diff --git a/contracts/DecentAppCert.sol b/contracts/DecentAppCert.sol index 77b4b09..0922b4f 100644 --- a/contracts/DecentAppCert.sol +++ b/contracts/DecentAppCert.sol @@ -4,9 +4,10 @@ pragma solidity ^0.8.17; import {Asn1Decode} from "../libs/asn1-decode/Asn1Decode.sol"; import {BytesUtils} from "../libs/ens-contracts/BytesUtils.sol"; + import { Interface_DecentServerCertMgr -} from "../contracts/Interface_DecentServerCertMgr.sol"; +} from "./Interface_DecentServerCertMgr.sol"; import {LibSecp256k1Sha256} from "./LibSecp256k1Sha256.sol"; import {OIDs} from "./Constants.sol"; import {X509CertNodes} from "./X509CertNodes.sol"; diff --git a/contracts/DecentServerCert.sol b/contracts/DecentServerCert.sol index 7f8cb26..f6c4653 100644 --- a/contracts/DecentServerCert.sol +++ b/contracts/DecentServerCert.sol @@ -5,11 +5,12 @@ pragma solidity ^0.8.17; import {Asn1Decode} from "../libs/asn1-decode/Asn1Decode.sol"; import {Base64} from "../libs/base64/base64.sol"; import {BytesUtils} from "../libs/ens-contracts/BytesUtils.sol"; +import {RLPReader} from "../libs/Solidity-RLP/contracts/RLPReader.sol"; + import {IASReportCert} from "./IASReportCert.sol"; import {Interface_IASReportCertMgr} from "./Interface_IASReportCertMgr.sol"; import {LibSecp256k1Sha256} from "./LibSecp256k1Sha256.sol"; import {OIDs} from "./Constants.sol"; -import {RLPReader} from "../libs/Solidity-RLP/contracts/RLPReader.sol"; import {X509CertNodes} from "./X509CertNodes.sol"; import {X509Extension} from "./X509Extension.sol"; diff --git a/contracts/IASReportCert.sol b/contracts/IASReportCert.sol index 4f58a4b..f375d7d 100644 --- a/contracts/IASReportCert.sol +++ b/contracts/IASReportCert.sol @@ -3,10 +3,12 @@ pragma solidity ^0.8.17; import {Asn1Decode} from "../libs/asn1-decode/Asn1Decode.sol"; -import {OIDs, Names} from "./Constants.sol"; import {LibRsaSha256} from "../libs/sig-verify-algs/LibRsaSha256.sol"; + +import {OIDs, Names} from "./Constants.sol"; import {X509CertNodes} from "./X509CertNodes.sol"; import {X509Name} from "./X509Name.sol"; +import {X509Timestamp} from "./X509Timestamp.sol"; library IASReportCert { @@ -14,6 +16,7 @@ library IASReportCert { using Asn1Decode for bytes; using X509CertNodes for X509CertNodes.CertNodesObj; using X509CertNodes for X509CertNodes.CertTbsNodesObj; + using X509Timestamp for X509CertNodes.CertTbsNodesObj; //===== constants ===== diff --git a/contracts/IASReportCertMgr.sol b/contracts/IASReportCertMgr.sol index 3feed9e..bcc53d1 100644 --- a/contracts/IASReportCertMgr.sol +++ b/contracts/IASReportCertMgr.sol @@ -2,9 +2,10 @@ pragma solidity ^0.8.17; +import {LibRsaSha256} from "../libs/sig-verify-algs/LibRsaSha256.sol"; + import {Interface_IASRootCertMgr} from "./Interface_IASRootCertMgr.sol"; import {IASReportCert} from "./IASReportCert.sol"; -import {LibRsaSha256} from "../libs/sig-verify-algs/LibRsaSha256.sol"; import {X509CertNodes} from "./X509CertNodes.sol"; diff --git a/contracts/IASRootCert.sol b/contracts/IASRootCert.sol index f5fd13d..dfa54a3 100644 --- a/contracts/IASRootCert.sol +++ b/contracts/IASRootCert.sol @@ -3,10 +3,12 @@ pragma solidity ^0.8.17; import {Asn1Decode} from "../libs/asn1-decode/Asn1Decode.sol"; -import {OIDs, Names} from "./Constants.sol"; import {LibRsaSha256} from "../libs/sig-verify-algs/LibRsaSha256.sol"; + +import {OIDs, Names} from "./Constants.sol"; import {X509CertNodes} from "./X509CertNodes.sol"; import {X509Name} from "./X509Name.sol"; +import {X509Timestamp} from "./X509Timestamp.sol"; library IASRootCert { @@ -14,6 +16,7 @@ library IASRootCert { using Asn1Decode for bytes; using X509CertNodes for X509CertNodes.CertNodesObj; using X509CertNodes for X509CertNodes.CertTbsNodesObj; + using X509Timestamp for X509CertNodes.CertTbsNodesObj; //===== structs ===== diff --git a/contracts/LibSecp256k1Sha256.sol b/contracts/LibSecp256k1Sha256.sol index 0a85c63..e649d75 100644 --- a/contracts/LibSecp256k1Sha256.sol +++ b/contracts/LibSecp256k1Sha256.sol @@ -4,6 +4,7 @@ pragma solidity >=0.8.0 <0.9.0; import {Asn1Decode} from "../libs/asn1-decode/Asn1Decode.sol"; import {BytesUtils} from "../libs/ens-contracts/BytesUtils.sol"; + import {X509CertNodes} from "./X509CertNodes.sol"; diff --git a/contracts/Makefile b/contracts/Makefile index 72fc022..db9cc27 100644 --- a/contracts/Makefile +++ b/contracts/Makefile @@ -4,61 +4,61 @@ CONTRACTS := \ IASReportCertMgr \ DecentServerCertMgr +MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) +CURRENT_DIR := $(dir $(MKFILE_PATH)) +ROOT_DIR := $(CURRENT_DIR)/.. +BUILD_DIR := $(ROOT_DIR)/build + +SOLC_BIN := $(BUILD_DIR)/solc-static-linux +OPTIMIZE_RUN := 200 +SOLC_FLAGS := --optimize --optimize-runs $(OPTIMIZE_RUN) \ + --revert-strings strip \ + --via-ir \ + --overwrite \ + --base-path $(ROOT_DIR) \ + --output-dir $(BUILD_DIR)/$(MODULE_NAME)/all/ + CHECKSUM_BIN := openssl sha256 -all: $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .abi,$(CONTRACTS))) \ - $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .bin,$(CONTRACTS))) \ - $(addprefix ../build/$(MODULE_NAME)/,checksums.txt) +all: $(CONTRACTS) checksums -../build/nodeenv.state: - $(MAKE) -C .. build/nodeenv.state +$(SOLC_BIN): + $(MAKE) -C .. solc_bin -../build/$(MODULE_NAME)/%.bin: %.sol ../build/nodeenv.state +$(BUILD_DIR)/$(MODULE_NAME)/%.bin: %.sol $(SOLC_BIN) ( \ - . ../build/nodeenv/bin/activate && \ - solcjs --optimize --optimize-runs 200 \ - --bin \ - --include-path node_modules/ --base-path .. \ - --output-dir ../build/$(MODULE_NAME)/ \ - $< && \ - mv ../build/$(MODULE_NAME)/$(MODULE_NAME)_$(basename $<)_sol_$(basename $<).bin \ - ../build/$(MODULE_NAME)/$(basename $<).bin && \ - rm -f ../build/$(MODULE_NAME)/*_sol_*.bin \ + $(SOLC_BIN) --bin $(SOLC_FLAGS) $< && \ + cp $(BUILD_DIR)/$(MODULE_NAME)/all/$(basename $<).bin \ + $(BUILD_DIR)/$(MODULE_NAME)/$(basename $<).bin \ ) -../build/$(MODULE_NAME)/%.abi: %.sol ../build/nodeenv.state +$(BUILD_DIR)/$(MODULE_NAME)/%.abi: %.sol $(SOLC_BIN) ( \ - . ../build/nodeenv/bin/activate && \ - solcjs --optimize --optimize-runs 200 \ - --abi \ - --include-path node_modules/ --base-path .. \ - --output-dir ../build/$(MODULE_NAME)/ \ - $< && \ - mv ../build/$(MODULE_NAME)/$(MODULE_NAME)_$(basename $<)_sol_$(basename $<).abi \ - ../build/$(MODULE_NAME)/$(basename $<).abi && \ - rm -f ../build/$(MODULE_NAME)/*_sol_*.abi \ + $(SOLC_BIN) --abi $(SOLC_FLAGS) $< && \ + cp $(BUILD_DIR)/$(MODULE_NAME)/all/$(basename $<).abi \ + $(BUILD_DIR)/$(MODULE_NAME)/$(basename $<).abi \ ) -../build/$(MODULE_NAME)/checksums.txt: $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .abi,$(CONTRACTS))) \ - $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .bin,$(CONTRACTS))) +$(CONTRACTS): %: $(BUILD_DIR)/$(MODULE_NAME)/%.abi $(BUILD_DIR)/$(MODULE_NAME)/%.bin + + +$(BUILD_DIR)/$(MODULE_NAME)/checksums.txt: $(CONTRACTS) ( \ - cd ../build/$(MODULE_NAME); \ + cd $(BUILD_DIR)/$(MODULE_NAME); \ $(CHECKSUM_BIN) $(addsuffix .abi,$(CONTRACTS)) $(addsuffix .bin,$(CONTRACTS)) > checksums.txt; \ ) -checksums: ../build/$(MODULE_NAME)/checksums.txt +checksums: $(BUILD_DIR)/$(MODULE_NAME)/checksums.txt clean: - rm -f $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .abi,$(CONTRACTS))) \ - $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .bin,$(CONTRACTS))) \ - $(addprefix ../build/$(MODULE_NAME)/,checksums.txt) + rm -rf $(BUILD_DIR)/$(MODULE_NAME)/ -.PHONY: all clean checksums +.PHONY: all clean checksums $(CONTRACTS) diff --git a/contracts/X509CertNodes.sol b/contracts/X509CertNodes.sol index f513e72..c0c16b1 100644 --- a/contracts/X509CertNodes.sol +++ b/contracts/X509CertNodes.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.17; import {Asn1Decode, NodePtr} from "../libs/asn1-decode/Asn1Decode.sol"; -import {X509Parser} from "../libs/x509-forest-of-trust/X509Parser.sol"; library X509CertNodes { @@ -100,22 +99,4 @@ library X509CertNodes { certNodes.sigNode = certDer.nextSiblingOf(certNodes.algTypeNode); } - function getValidityTimestamps( - CertTbsNodesObj memory tbsNodes, - bytes memory certDer - ) - internal - pure - returns (uint256 notBefore, uint256 notAfter) - { - uint256 notBeforeNode = certDer.firstChildOf(tbsNodes.validityNode); - uint256 notAfterNode = certDer.nextSiblingOf(notBeforeNode); - - notBefore = - X509Parser.toTimestamp(certDer.bytesAt(notBeforeNode)); - - notAfter = - X509Parser.toTimestamp(certDer.bytesAt(notAfterNode)); - } - } diff --git a/contracts/X509Name.sol b/contracts/X509Name.sol index cbb95a8..f9c2534 100644 --- a/contracts/X509Name.sol +++ b/contracts/X509Name.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.17; import {Asn1Decode} from "../libs/asn1-decode/Asn1Decode.sol"; + import {OIDs} from "./Constants.sol"; diff --git a/contracts/X509Timestamp.sol b/contracts/X509Timestamp.sol new file mode 100644 index 0000000..8eac382 --- /dev/null +++ b/contracts/X509Timestamp.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + + +import {Asn1Decode} from "../libs/asn1-decode/Asn1Decode.sol"; +import {X509Parser} from "../libs/x509-forest-of-trust/X509Parser.sol"; + +import {X509CertNodes} from "./X509CertNodes.sol"; + + +library X509Timestamp { + + using Asn1Decode for bytes; + + //===== functions ===== + + function getValidityTimestamps( + X509CertNodes.CertTbsNodesObj memory tbsNodes, + bytes memory certDer + ) + internal + pure + returns (uint256 notBefore, uint256 notAfter) + { + uint256 notBeforeNode = certDer.firstChildOf(tbsNodes.validityNode); + uint256 notAfterNode = certDer.nextSiblingOf(notBeforeNode); + + notBefore = + X509Parser.toTimestamp(certDer.bytesAt(notBeforeNode)); + + notAfter = + X509Parser.toTimestamp(certDer.bytesAt(notAfterNode)); + } + +} diff --git a/tests/Decent/09_DecentServerCert_test.sol b/tests/Decent/09_DecentServerCert_test.sol deleted file mode 100644 index 7689acd..0000000 --- a/tests/Decent/09_DecentServerCert_test.sol +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.4.17 <0.9.0; - -// This import is automatically injected by Remix -import "remix_tests.sol"; - -// This import is required to use custom transaction context -// Although it may fail compilation in 'Solidity Compiler' plugin -// But it will work fine in 'Solidity Unit Testing' plugin -import "remix_accounts.sol"; - - -import {DecentServerCert_proxy} from "./09_DecentServerCert.sol"; -import {IASReportCertMgr} from "../../contracts/IASReportCertMgr.sol"; -import {IASRootCertMgr} from "../../contracts/IASRootCertMgr.sol"; -import {TestCerts} from "../TestCerts.sol"; - - -// File name has to end with '_test.sol', this file can contain more than one testSuite contracts -contract DecentServerCert_testSuit { - - //===== member variables ===== - - address m_testProxyAddr; - - /// 'beforeAll' runs before all other tests - /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll' - function beforeAll() public { - m_testProxyAddr = address(new DecentServerCert_proxy()); - } - - function strFindTest() public { - try DecentServerCert_proxy(m_testProxyAddr).strFindTest() { - Assert.ok(true, "strFindTest should not throw"); - } catch Error(string memory reason) { - Assert.ok(false, reason); - } catch (bytes memory /*lowLevelData*/) { - Assert.ok(false, "unexpected error - strFindTest"); - } - } - - function jsonSimpleReadValPosTest() public { - try DecentServerCert_proxy(m_testProxyAddr).jsonSimpleReadValPosTest() { - Assert.ok(true, "jsonSimpleReadValPosTest should not throw"); - } catch Error(string memory reason) { - Assert.ok(false, reason); - } catch (bytes memory /*lowLevelData*/) { - Assert.ok(false, "unexpected error - jsonSimpleReadValPosTest"); - } - } - - function verifyEPIDAttestationRepTest() public { - IASRootCertMgr rootCertMgr = - new IASRootCertMgr(TestCerts.IAS_ROOT_CERT_DER); - IASReportCertMgr iasReportCertMgr = - new IASReportCertMgr(address(rootCertMgr)); - - try DecentServerCert_proxy(m_testProxyAddr).verifyEPIDAttestationRepTest( - address(iasReportCertMgr) - ) { - Assert.ok(true, "verifyEPIDAttestationRepTest should not throw"); - } catch Error(string memory reason) { - Assert.ok(false, reason); - } catch (bytes memory /*lowLevelData*/) { - Assert.ok(false, "unexpected error - verifyEPIDAttestationRepTest"); - } - } - - function verifySelfSignTest() public { - try DecentServerCert_proxy(m_testProxyAddr).verifySelfSignTest() { - Assert.ok(true, "verifySelfSignTest should not throw"); - } catch Error(string memory reason) { - Assert.ok(false, reason); - } catch (bytes memory /*lowLevelData*/) { - Assert.ok(false, "unexpected error - verifySelfSignTest"); - } - } - - function extractDecentServerKeyTest() public { - try DecentServerCert_proxy(m_testProxyAddr).extractDecentServerKeyTest() { - Assert.ok(true, "extractDecentServerKeyTest should not throw"); - } catch Error(string memory reason) { - Assert.ok(false, reason); - } catch (bytes memory /*lowLevelData*/) { - Assert.ok(false, "unexpected error - extractDecentServerKeyTest"); - } - } - - function loadCertTest() public { - IASRootCertMgr rootCertMgr = - new IASRootCertMgr(TestCerts.IAS_ROOT_CERT_DER); - IASReportCertMgr iasReportCertMgr = - new IASReportCertMgr(address(rootCertMgr)); - - try DecentServerCert_proxy(m_testProxyAddr).loadCertTest( - address(iasReportCertMgr) - ) { - Assert.ok(true, "loadCertTest should not throw"); - } catch Error(string memory reason) { - Assert.ok(false, reason); - } catch (bytes memory /*lowLevelData*/) { - Assert.ok(false, "unexpected error - loadCertTest"); - } - } - -} diff --git a/tests/DecentApp/00_PredeployA_IASRoot_test.sol b/tests/DecentApp/00_PredeployA_IASRoot_test.sol new file mode 100644 index 0000000..44869a6 --- /dev/null +++ b/tests/DecentApp/00_PredeployA_IASRoot_test.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.17 <0.9.0; + +// This import is automatically injected by Remix +import "remix_tests.sol"; + +// This import is required to use custom transaction context +// Although it may fail compilation in 'Solidity Compiler' plugin +// But it will work fine in 'Solidity Unit Testing' plugin +import "remix_accounts.sol"; + + +import {IASRootCertMgr} from "../../contracts/IASRootCertMgr.sol"; + +import {TestCerts} from "../TestCerts.sol"; + + +// File name has to end with '_test.sol', this file can contain more than one testSuite contracts +contract PredeployA_IASRoot_testSuit { + + //===== member variables ===== + + address m_addr; + + //===== functions ===== + + /// 'beforeAll' runs before all other tests + /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll' + function beforeAll() public { + m_addr = address(new IASRootCertMgr(TestCerts.IAS_ROOT_CERT_DER)); + Assert.equal( + m_addr, + 0x93Ff8fe9BF40051E8763C864B15A0E87f2f96468, + "The address of predeployed contract is changed;" + " please update it accordingly in all test cases" + ); + } + +} diff --git a/tests/DecentApp/00_PredeployB_IASReport_test.sol b/tests/DecentApp/00_PredeployB_IASReport_test.sol new file mode 100644 index 0000000..4185072 --- /dev/null +++ b/tests/DecentApp/00_PredeployB_IASReport_test.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.17 <0.9.0; + +// This import is automatically injected by Remix +import "remix_tests.sol"; + +// This import is required to use custom transaction context +// Although it may fail compilation in 'Solidity Compiler' plugin +// But it will work fine in 'Solidity Unit Testing' plugin +import "remix_accounts.sol"; + + +import {IASReportCertMgr} from "../../contracts/IASReportCertMgr.sol"; + +import {TestCerts} from "../TestCerts.sol"; + + +// File name has to end with '_test.sol', this file can contain more than one testSuite contracts +contract PredeployB_IASReport_testSuit { + + //===== member variables ===== + + address m_addr1; + address m_addr2; + + //===== functions ===== + + /// 'beforeAll' runs before all other tests + /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll' + function beforeAll() public { + address iasRootAddr = 0x93Ff8fe9BF40051E8763C864B15A0E87f2f96468; + m_addr1 = address(new IASReportCertMgr(iasRootAddr)); + Assert.equal( + m_addr1, + 0xd840735F4B6a0d1AF8Fa48EcE560f4778c007397, + "The address of predeployed contract is changed;" + " please update it accordingly in all test cases" + ); + + m_addr2 = address(new IASReportCertMgr(iasRootAddr)); + Assert.equal( + m_addr2, + 0x3903c0ac720556c950cc9C5e5037265b156c8849, + "The address of predeployed contract is changed;" + " please update it accordingly in all test cases" + ); + } + +} diff --git a/tests/DecentApp/00_PredeployC_DecentSvr_test.sol b/tests/DecentApp/00_PredeployC_DecentSvr_test.sol new file mode 100644 index 0000000..5cf57ac --- /dev/null +++ b/tests/DecentApp/00_PredeployC_DecentSvr_test.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.17 <0.9.0; + +// This import is automatically injected by Remix +import "remix_tests.sol"; + +// This import is required to use custom transaction context +// Although it may fail compilation in 'Solidity Compiler' plugin +// But it will work fine in 'Solidity Unit Testing' plugin +import "remix_accounts.sol"; + + +import {DecentServerCertMgr} from "../../contracts/DecentServerCertMgr.sol"; + +import {TestCerts} from "../TestCerts.sol"; + + +// File name has to end with '_test.sol', this file can contain more than one testSuite contracts +contract PredeployC_DecentSvr_testSuit { + + //===== member variables ===== + + address m_addr1; + address m_addr2; + + //===== functions ===== + + /// 'beforeAll' runs before all other tests + /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll' + function beforeAll() public { + address iasRepAddr1 = 0xd840735F4B6a0d1AF8Fa48EcE560f4778c007397; + m_addr1 = address(new DecentServerCertMgr(iasRepAddr1)); + Assert.equal( + m_addr1, + 0xD9eC9E840Bb5Df076DBbb488d01485058f421e58, + "The address of predeployed contract is changed;" + " please update it accordingly in all test cases" + ); + + address iasRepAddr2 = 0x3903c0ac720556c950cc9C5e5037265b156c8849; + m_addr2 = address(new DecentServerCertMgr(iasRepAddr2)); + Assert.equal( + m_addr2, + 0xaa96CB8107828e584C4FbC37a41754333DfFD206, + "The address of predeployed contract is changed;" + " please update it accordingly in all test cases" + ); + } + +} diff --git a/tests/Decent/11_DecentAppCert.sol b/tests/DecentApp/01_DecentAppCertBasics.sol similarity index 57% rename from tests/Decent/11_DecentAppCert.sol rename to tests/DecentApp/01_DecentAppCertBasics.sol index 36a5f92..0badedd 100644 --- a/tests/Decent/11_DecentAppCert.sol +++ b/tests/DecentApp/01_DecentAppCertBasics.sol @@ -5,45 +5,20 @@ pragma solidity >=0.4.17 <0.9.0; // This import is automatically injected by Remix import "remix_tests.sol"; -import {Asn1Decode} from "../../libs/asn1-decode/Asn1Decode.sol"; import {DecentAppCert} from "../../contracts/DecentAppCert.sol"; -import {DecentServerCertMgr} from "../../contracts/DecentServerCertMgr.sol"; -import {IASReportCertMgr} from "../../contracts/IASReportCertMgr.sol"; -import {IASRootCertMgr} from "../../contracts/IASRootCertMgr.sol"; import {X509CertNodes} from "../../contracts/X509CertNodes.sol"; import {TestCerts} from "../TestCerts.sol"; -contract DecentAppCert_proxy { +contract DecentAppCertBasics_proxy { - using Asn1Decode for bytes; using DecentAppCert for DecentAppCert.DecentApp; using X509CertNodes for X509CertNodes.CertNodesObj; - //===== member variables ===== - - address m_iasRootCertMgrAddr; - address m_iasReportCertMgrAddr; - address m_decentSvrCertMgrAddr; - //===== constructor ===== constructor() { - m_iasRootCertMgrAddr = - address(new IASRootCertMgr(TestCerts.IAS_ROOT_CERT_DER)); - - IASReportCertMgr reportCertMgr = - new IASReportCertMgr(m_iasRootCertMgrAddr); - reportCertMgr.verifyCert(TestCerts.IAS_REPORT_CERT_DER); - - m_iasReportCertMgrAddr = address(reportCertMgr); - - DecentServerCertMgr decentSvrCertMgr = - new DecentServerCertMgr(m_iasReportCertMgrAddr); - decentSvrCertMgr.verifyCert(TestCerts.DECENT_SVR_CERT_DER); - - m_decentSvrCertMgrAddr = address(decentSvrCertMgr); } //===== functions ===== @@ -132,49 +107,4 @@ contract DecentAppCert_proxy { ); } - function loadCertWithAddrTest() public { - bytes memory appCertDer = TestCerts.DECENT_APP_CERT_DER; - - DecentAppCert.DecentApp memory decentApp; - - decentApp.loadCert( - appCertDer, - m_decentSvrCertMgrAddr, - TestCerts.DECENT_SVR_CERT_KEY_ADDR - ); - - Assert.equal( - decentApp.appKeyAddr, - TestCerts.DECENT_APP_CERT_KEY_ADDR, - "appKeyAddr should be equal" - ); - Assert.equal( - keccak256(decentApp.appPlatform), - keccak256("SGX_EPID"), - "appPlatform not match" - ); - Assert.equal( - decentApp.appEnclaveHash, - TestCerts.DECENT_APP_CERT_ENCL_HASH, - "appEnclaveHash not match" - ); - Assert.equal( - keccak256(decentApp.appAuthList), - keccak256(TestCerts.DECENT_APP_CERT_AUTHLIST), - "appAuthList not match" - ); - } - - function loadCertWithWrongAddrTest() public { - bytes memory appCertDer = TestCerts.DECENT_APP_CERT_DER; - - DecentAppCert.DecentApp memory decentApp; - - decentApp.loadCert( - appCertDer, - m_decentSvrCertMgrAddr, - address(this) - ); - } - } diff --git a/tests/Decent/11_DecentAppCert_test.sol b/tests/DecentApp/01_DecentAppCertBasics_test.sol similarity index 61% rename from tests/Decent/11_DecentAppCert_test.sol rename to tests/DecentApp/01_DecentAppCertBasics_test.sol index 1ed83d0..18a3966 100644 --- a/tests/Decent/11_DecentAppCert_test.sol +++ b/tests/DecentApp/01_DecentAppCertBasics_test.sol @@ -10,11 +10,11 @@ import "remix_tests.sol"; import "remix_accounts.sol"; -import {DecentAppCert_proxy} from "./11_DecentAppCert.sol"; +import {DecentAppCertBasics_proxy} from "./01_DecentAppCertBasics.sol"; // File name has to end with '_test.sol', this file can contain more than one testSuite contracts -contract DecentAppCert_testSuit { +contract DecentAppCertBasics_testSuit { //===== member variables ===== @@ -25,11 +25,11 @@ contract DecentAppCert_testSuit { /// 'beforeAll' runs before all other tests /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll' function beforeAll() public { - m_testProxyAddr = address(new DecentAppCert_proxy()); + m_testProxyAddr = address(new DecentAppCertBasics_proxy()); } function extractDecentAppKeyTest() public { - try DecentAppCert_proxy(m_testProxyAddr).extractDecentAppKeyTest() { + try DecentAppCertBasics_proxy(m_testProxyAddr).extractDecentAppKeyTest() { Assert.ok(true, "extractDecentAppKeyTest should not throw"); } catch Error(string memory reason) { Assert.ok(false, reason); @@ -39,7 +39,7 @@ contract DecentAppCert_testSuit { } function verifyAppCertSignTest() public { - try DecentAppCert_proxy(m_testProxyAddr).verifyAppCertSignTest() { + try DecentAppCertBasics_proxy(m_testProxyAddr).verifyAppCertSignTest() { Assert.ok(true, "verifyAppCertSignTest should not throw"); } catch Error(string memory reason) { Assert.ok(false, reason); @@ -49,7 +49,7 @@ contract DecentAppCert_testSuit { } function extractAppCertExtensionsTest() public { - try DecentAppCert_proxy(m_testProxyAddr).extractAppCertExtensionsTest() { + try DecentAppCertBasics_proxy(m_testProxyAddr).extractAppCertExtensionsTest() { Assert.ok(true, "extractAppCertExtensionsTest should not throw"); } catch Error(string memory reason) { Assert.ok(false, reason); @@ -59,7 +59,7 @@ contract DecentAppCert_testSuit { } function loadCertTest() public { - try DecentAppCert_proxy(m_testProxyAddr).loadCertTest() { + try DecentAppCertBasics_proxy(m_testProxyAddr).loadCertTest() { Assert.ok(true, "loadCertTest should not throw"); } catch Error(string memory reason) { Assert.ok(false, reason); @@ -68,24 +68,4 @@ contract DecentAppCert_testSuit { } } - function loadCertWithAddrTest() public { - try DecentAppCert_proxy(m_testProxyAddr).loadCertWithAddrTest() { - Assert.ok(true, "loadCertWithAddrTest should not throw"); - } catch Error(string memory reason) { - Assert.ok(false, reason); - } catch (bytes memory /*lowLevelData*/) { - Assert.ok(false, "unexpected error - loadCertWithAddrTest"); - } - } - - function loadCertWithWrongAddrTest() public { - try DecentAppCert_proxy(m_testProxyAddr).loadCertWithWrongAddrTest() { - Assert.ok(false, "loadCertWithWrongAddrTest should throw"); - } catch Error(string memory reason) { - Assert.equal(reason, "Invalid issuer", reason); - } catch (bytes memory /*lowLevelData*/) { - Assert.ok(false, "unexpected error - loadCertWithWrongAddrTest"); - } - } - } diff --git a/tests/DecentApp/02_DecentAppCert.sol b/tests/DecentApp/02_DecentAppCert.sol new file mode 100644 index 0000000..4c2e1a6 --- /dev/null +++ b/tests/DecentApp/02_DecentAppCert.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.17 <0.9.0; + + +// This import is automatically injected by Remix +import "remix_tests.sol"; + +import {DecentAppCert} from "../../contracts/DecentAppCert.sol"; +// import {DecentServerCertMgr} from "../../contracts/DecentServerCertMgr.sol"; +// import {IASReportCertMgr} from "../../contracts/IASReportCertMgr.sol"; +// import {IASRootCertMgr} from "../../contracts/IASRootCertMgr.sol"; +import { + Interface_DecentServerCertMgr +} from "../../contracts/Interface_DecentServerCertMgr.sol"; +import {X509CertNodes} from "../../contracts/X509CertNodes.sol"; + +import {TestCerts} from "../TestCerts.sol"; + + +contract DecentAppCert_proxy { + + using DecentAppCert for DecentAppCert.DecentApp; + using X509CertNodes for X509CertNodes.CertNodesObj; + + //===== member variables ===== + + address m_decentSvrCertMgrAddr; + + //===== constructor ===== + + constructor() { + m_decentSvrCertMgrAddr = + // address(new DecentServerCertMgr( + // address(new IASReportCertMgr( + // address(new IASRootCertMgr(TestCerts.IAS_ROOT_CERT_DER)) + // )) + // )); + 0xD9eC9E840Bb5Df076DBbb488d01485058f421e58; + Interface_DecentServerCertMgr(m_decentSvrCertMgrAddr).verifyCert( + TestCerts.DECENT_SVR_CERT_DER + ); + } + + //===== functions ===== + + function loadCertWithAddrTest() public { + DecentAppCert.DecentApp memory decentApp; + decentApp.loadCert( + TestCerts.DECENT_APP_CERT_DER, + m_decentSvrCertMgrAddr, + TestCerts.DECENT_SVR_CERT_KEY_ADDR + ); + + Assert.equal( + decentApp.appKeyAddr, + TestCerts.DECENT_APP_CERT_KEY_ADDR, + "appKeyAddr should be equal" + ); + Assert.equal( + keccak256(decentApp.appPlatform), + keccak256("SGX_EPID"), + "appPlatform not match" + ); + Assert.equal( + decentApp.appEnclaveHash, + TestCerts.DECENT_APP_CERT_ENCL_HASH, + "appEnclaveHash not match" + ); + Assert.equal( + keccak256(decentApp.appAuthList), + keccak256(TestCerts.DECENT_APP_CERT_AUTHLIST), + "appAuthList not match" + ); + } + + function loadCertWithWrongAddrTest() public { + bytes memory appCertDer = TestCerts.DECENT_APP_CERT_DER; + + DecentAppCert.DecentApp memory decentApp; + + decentApp.loadCert( + appCertDer, + m_decentSvrCertMgrAddr, + address(this) + ); + } + +} diff --git a/tests/DecentApp/02_DecentAppCert_test.sol b/tests/DecentApp/02_DecentAppCert_test.sol new file mode 100644 index 0000000..efa9409 --- /dev/null +++ b/tests/DecentApp/02_DecentAppCert_test.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.17 <0.9.0; + +// This import is automatically injected by Remix +import "remix_tests.sol"; + +// This import is required to use custom transaction context +// Although it may fail compilation in 'Solidity Compiler' plugin +// But it will work fine in 'Solidity Unit Testing' plugin +import "remix_accounts.sol"; + + +import {DecentAppCert_proxy} from "./02_DecentAppCert.sol"; + + +// File name has to end with '_test.sol', this file can contain more than one testSuite contracts +contract DecentAppCert_testSuit { + + //===== member variables ===== + + address m_testProxyAddr; + + //===== functions ===== + + /// 'beforeAll' runs before all other tests + /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll' + function beforeAll() public { + m_testProxyAddr = address(new DecentAppCert_proxy()); + } + + function loadCertWithAddrTest() public { + try DecentAppCert_proxy(m_testProxyAddr).loadCertWithAddrTest() { + Assert.ok(true, "loadCertWithAddrTest should not throw"); + } catch Error(string memory reason) { + Assert.ok(false, reason); + } catch (bytes memory /*lowLevelData*/) { + Assert.ok(false, "unexpected error - loadCertWithAddrTest"); + } + } + + function loadCertWithWrongAddrTest() public { + try DecentAppCert_proxy(m_testProxyAddr).loadCertWithWrongAddrTest() { + Assert.ok(false, "loadCertWithWrongAddrTest should throw"); + } catch Error(string memory reason) { + Assert.equal(reason, "Invalid issuer", reason); + } catch (bytes memory /*lowLevelData*/) { + Assert.ok(false, "unexpected error - loadCertWithWrongAddrTest"); + } + } + +} diff --git a/tests/Decent/12_DecentCertChain_test.sol b/tests/DecentApp/03_DecentCertChain_test.sol similarity index 76% rename from tests/Decent/12_DecentCertChain_test.sol rename to tests/DecentApp/03_DecentCertChain_test.sol index c03abf7..3fbdd1f 100644 --- a/tests/Decent/12_DecentCertChain_test.sol +++ b/tests/DecentApp/03_DecentCertChain_test.sol @@ -12,9 +12,9 @@ import "remix_accounts.sol"; import {DecentAppCert} from "../../contracts/DecentAppCert.sol"; import {DecentCertChain} from "../../contracts/DecentCertChain.sol"; -import {DecentServerCertMgr} from "../../contracts/DecentServerCertMgr.sol"; -import {IASReportCertMgr} from "../../contracts/IASReportCertMgr.sol"; -import {IASRootCertMgr} from "../../contracts/IASRootCertMgr.sol"; +// import {DecentServerCertMgr} from "../../contracts/DecentServerCertMgr.sol"; +// import {IASReportCertMgr} from "../../contracts/IASReportCertMgr.sol"; +// import {IASRootCertMgr} from "../../contracts/IASRootCertMgr.sol"; import {TestCerts} from "../TestCerts.sol"; @@ -24,8 +24,6 @@ contract DecentCertChain_testSuit { //===== member variables ===== - address m_iasRootCertMgrAddr; - address m_iasReportCertMgrAddr; address m_decentSvrCertMgrAddr; //===== functions ===== @@ -33,16 +31,13 @@ contract DecentCertChain_testSuit { /// 'beforeAll' runs before all other tests /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll' function beforeAll() public { - m_iasRootCertMgrAddr = - address(new IASRootCertMgr(TestCerts.IAS_ROOT_CERT_DER)); - - IASReportCertMgr reportCertMgr = - new IASReportCertMgr(m_iasRootCertMgrAddr); - m_iasReportCertMgrAddr = address(reportCertMgr); - - DecentServerCertMgr decentSvrCertMgr = - new DecentServerCertMgr(m_iasReportCertMgrAddr); - m_decentSvrCertMgrAddr = address(decentSvrCertMgr); + m_decentSvrCertMgrAddr = + // address(new DecentServerCertMgr( + // address(new IASReportCertMgr( + // address(new IASRootCertMgr(TestCerts.IAS_ROOT_CERT_DER)) + // )) + // )); + 0xaa96CB8107828e584C4FbC37a41754333DfFD206; } function verifyCertChainTest() public { diff --git a/tests/Decent/01_ParamPassing.sol b/tests/DecentCommon/01_ParamPassing.sol similarity index 88% rename from tests/Decent/01_ParamPassing.sol rename to tests/DecentCommon/01_ParamPassing.sol index e6a228e..5688627 100644 --- a/tests/Decent/01_ParamPassing.sol +++ b/tests/DecentCommon/01_ParamPassing.sol @@ -32,6 +32,19 @@ library LibParamPassing { return 3; } + function privMemFuncProxy(Struct1 memory s) internal pure returns (uint256) { + return privMemFunc(s); + } + + function privMemFunc(bytes memory b) private pure returns (uint256) { + require(b[0] == 0x01, "b[0]!=1"); + return 3; + } + + function privMemFuncProxy(bytes memory b) internal pure returns (uint256) { + return privMemFunc(b); + } + function internMemFunc(bytes memory b) internal pure returns (uint256) { require(b[0] == 0x01, "b[0]!=1"); return 3; diff --git a/tests/Decent/01_ParamPassing_test.sol b/tests/DecentCommon/01_ParamPassing_test.sol similarity index 89% rename from tests/Decent/01_ParamPassing_test.sol rename to tests/DecentCommon/01_ParamPassing_test.sol index 62987ec..7d9c527 100644 --- a/tests/Decent/01_ParamPassing_test.sol +++ b/tests/DecentCommon/01_ParamPassing_test.sol @@ -36,69 +36,15 @@ contract ParamPassing_testSuite { Assert.equal(retVal, 3, "retVal must be 3"); } - function libGasDiff() public { - bytes memory b = new bytes(4096); - b[0] = 0x01; - - // library - - uint256 internMemGasUsed = gasleft(); - uint256 retVal = LibParamPassing.internMemFunc(b); - internMemGasUsed -= gasleft(); - Assert.equal(retVal, 3, "retVal must be 3"); - - uint256 externMemGasUsed = gasleft(); - retVal = LibParamPassing.externMemFunc(b); - externMemGasUsed -= gasleft(); - Assert.equal(retVal, 3, "retVal must be 3"); - - uint256 externCallGasUsed = gasleft(); - retVal = LibParamPassing.externCallFunc(b); - externCallGasUsed -= gasleft(); - Assert.equal(retVal, 3, "retVal must be 3"); - - Assert.lesserThan(internMemGasUsed, uint256(500), "internMemGasUsed"); - // Assert.equal(internMemGasUsed, 152, "internMemGasUsed"); - Assert.greaterThan(externMemGasUsed, uint256(5000), "externMemGasUsed"); - // Assert.equal(externMemGasUsed, 15145, "externMemGasUsed"); - Assert.greaterThan(externCallGasUsed, uint256(5000), "externCallGasUsed"); - // Assert.equal(externCallGasUsed, 11264, "externCallGasUsed"); - - // contract - ContraParamPassing c = new ContraParamPassing(); - - externMemGasUsed = gasleft(); - retVal = c.externMemFunc(b); - externMemGasUsed -= gasleft(); - Assert.equal(retVal, 3, "retVal must be 3"); - - externCallGasUsed = gasleft(); - retVal = c.externCallFunc(b); - externCallGasUsed -= gasleft(); - Assert.equal(retVal, 3, "retVal must be 3"); - - uint256 pubCallGasUsed = gasleft(); - retVal = c.pubCallFunc(b); - pubCallGasUsed -= gasleft(); - Assert.equal(retVal, 3, "retVal must be 3"); - - Assert.greaterThan(externMemGasUsed, uint256(5000), "externMemGasUsed"); - // Assert.equal(externMemGasUsed, 12207, "externMemGasUsed"); - Assert.greaterThan(externCallGasUsed, uint256(5000), "externCallGasUsed"); - // Assert.equal(externCallGasUsed, 11298, "externCallGasUsed"); - Assert.greaterThan(pubCallGasUsed, uint256(5000), "pubCallGasUsed"); - // Assert.equal(pubCallGasUsed, 11277, "pubCallGasUsed"); - - pubCallGasUsed = gasleft(); - retVal = c.pubCallFunc(m_b); - pubCallGasUsed -= gasleft(); + /** + * library + private ==> Pass by reference (not visible) + */ + function libPrivMemFunc() public { + LibParamPassing.Struct1 memory s; + uint256 retVal = LibParamPassing.privMemFuncProxy(s); + Assert.equal(s.a, 1, "s.a must be 1"); + Assert.equal(s.b, 2, "s.b must be 2"); Assert.equal(retVal, 3, "retVal must be 3"); - Assert.greaterThan(pubCallGasUsed, uint256(50000), "pubCallGasUsed"); - // Assert.equal(pubCallGasUsed, 281951, "pubCallGasUsed"); - - uint256 internCallGasUsed = c.forwardInternCallFunc(b); - Assert.lesserThan(internCallGasUsed, uint256(500), "internCallGasUsed"); - Assert.equal(internCallGasUsed, 166, "internCallGasUsed"); } /** @@ -123,17 +69,6 @@ contract ParamPassing_testSuite { Assert.equal(retVal, 3, "retVal must be 3"); } - /** - * library + private ==> not visible - */ - // function libPrivMemFunc() public { - // LibParamPassing.Struct1 memory s; - // uint256 retVal = LibParamPassing.privMemFunc(s); - // Assert.equal(s.a, 0, "s.a must be 0"); - // Assert.equal(s.b, 0, "s.b must be 0"); - // Assert.equal(retVal, 3, "retVal must be 3"); - // } - /** * contract + external ==> Pass by copy */ @@ -186,4 +121,76 @@ contract ParamPassing_testSuite { // Assert.equal(retVal, 3, "retVal must be 3"); // } + function libGasDiff() public { + bytes memory b = new bytes(4096); + b[0] = 0x01; + + // library + + uint256 internMemGasUsed = gasleft(); + uint256 retVal = LibParamPassing.internMemFunc(b); + internMemGasUsed -= gasleft(); + Assert.equal(retVal, 3, "retVal must be 3"); + + uint256 privMemGasUsed = gasleft(); + retVal = LibParamPassing.privMemFuncProxy(b); + privMemGasUsed -= gasleft(); + Assert.equal(retVal, 3, "retVal must be 3"); + + uint256 externMemGasUsed = gasleft(); + retVal = LibParamPassing.externMemFunc(b); + externMemGasUsed -= gasleft(); + Assert.equal(retVal, 3, "retVal must be 3"); + + uint256 externCallGasUsed = gasleft(); + retVal = LibParamPassing.externCallFunc(b); + externCallGasUsed -= gasleft(); + Assert.equal(retVal, 3, "retVal must be 3"); + + Assert.lesserThan(internMemGasUsed, uint256(500), "internMemGasUsed"); + // Assert.equal(internMemGasUsed, 152, "internMemGasUsed"); + Assert.lesserThan(privMemGasUsed, uint256(500), "privMemGasUsed"); + // Assert.equal(privMemGasUsed, 189, "privMemGasUsed"); + Assert.greaterThan(externMemGasUsed, uint256(5000), "externMemGasUsed"); + // Assert.equal(externMemGasUsed, 15145, "externMemGasUsed"); + Assert.greaterThan(externCallGasUsed, uint256(5000), "externCallGasUsed"); + // Assert.equal(externCallGasUsed, 11264, "externCallGasUsed"); + + // contract + ContraParamPassing c = new ContraParamPassing(); + + externMemGasUsed = gasleft(); + retVal = c.externMemFunc(b); + externMemGasUsed -= gasleft(); + Assert.equal(retVal, 3, "retVal must be 3"); + + externCallGasUsed = gasleft(); + retVal = c.externCallFunc(b); + externCallGasUsed -= gasleft(); + Assert.equal(retVal, 3, "retVal must be 3"); + + uint256 pubCallGasUsed = gasleft(); + retVal = c.pubCallFunc(b); + pubCallGasUsed -= gasleft(); + Assert.equal(retVal, 3, "retVal must be 3"); + + Assert.greaterThan(externMemGasUsed, uint256(5000), "externMemGasUsed"); + // Assert.equal(externMemGasUsed, 12207, "externMemGasUsed"); + Assert.greaterThan(externCallGasUsed, uint256(5000), "externCallGasUsed"); + // Assert.equal(externCallGasUsed, 11298, "externCallGasUsed"); + Assert.greaterThan(pubCallGasUsed, uint256(5000), "pubCallGasUsed"); + // Assert.equal(pubCallGasUsed, 11277, "pubCallGasUsed"); + + pubCallGasUsed = gasleft(); + retVal = c.pubCallFunc(m_b); + pubCallGasUsed -= gasleft(); + Assert.equal(retVal, 3, "retVal must be 3"); + Assert.greaterThan(pubCallGasUsed, uint256(50000), "pubCallGasUsed"); + // Assert.equal(pubCallGasUsed, 281951, "pubCallGasUsed"); + + uint256 internCallGasUsed = c.forwardInternCallFunc(b); + Assert.lesserThan(internCallGasUsed, uint256(500), "internCallGasUsed"); + // Assert.equal(internCallGasUsed, 166, "internCallGasUsed"); + } + } diff --git a/tests/Decent/02_X509CertNodes.sol b/tests/DecentCommon/02_X509CertNodes.sol similarity index 100% rename from tests/Decent/02_X509CertNodes.sol rename to tests/DecentCommon/02_X509CertNodes.sol diff --git a/tests/Decent/02_X509CertNodes_test.sol b/tests/DecentCommon/02_X509CertNodes_test.sol similarity index 98% rename from tests/Decent/02_X509CertNodes_test.sol rename to tests/DecentCommon/02_X509CertNodes_test.sol index 514684f..1c77d04 100644 --- a/tests/Decent/02_X509CertNodes_test.sol +++ b/tests/DecentCommon/02_X509CertNodes_test.sol @@ -11,8 +11,11 @@ import "remix_accounts.sol"; import {Asn1Decode, NodePtr} from "../../libs/asn1-decode/Asn1Decode.sol"; + import {X509CertNodes} from "../../contracts/X509CertNodes.sol"; +import {X509Timestamp} from "../../contracts/X509Timestamp.sol"; import {OIDs} from "../../contracts/Constants.sol"; + import {TestCerts} from "../TestCerts.sol"; import {X509CertNodes_utils} from "./02_X509CertNodes.sol"; @@ -22,6 +25,7 @@ contract X509CertNodes_testSuit { using Asn1Decode for bytes; using X509CertNodes for X509CertNodes.CertTbsNodesObj; using X509CertNodes for X509CertNodes.CertNodesObj; + using X509Timestamp for X509CertNodes.CertTbsNodesObj; /// 'beforeAll' runs before all other tests /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll' diff --git a/tests/Decent/03_X509Name_test.sol b/tests/DecentCommon/03_X509Name_test.sol similarity index 99% rename from tests/Decent/03_X509Name_test.sol rename to tests/DecentCommon/03_X509Name_test.sol index 5e25424..4c5a767 100644 --- a/tests/Decent/03_X509Name_test.sol +++ b/tests/DecentCommon/03_X509Name_test.sol @@ -12,6 +12,7 @@ import "remix_accounts.sol"; import {X509Name} from "../../contracts/X509Name.sol"; import {X509CertNodes} from "../../contracts/X509CertNodes.sol"; + import {TestCerts} from "../TestCerts.sol"; diff --git a/tests/Decent/08_X509Extension.sol b/tests/DecentCommon/04_X509Extension.sol similarity index 100% rename from tests/Decent/08_X509Extension.sol rename to tests/DecentCommon/04_X509Extension.sol diff --git a/tests/Decent/08_X509Extension_test.sol b/tests/DecentCommon/04_X509Extension_test.sol similarity index 96% rename from tests/Decent/08_X509Extension_test.sol rename to tests/DecentCommon/04_X509Extension_test.sol index 46d8112..f463a7d 100644 --- a/tests/Decent/08_X509Extension_test.sol +++ b/tests/DecentCommon/04_X509Extension_test.sol @@ -11,7 +11,7 @@ import "remix_accounts.sol"; import {X509Extension} from "../../contracts/X509Extension.sol"; -import {X509Extension_proxy} from "./08_X509Extension.sol"; +import {X509Extension_proxy} from "./04_X509Extension.sol"; // File name has to end with '_test.sol', this file can contain more than one testSuite contracts diff --git a/tests/Decent/04_IASRootCert_test.sol b/tests/DecentIAS/01_IASRootCert_test.sol similarity index 99% rename from tests/Decent/04_IASRootCert_test.sol rename to tests/DecentIAS/01_IASRootCert_test.sol index 2a95a93..019be3a 100644 --- a/tests/Decent/04_IASRootCert_test.sol +++ b/tests/DecentIAS/01_IASRootCert_test.sol @@ -12,6 +12,7 @@ import "remix_accounts.sol"; import {IASRootCert} from "../../contracts/IASRootCert.sol"; import {Names} from "../../contracts/Constants.sol"; + import {TestCerts} from "../TestCerts.sol"; diff --git a/tests/Decent/05_IASRootCertMgr_test.sol b/tests/DecentIAS/02_IASRootCertMgr_test.sol similarity index 100% rename from tests/Decent/05_IASRootCertMgr_test.sol rename to tests/DecentIAS/02_IASRootCertMgr_test.sol diff --git a/tests/Decent/06_IASReportCert.sol b/tests/DecentIAS/03_IASReportCert.sol similarity index 100% rename from tests/Decent/06_IASReportCert.sol rename to tests/DecentIAS/03_IASReportCert.sol diff --git a/tests/Decent/06_IASReportCert_test.sol b/tests/DecentIAS/03_IASReportCert_test.sol similarity index 98% rename from tests/Decent/06_IASReportCert_test.sol rename to tests/DecentIAS/03_IASReportCert_test.sol index b7ad039..6755e98 100644 --- a/tests/Decent/06_IASReportCert_test.sol +++ b/tests/DecentIAS/03_IASReportCert_test.sol @@ -11,9 +11,10 @@ import "remix_accounts.sol"; import {IASReportCert} from "../../contracts/IASReportCert.sol"; -import {TestCerts} from "../TestCerts.sol"; import {X509CertNodes} from "../../contracts/X509CertNodes.sol"; -import {IASReportCert_proxy} from "./06_IASReportCert.sol"; + +import {TestCerts} from "../TestCerts.sol"; +import {IASReportCert_proxy} from "./03_IASReportCert.sol"; // File name has to end with '_test.sol', this file can contain more than one testSuite contracts diff --git a/tests/Decent/07_IASReportCertMgr_test.sol b/tests/DecentIAS/04_IASReportCertMgr_test.sol similarity index 99% rename from tests/Decent/07_IASReportCertMgr_test.sol rename to tests/DecentIAS/04_IASReportCertMgr_test.sol index a1292af..d7e23e2 100644 --- a/tests/Decent/07_IASReportCertMgr_test.sol +++ b/tests/DecentIAS/04_IASReportCertMgr_test.sol @@ -12,9 +12,10 @@ import "remix_accounts.sol"; import {IASReportCertMgr} from "../../contracts/IASReportCertMgr.sol"; import {IASRootCertMgr} from "../../contracts/IASRootCertMgr.sol"; -import {TestCerts} from "../TestCerts.sol"; import {X509CertNodes} from "../../contracts/X509CertNodes.sol"; +import {TestCerts} from "../TestCerts.sol"; + // File name has to end with '_test.sol', this file can contain more than one testSuite contracts contract IASReportCertMgr_testSuit { diff --git a/tests/Decent/09_DecentServerCert.sol b/tests/DecentServer/01_DecentServerCert.sol similarity index 91% rename from tests/Decent/09_DecentServerCert.sol rename to tests/DecentServer/01_DecentServerCert.sol index 0e746ac..65a0d4c 100644 --- a/tests/Decent/09_DecentServerCert.sol +++ b/tests/DecentServer/01_DecentServerCert.sol @@ -6,14 +6,15 @@ pragma solidity >=0.4.17 <0.9.0; import "remix_tests.sol"; import {BytesUtils} from "../../libs/ens-contracts/BytesUtils.sol"; + +import {DecentServerCert} from "../../contracts/DecentServerCert.sol"; import {OIDs} from "../../contracts/Constants.sol"; import {X509CertNodes} from "../../contracts/X509CertNodes.sol"; -import {DecentServerCert} from "../../contracts/DecentServerCert.sol"; import {TestCerts} from "../TestCerts.sol"; -contract DecentServerCert_proxy { +contract DecentServerCertBasics_proxy { using DecentServerCert for DecentServerCert.DecentServerCertObj; using X509CertNodes for X509CertNodes.CertNodesObj; @@ -87,8 +88,8 @@ contract DecentServerCert_proxy { } function jsonSimpleReadValPosTest() public { + bytes memory str = REPORT_JSON; { - bytes memory str = REPORT_JSON; bytes memory key = "\"isvEnclaveQuoteStatus\""; (uint256 idx, uint256 len) = DecentServerCert.jsonSimpleReadValPos(str, key); @@ -104,7 +105,6 @@ contract DecentServerCert_proxy { ); } { - bytes memory str = REPORT_JSON; bytes memory key = "\"isvEnclaveQuoteBody\""; (uint256 idx, uint256 len) = DecentServerCert.jsonSimpleReadValPos(str, key); @@ -139,6 +139,31 @@ contract DecentServerCert_proxy { ); } +} + + +contract DecentServerCertCerts_proxy { + + using DecentServerCert for DecentServerCert.DecentServerCertObj; + using X509CertNodes for X509CertNodes.CertNodesObj; + + //===== constants ===== + + //===== member variables ===== + + mapping(bytes32 => bool) m_quoteStatusMap; + + //===== constructor ===== + + constructor() { + m_quoteStatusMap[keccak256("OK")] = true; + m_quoteStatusMap[keccak256("CONFIGURATION_NEEDED")] = true; + m_quoteStatusMap[keccak256("SW_HARDENING_NEEDED")] = true; + m_quoteStatusMap[keccak256("CONFIGURATION_AND_SW_HARDENING_NEEDED")] = true; + } + + //===== functions ===== + function verifySelfSignTest() public { bytes memory certDer = TestCerts.DECENT_SVR_CERT_DER; X509CertNodes.CertNodesObj memory certNodes; diff --git a/tests/DecentServer/01_DecentServerCertBasics_test.sol b/tests/DecentServer/01_DecentServerCertBasics_test.sol new file mode 100644 index 0000000..dc657c4 --- /dev/null +++ b/tests/DecentServer/01_DecentServerCertBasics_test.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.17 <0.9.0; + +// This import is automatically injected by Remix +import "remix_tests.sol"; + +// This import is required to use custom transaction context +// Although it may fail compilation in 'Solidity Compiler' plugin +// But it will work fine in 'Solidity Unit Testing' plugin +import "remix_accounts.sol"; + + +import {IASReportCertMgr} from "../../contracts/IASReportCertMgr.sol"; +import {IASRootCertMgr} from "../../contracts/IASRootCertMgr.sol"; + +import {TestCerts} from "../TestCerts.sol"; +import {DecentServerCertBasics_proxy} from "./01_DecentServerCert.sol"; + + +// File name has to end with '_test.sol', this file can contain more than one testSuite contracts +contract DecentServerCertBasics_testSuit { + + //===== member variables ===== + + address m_iasRootCertMgrAddr; + address m_testProxyBAddr; + + /// 'beforeAll' runs before all other tests + /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll' + function beforeAll() public { + m_iasRootCertMgrAddr = + address(new IASRootCertMgr(TestCerts.IAS_ROOT_CERT_DER)); + m_testProxyBAddr = address(new DecentServerCertBasics_proxy()); + } + + function strFindTest() public { + try DecentServerCertBasics_proxy(m_testProxyBAddr).strFindTest() { + Assert.ok(true, "strFindTest should not throw"); + } catch Error(string memory reason) { + Assert.ok(false, reason); + } catch (bytes memory /*lowLevelData*/) { + Assert.ok(false, "unexpected error - strFindTest"); + } + } + + function jsonSimpleReadValPosTest() public { + try DecentServerCertBasics_proxy(m_testProxyBAddr).jsonSimpleReadValPosTest() { + Assert.ok(true, "jsonSimpleReadValPosTest should not throw"); + } catch Error(string memory reason) { + Assert.ok(false, reason); + } catch (bytes memory /*lowLevelData*/) { + Assert.ok(false, "unexpected error - jsonSimpleReadValPosTest"); + } + } + + function verifyEPIDAttestationRepTest() public { + IASReportCertMgr iasReportCertMgr = + new IASReportCertMgr(m_iasRootCertMgrAddr); + + try DecentServerCertBasics_proxy(m_testProxyBAddr).verifyEPIDAttestationRepTest( + address(iasReportCertMgr) + ) { + Assert.ok(true, "verifyEPIDAttestationRepTest should not throw"); + } catch Error(string memory reason) { + Assert.ok(false, reason); + } catch (bytes memory /*lowLevelData*/) { + Assert.ok(false, "unexpected error - verifyEPIDAttestationRepTest"); + } + } + +} diff --git a/tests/DecentServer/02_DecentServerCert_test.sol b/tests/DecentServer/02_DecentServerCert_test.sol new file mode 100644 index 0000000..abad9a5 --- /dev/null +++ b/tests/DecentServer/02_DecentServerCert_test.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.17 <0.9.0; + +// This import is automatically injected by Remix +import "remix_tests.sol"; + +// This import is required to use custom transaction context +// Although it may fail compilation in 'Solidity Compiler' plugin +// But it will work fine in 'Solidity Unit Testing' plugin +import "remix_accounts.sol"; + + +import {IASReportCertMgr} from "../../contracts/IASReportCertMgr.sol"; +import {IASRootCertMgr} from "../../contracts/IASRootCertMgr.sol"; + +import {TestCerts} from "../TestCerts.sol"; +import {DecentServerCertCerts_proxy} from "./01_DecentServerCert.sol"; + + +// File name has to end with '_test.sol', this file can contain more than one testSuite contracts +contract DecentServerCert_testSuit { + + //===== member variables ===== + + address m_iasRootCertMgrAddr; + address m_testProxyCAddr; + + /// 'beforeAll' runs before all other tests + /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll' + function beforeAll() public { + m_iasRootCertMgrAddr = + address(new IASRootCertMgr(TestCerts.IAS_ROOT_CERT_DER)); + m_testProxyCAddr = address(new DecentServerCertCerts_proxy()); + } + + function verifySelfSignTest() public { + try DecentServerCertCerts_proxy(m_testProxyCAddr).verifySelfSignTest() { + Assert.ok(true, "verifySelfSignTest should not throw"); + } catch Error(string memory reason) { + Assert.ok(false, reason); + } catch (bytes memory /*lowLevelData*/) { + Assert.ok(false, "unexpected error - verifySelfSignTest"); + } + } + + function extractDecentServerKeyTest() public { + try DecentServerCertCerts_proxy(m_testProxyCAddr).extractDecentServerKeyTest() { + Assert.ok(true, "extractDecentServerKeyTest should not throw"); + } catch Error(string memory reason) { + Assert.ok(false, reason); + } catch (bytes memory /*lowLevelData*/) { + Assert.ok(false, "unexpected error - extractDecentServerKeyTest"); + } + } + + function loadCertTest() public { + IASReportCertMgr iasReportCertMgr = + new IASReportCertMgr(m_iasRootCertMgrAddr); + + try DecentServerCertCerts_proxy(m_testProxyCAddr).loadCertTest( + address(iasReportCertMgr) + ) { + Assert.ok(true, "loadCertTest should not throw"); + } catch Error(string memory reason) { + Assert.ok(false, reason); + } catch (bytes memory /*lowLevelData*/) { + Assert.ok(false, "unexpected error - loadCertTest"); + } + } + +} diff --git a/tests/Decent/10_DecentServerCertMgr_test.sol b/tests/DecentServer/03_DecentServerCertMgr_test.sol similarity index 99% rename from tests/Decent/10_DecentServerCertMgr_test.sol rename to tests/DecentServer/03_DecentServerCertMgr_test.sol index 28fae1a..63befff 100644 --- a/tests/Decent/10_DecentServerCertMgr_test.sol +++ b/tests/DecentServer/03_DecentServerCertMgr_test.sol @@ -14,9 +14,10 @@ import {DecentServerCert} from "../../contracts/DecentServerCert.sol"; import {DecentServerCertMgr} from "../../contracts/DecentServerCertMgr.sol"; import {IASReportCertMgr} from "../../contracts/IASReportCertMgr.sol"; import {IASRootCertMgr} from "../../contracts/IASRootCertMgr.sol"; -import {TestCerts} from "../TestCerts.sol"; import {X509CertNodes} from "../../contracts/X509CertNodes.sol"; +import {TestCerts} from "../TestCerts.sol"; + // File name has to end with '_test.sol', this file can contain more than one testSuite contracts contract DecentServerCertMgr_testSuit { diff --git a/tests/Makefile b/tests/Makefile index 46dae05..da5d530 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -2,61 +2,61 @@ MODULE_NAME := tests CONTRACTS := \ HelloWorldApp +MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) +CURRENT_DIR := $(dir $(MKFILE_PATH)) +ROOT_DIR := $(CURRENT_DIR)/.. +BUILD_DIR := $(ROOT_DIR)/build + +SOLC_BIN := $(BUILD_DIR)/solc-static-linux +OPTIMIZE_RUN := 200 +SOLC_FLAGS := --optimize --optimize-runs $(OPTIMIZE_RUN) \ + --revert-strings strip \ + --via-ir \ + --overwrite \ + --base-path $(ROOT_DIR) \ + --output-dir $(BUILD_DIR)/$(MODULE_NAME)/all/ + CHECKSUM_BIN := openssl sha256 -all: $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .abi,$(CONTRACTS))) \ - $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .bin,$(CONTRACTS))) \ - $(addprefix ../build/$(MODULE_NAME)/,checksums.txt) +all: $(CONTRACTS) checksums -../build/nodeenv.state: - $(MAKE) -C .. build/nodeenv.state +$(SOLC_BIN): + $(MAKE) -C .. solc_bin -../build/$(MODULE_NAME)/%.bin: %.sol ../build/nodeenv.state +$(BUILD_DIR)/$(MODULE_NAME)/%.bin: %.sol $(SOLC_BIN) ( \ - . ../build/nodeenv/bin/activate && \ - solcjs --optimize --optimize-runs 200 \ - --bin \ - --include-path node_modules/ --base-path .. \ - --output-dir ../build/$(MODULE_NAME)/ \ - $< && \ - mv ../build/$(MODULE_NAME)/$(MODULE_NAME)_$(basename $<)_sol_$(basename $<).bin \ - ../build/$(MODULE_NAME)/$(basename $<).bin && \ - rm -f ../build/$(MODULE_NAME)/*_sol_*.bin \ + $(SOLC_BIN) --bin $(SOLC_FLAGS) $< && \ + cp $(BUILD_DIR)/$(MODULE_NAME)/all/$(basename $<).bin \ + $(BUILD_DIR)/$(MODULE_NAME)/$(basename $<).bin \ ) -../build/$(MODULE_NAME)/%.abi: %.sol ../build/nodeenv.state +$(BUILD_DIR)/$(MODULE_NAME)/%.abi: %.sol $(SOLC_BIN) ( \ - . ../build/nodeenv/bin/activate && \ - solcjs --optimize --optimize-runs 200 \ - --abi \ - --include-path node_modules/ --base-path .. \ - --output-dir ../build/$(MODULE_NAME)/ \ - $< && \ - mv ../build/$(MODULE_NAME)/$(MODULE_NAME)_$(basename $<)_sol_$(basename $<).abi \ - ../build/$(MODULE_NAME)/$(basename $<).abi && \ - rm -f ../build/$(MODULE_NAME)/*_sol_*.abi \ + $(SOLC_BIN) --abi $(SOLC_FLAGS) $< && \ + cp $(BUILD_DIR)/$(MODULE_NAME)/all/$(basename $<).abi \ + $(BUILD_DIR)/$(MODULE_NAME)/$(basename $<).abi \ ) -../build/$(MODULE_NAME)/checksums.txt: $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .abi,$(CONTRACTS))) \ - $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .bin,$(CONTRACTS))) +$(CONTRACTS): %: $(BUILD_DIR)/$(MODULE_NAME)/%.abi $(BUILD_DIR)/$(MODULE_NAME)/%.bin + + +$(BUILD_DIR)/$(MODULE_NAME)/checksums.txt: $(CONTRACTS) ( \ - cd ../build/$(MODULE_NAME); \ + cd $(BUILD_DIR)/$(MODULE_NAME); \ $(CHECKSUM_BIN) $(addsuffix .abi,$(CONTRACTS)) $(addsuffix .bin,$(CONTRACTS)) > checksums.txt; \ ) -checksums: ../build/$(MODULE_NAME)/checksums.txt +checksums: $(BUILD_DIR)/$(MODULE_NAME)/checksums.txt clean: - rm -f $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .abi,$(CONTRACTS))) \ - $(addprefix ../build/$(MODULE_NAME)/,$(addsuffix .bin,$(CONTRACTS))) \ - $(addprefix ../build/$(MODULE_NAME)/,checksums.txt) + rm -rf $(BUILD_DIR)/$(MODULE_NAME)/ -.PHONY: all clean checksums +.PHONY: all clean checksums $(CONTRACTS) diff --git a/tests/RLP/RLP_test.sol b/tests/RLP/RLP_test.sol index 043c903..c6eb216 100644 --- a/tests/RLP/RLP_test.sol +++ b/tests/RLP/RLP_test.sol @@ -12,15 +12,17 @@ import "remix_accounts.sol"; import {RLPReader} from "../../libs/Solidity-RLP/contracts/RLPReader.sol"; +import {TestCerts} from "../TestCerts.sol"; + contract RLPTest { - using RLPReader for RLPReader.RLPItem; + using RLPReader for RLPReader.RLPItem; function beforeAll () public { } - function rlpTest1() external { + function rlpTest1() public { uint i = 1337; bytes memory rlpBytes = abi.encodePacked(i); RLPReader.RLPItem memory item = RLPReader.toRlpItem(rlpBytes); @@ -28,4 +30,39 @@ contract RLPTest { Assert.equal(val, uint(1337), "rlp value not equal"); } + + function decentAttestRepSetTest() public { + bytes memory rlpBytes = TestCerts.DECENT_SVR_CERT_ATT_REP_RLP; + + bytes memory iasRepCert = TestCerts.IAS_REPORT_CERT_DER; + bytes memory iasRep = TestCerts.DECENT_SVR_CERT_ATT_REP_JSON; + bytes memory iasSig = TestCerts.DECENT_SVR_CERT_ATT_REP_SIGN; + + RLPReader.RLPItem[] memory rep = RLPReader.toRlpItem(rlpBytes).toList(); + + RLPReader.RLPItem[] memory repCerts = rep[0].toList(); + Assert.equal(repCerts.length, 1, "wrong number of items"); + + bytes memory repCertDer = repCerts[0].toBytes(); + Assert.equal( + keccak256(repCertDer), + keccak256(iasRepCert), + "wrong IAS report cert DER" + ); + + bytes memory repJson = rep[1].toBytes(); + Assert.equal( + keccak256(repJson), + keccak256(iasRep), + "wrong IAS report JSON" + ); + + bytes memory repSig = rep[2].toBytes(); + Assert.equal( + keccak256(repSig), + keccak256(iasSig), + "wrong IAS report signature" + ); + } + } diff --git a/tests/x509-forest-of-trust/01_X509Parser.sol b/tests/x509-forest-of-trust/01_X509Parser.sol index 8a74e73..754ac8c 100644 --- a/tests/x509-forest-of-trust/01_X509Parser.sol +++ b/tests/x509-forest-of-trust/01_X509Parser.sol @@ -18,7 +18,7 @@ contract X509Parser_proxy{ uint256 result = X509Parser.toTimestamp("161114153731Z"); gasUsed -= gasleft(); Assert.equal(result, 1479137851, "timestamp not equal"); - //Assert.equal(gasUsed, 0, "gasUsed"); + // Assert.equal(gasUsed, 8100, "gasUsed"); } { @@ -26,7 +26,7 @@ contract X509Parser_proxy{ uint256 result = X509Parser.toTimestamp("220101000000Z"); gasUsed -= gasleft(); Assert.equal(result, 1640995200, "timestamp not equal"); - //Assert.equal(gasUsed, 0, "gasUsed"); + // Assert.equal(gasUsed, 8088, "gasUsed"); } { @@ -34,7 +34,7 @@ contract X509Parser_proxy{ uint256 result = X509Parser.toTimestamp("20491231235959Z"); gasUsed -= gasleft(); Assert.equal(result, 2524607999, "timestamp not equal"); - //Assert.equal(gasUsed, 0, "gasUsed"); + // Assert.equal(gasUsed, 8552, "gasUsed"); } { diff --git a/utils/GanacheContractTests.py b/utils/GanacheContractTests.py index 7032ed5..ca3e677 100644 --- a/utils/GanacheContractTests.py +++ b/utils/GanacheContractTests.py @@ -10,6 +10,7 @@ import argparse import base64 +import json import logging import os import signal @@ -46,6 +47,7 @@ def StartGanache() -> subprocess.Popen: '-d', '-a', str(GANACHE_NUM_KEYS), '--network-id', str(GANACHE_NET_ID), + '--chain.hardfork', 'shanghai', '--wallet.accountKeysPath', str(GANACHE_KEYS_PATH), ] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -94,7 +96,7 @@ def LoadDecentAppCertDer() -> bytes: return _PemToDerCert(certPem) -def RunTests_VerifyIndividually() -> None: +def RunTests_VerifyIndividually() -> dict: # connect to ganache ganacheUrl = 'http://localhost:{}'.format(GANACHE_PORT) w3 = Web3(Web3.HTTPProvider(ganacheUrl)) @@ -116,6 +118,8 @@ def RunTests_VerifyIndividually() -> None: keyJson=CHECKSUM_KEYS_PATH ) + gasCosts = {} + # deploy IASRootCertMgr contract print('Deploying IASRootCertMgr contract...') iasRootContract = EthContractHelper.LoadContract( @@ -138,6 +142,8 @@ def RunTests_VerifyIndividually() -> None: print('IASRootCertMgr contract deployed at {}'.format(iasRootAddr)) print() + gasCosts['deployIasRootCertMgr'] = iasRootReceipt.gasUsed + # deploy IASReportCertMgr contract print('Deploying IASReportCertMgr contract...') iasReportContract = EthContractHelper.LoadContract( @@ -167,9 +173,11 @@ def RunTests_VerifyIndividually() -> None: ) print() + gasCosts['deployIasReportCertMgr'] = iasReportReceipt.gasUsed + # verify IAS report certificate print('Verifying IAS report certificate...') - EthContractHelper.CallContractFunc( + verifyReceipt = EthContractHelper.CallContractFunc( w3=w3, contract=iasReportContract, funcName='verifyCert', @@ -181,6 +189,8 @@ def RunTests_VerifyIndividually() -> None: ) print() + gasCosts['verifyIasReportCert'] = verifyReceipt.gasUsed + # deploy DecentServerCertMgr contract print('Deploying DecentServerCertMgr contract...') decentSvrContract = EthContractHelper.LoadContract( @@ -210,9 +220,11 @@ def RunTests_VerifyIndividually() -> None: ) print() + gasCosts['deployDecentServerCertMgr'] = decentSvrReceipt.gasUsed + # verify Decent server certificate print('Verifying Decent Server certificate...') - EthContractHelper.CallContractFunc( + verifyReceipt = EthContractHelper.CallContractFunc( w3=w3, contract=decentSvrContract, funcName='verifyCert', @@ -224,6 +236,8 @@ def RunTests_VerifyIndividually() -> None: ) print() + gasCosts['verifyDecentServerCert'] = verifyReceipt.gasUsed + # deploy HelloWorldApp contract print('Deploying HelloWorldApp contract...') decentAppContract = EthContractHelper.LoadContract( @@ -253,9 +267,11 @@ def RunTests_VerifyIndividually() -> None: ) print() + gasCosts['deployHelloWorldApp'] = decentAppReceipt.gasUsed + # verify Decent server certificate print('Verifying Decent App certificate...') - EthContractHelper.CallContractFunc( + verifyReceipt = EthContractHelper.CallContractFunc( w3=w3, contract=decentAppContract, funcName='loadAppCert', @@ -270,6 +286,10 @@ def RunTests_VerifyIndividually() -> None: ) print() + gasCosts['verifyDecentAppCert'] = verifyReceipt.gasUsed + + return gasCosts + def RunTests_VerifyAllOnce() -> None: # connect to ganache @@ -293,6 +313,8 @@ def RunTests_VerifyAllOnce() -> None: keyJson=CHECKSUM_KEYS_PATH ) + gasCosts = {} + # deploy IASRootCertMgr contract print('Deploying IASRootCertMgr contract...') iasRootContract = EthContractHelper.LoadContract( @@ -390,7 +412,7 @@ def RunTests_VerifyAllOnce() -> None: # verify Decent certificate chain print('Verifying Decent App certificate...') - EthContractHelper.CallContractFunc( + verifyReceipt = EthContractHelper.CallContractFunc( w3=w3, contract=decentAppContract, funcName='verifyCertChain', @@ -405,6 +427,22 @@ def RunTests_VerifyAllOnce() -> None: ) print() + gasCosts['verifyCertChain'] = verifyReceipt.gasUsed + + return gasCosts + + +def EvaluateGasCosts() -> None: + gasCosts1 = RunTests_VerifyIndividually() + gasCosts2 = RunTests_VerifyAllOnce() + gasCost = { + **gasCosts1, + **gasCosts2, + } + savePath = os.path.join(BUILD_DIR, 'gas_costs.json') + with open(savePath, 'w') as f: + json.dump(gasCost, f, indent='\t') + def StopGanache(ganacheProc: subprocess.Popen) -> None: print('Shutting down ganache (it may take ~15 seconds)...') @@ -441,6 +479,10 @@ def main(): 'all', help='Verify certificates all at once' ) + modParser.add_parser( + 'eval', + help='Evaluate gas costs and save results to a JSON file' + ) args = argParser.parse_args() # logging configuration @@ -455,6 +497,8 @@ def main(): RunTests_VerifyIndividually() elif args.testMode == 'all': RunTests_VerifyAllOnce() + elif args.testMode == 'eval': + EvaluateGasCosts() else: raise RuntimeError('Unexpected test mode: {}'.format(args.testMode)) finally: diff --git a/utils/gas_cost_eval_requirements.txt b/utils/gas_cost_eval_requirements.txt new file mode 100644 index 0000000..8498ae0 --- /dev/null +++ b/utils/gas_cost_eval_requirements.txt @@ -0,0 +1,7 @@ +web3==6.2.0 +requests==2.28.2 +numpy==1.24.3 +matplotlib==3.7.1 +plotly==5.14.1 +kaleido==0.2.1 +pandas==2.0.1 \ No newline at end of file