Compare commits
440 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 69599db279 | |||
| d81cb903ad | |||
| 06a3c518fe | |||
| 7a2c49262f | |||
| 7479f2be35 | |||
| acfb0a7cc2 | |||
| d658c90b6d | |||
| 2ae2708fd8 | |||
| 36f2da87c3 | |||
| fef5731b58 | |||
| 92945e4572 | |||
| c32f4e4f7a | |||
| c8535689e2 | |||
| 8b76fa3f7c | |||
| a762ebdbab | |||
| d244ead4d8 | |||
| 4153ba41f7 | |||
| 62f04bd94d | |||
| d607a92712 | |||
| 425fc6c3c2 | |||
| 00cb315396 | |||
| a53fc34ce3 | |||
| a294a08ab7 | |||
| bad7b81900 | |||
| db42ab457f | |||
| b086797420 | |||
| 09b234bf35 | |||
| b9f47e0119 | |||
| fb6ad1be16 | |||
| 01fa60da98 | |||
| 9e72ac27eb | |||
| 9e811a371f | |||
| 6606549ca4 | |||
| c74f115754 | |||
| cdd38e2843 | |||
| 06c541cece | |||
| 664f4d624b | |||
| b38155045a | |||
| f26edc8627 | |||
| 4c56554cdf | |||
| ecb339bb64 | |||
| 3793b76ac5 | |||
| c7ce2a9de6 | |||
| c4ea7b7c3f | |||
| 3c95130678 | |||
| c214b8d68c | |||
| ac6952d6d5 | |||
| e4b134ddef | |||
| 6053155040 | |||
| 0367525f76 | |||
| fdfc1908c3 | |||
| 04367180e9 | |||
| a8705b701b | |||
| 647b82a089 | |||
| b8b927822e | |||
| 9ff9017aa4 | |||
| 37abd4be39 | |||
| 4d84c74e64 | |||
| b27ae09d6a | |||
| 02c01a150e | |||
| 86f0e0e745 | |||
| b146e8efa4 | |||
| e97e16a371 | |||
| 60902e9e38 | |||
| eac3929865 | |||
| 7bdb80e33f | |||
| 2e0a036574 | |||
| c3223aefe2 | |||
| dcd84c4da0 | |||
| 96fb93bb38 | |||
| d25324cf8a | |||
| 28083257c0 | |||
| 0b8f5fea25 | |||
| 74b8ab8764 | |||
| bc2420a3cf | |||
| 28bc1bfb88 | |||
| 697ab13a68 | |||
| 5937050834 | |||
| 21133bba37 | |||
| 64cbbd29a4 | |||
| 204dcf0baf | |||
| ff10448ae8 | |||
| 58559f7915 | |||
| dc19551940 | |||
| b9b3c70b1e | |||
| 9e43412631 | |||
| 733be5fde5 | |||
| 4e833dec5d | |||
| d697c579ee | |||
| 259f42785f | |||
| 00f721cbc8 | |||
| 5f70b45944 | |||
| 814c16f979 | |||
| 07c2fec73c | |||
| 1631a59471 | |||
| 47554ec338 | |||
| e34e8f83c2 | |||
| bc5974f2a0 | |||
| 7ce35739b4 | |||
| 2ba236cdd5 | |||
| 6bfccfde76 | |||
| 6abb8dbb26 | |||
| e1227b7767 | |||
| a3ad5f6f78 | |||
| d51ad33ef5 | |||
| 91b4b00ebe | |||
| 0acd966180 | |||
| 090c99fd66 | |||
| aa16dcd65a | |||
| 061efae475 | |||
| aea6188d15 | |||
| d7fa594cc3 | |||
| 1df88ab31c | |||
| 438cc150ae | |||
| b6a42b47fc | |||
| cbf17eb10c | |||
| 58bd4c0ad5 | |||
| 8af48755a0 | |||
| 4848fb2423 | |||
| 5f76c082c0 | |||
| 6e8d8b2653 | |||
| 24639d6aa6 | |||
| 13ce859c98 | |||
| 566563f3f3 | |||
| df4a8c2fb9 | |||
| dd6ffaa864 | |||
| 79d466e089 | |||
| de416fd0e8 | |||
| 7cab68c568 | |||
| ca6f0a1aee | |||
| e798246586 | |||
| 797d5aa714 | |||
| 755ddc5d54 | |||
| bc1f595e7a | |||
| ecd7c0ec88 | |||
| 13e3b3be27 | |||
| f654409858 | |||
| 0aaf6a233e | |||
| b35845994b | |||
| 676233a28e | |||
| de050b2959 | |||
| 67b646c730 | |||
| 7454073875 | |||
| f45496e454 | |||
| 1c9cd27993 | |||
| d3cac6a644 | |||
| 34576751fc | |||
| bb66029001 | |||
| 10e896741a | |||
| 20a036c4cc | |||
| f669a1ec67 | |||
| 2bd39eb47f | |||
| 6d16938419 | |||
| 939b0cf024 | |||
| 9bc60ad125 | |||
| b540567a2d | |||
| e278557637 | |||
| 2b114e75f4 | |||
| 9b4d922c73 | |||
| d793d443ac | |||
| a12e6df843 | |||
| 8abaf40454 | |||
| 582f38a64d | |||
| 34a71155ef | |||
| 617bfe6330 | |||
| cfec3f1446 | |||
| f27981b4f7 | |||
| 89099625e9 | |||
| b307b2ed0d | |||
| 2853bc1d0a | |||
| b0b2e8e3d1 | |||
| 1dcd1923a6 | |||
| fde97b1563 | |||
| fa72f82451 | |||
| 21fa60dab0 | |||
| b97d5631de | |||
| defff56bda | |||
| f3380facc0 | |||
| 53e4574517 | |||
| a0e7748412 | |||
| 5acda86dd9 | |||
| 7028e80f44 | |||
| 551179192c | |||
| 98f94f634e | |||
| e211d6a154 | |||
| b4a95f95c2 | |||
| 376cb89a68 | |||
| c19cde4daf | |||
| e7473c3e9a | |||
| f1feb03207 | |||
| 14684af1c1 | |||
| f2f23f9b84 | |||
| dbdfa5f00c | |||
| b1cfa305bc | |||
| f2e8e9209c | |||
| 29f4232238 | |||
| bec0d6cac9 | |||
| 387c2b8624 | |||
| 9c5c88cc85 | |||
| 76de7e8b9a | |||
| b2c7d0deed | |||
| 6b98462d0d | |||
| 6d4f93229c | |||
| afdcd5269f | |||
| 6ffc9c985a | |||
| 18b09ddccb | |||
| b949569188 | |||
| 293ee7a4b0 | |||
| 8a164d06bf | |||
| d660810d2e | |||
| bc90b7170a | |||
| f228975712 | |||
| cf6988a803 | |||
| 65ac0987a4 | |||
| 93ddaaa5e3 | |||
| db51a8ee38 | |||
| 40681c7283 | |||
| 12df4cc329 | |||
| a88c7b8f56 | |||
| 775d671e1e | |||
| c250347804 | |||
| a50e3a43a7 | |||
| 83a594dfbe | |||
| 0b2c5eb909 | |||
| 698c54c00e | |||
| cceffd7275 | |||
| 9ecdca0f08 | |||
| 198b32e962 | |||
| 6ba64dacb5 | |||
| 6da162abea | |||
| da7e87ad9e | |||
| 44321e257d | |||
| c71fc70d07 | |||
| d803deac88 | |||
| e97603726a | |||
| 13f21ef100 | |||
| c646d38e98 | |||
| 0ab129eb93 | |||
| f5e7976a9d | |||
| a95b1d4936 | |||
| a306d507f1 | |||
| bdba2fa7ce | |||
| 904b177890 | |||
| 582244a233 | |||
| 3cd6a4a4e7 | |||
| c538d947a5 | |||
| e40b7d35eb | |||
| 7ef58b4c65 | |||
| 2912af0a9d | |||
| 99600bb8d6 | |||
| baa3f58cc4 | |||
| 01b3b6e7da | |||
| e610d1b14e | |||
| 7906f2a2fb | |||
| 7719029931 | |||
| 4911e5fc0b | |||
| 4eee901c29 | |||
| 921e850e65 | |||
| dc1019e410 | |||
| 5763afdb48 | |||
| 26414ada06 | |||
| 75eb06ea03 | |||
| 28794f472e | |||
| 42c0a9d158 | |||
| b067f1c76b | |||
| 26289ffcaa | |||
| 0d42f9bc77 | |||
| b8b9318784 | |||
| fd49c7b08c | |||
| 6906563d89 | |||
| b9e8265d5b | |||
| 6cda379dc3 | |||
| 3b07180665 | |||
| d31c73a65b | |||
| 47e1b5175a | |||
| 5634784cd0 | |||
| 589faab1d0 | |||
| b1eacc8b9f | |||
| e87d621b0c | |||
| da082d4d47 | |||
| d572004e4d | |||
| a2e3f3f240 | |||
| 98e09b9ffa | |||
| 4c47d241b8 | |||
| 7eeaba0761 | |||
| a532a6dec4 | |||
| c82af4eb22 | |||
| f43d6efc79 | |||
| 8ab3b6b5b3 | |||
| 30786faac5 | |||
| cb73eae845 | |||
| 5e504d3e62 | |||
| 290e80681a | |||
| 5641111004 | |||
| 1c151b52f7 | |||
| f9331b180d | |||
| c90795ee12 | |||
| 5bdd337b61 | |||
| 6e8e98a949 | |||
| 3588c2c3c7 | |||
| 8cdc0f4596 | |||
| b124284d13 | |||
| 122ff0807c | |||
| 34c7f69913 | |||
| 6beeb6c92c | |||
| c076567d0e | |||
| 677e739462 | |||
| 260c2a27e1 | |||
| 481d28a54d | |||
| e537352ed9 | |||
| df382e485c | |||
| 21b4ab66d8 | |||
| dd0887c4d1 | |||
| 71366defce | |||
| 4d2931fd01 | |||
| 26f8d67140 | |||
| 62b283dcd4 | |||
| 359f483b68 | |||
| 3dcdca1a27 | |||
| dae43fd8f4 | |||
| 89bb917359 | |||
| 46b336c18a | |||
| f897dc7b82 | |||
| bf7fe2e3e5 | |||
| 181595fd38 | |||
| 977d18802a | |||
| 70928133ee | |||
| 734da3fd79 | |||
| 00a8c47ef7 | |||
| c09fcff613 | |||
| bb32acc377 | |||
| f8b654855d | |||
| eff46f2020 | |||
| 2c8868e46a | |||
| 7e2efdafda | |||
| 59bb425a25 | |||
| e2d7bfbf79 | |||
| ea06f6cc82 | |||
| 87672eedb5 | |||
| 4b6430ed3a | |||
| f6ef88a7d8 | |||
| c3af527450 | |||
| 6683402357 | |||
| 6b55a4f119 | |||
| f88520b2f1 | |||
| 88b1dac112 | |||
| e2303c042f | |||
| d6721b2d66 | |||
| 93f6a186aa | |||
| 6f637b05cb | |||
| 8d6265dd98 | |||
| 1dc5b7d8d6 | |||
| 2a2db21d0a | |||
| 3e233826c0 | |||
| 938204c5c7 | |||
| 824cf1f410 | |||
| 17b6b4dcc9 | |||
| 409e5b2f31 | |||
| 5f1ad6f6e7 | |||
| 492d92373e | |||
| 5a0664705c | |||
| 6f61e69554 | |||
| 01d06ab650 | |||
| 4673b4524a | |||
| 116c6ba28d | |||
| 2601d3e2a5 | |||
| d87749e732 | |||
| 14351e0d84 | |||
| 0f0a02c314 | |||
| 7b55d92177 | |||
| a46c482228 | |||
| 1219fe772e | |||
| c27e69e49b | |||
| 8160de1e9a | |||
| 9a1164b487 | |||
| 3777db3212 | |||
| 0056647020 | |||
| b2386d9ff3 | |||
| 6e98fda59f | |||
| 8f467812bc | |||
| 34ad214294 | |||
| 6c78f0ae61 | |||
| 73662c240a | |||
| 19749dd297 | |||
| 208274a8f6 | |||
| dc8d62c5c7 | |||
| b2d6f0b18d | |||
| c1eca818a9 | |||
| 9e3d4a0a72 | |||
| e644e75d3e | |||
| 0a747a936d | |||
| b540790b05 | |||
| 134a7cd141 | |||
| 482de2c29e | |||
| 19b3b249aa | |||
| 459fa3226d | |||
| 3f701e2ea9 | |||
| 8a18e7a976 | |||
| 9d1424dfcf | |||
| 7a6dfcb4a5 | |||
| b5d71e23d6 | |||
| 21a82212b3 | |||
| 2838fe7641 | |||
| baa6147ee3 | |||
| 7b058b424a | |||
| 6ed17a2b10 | |||
| 2975faaca2 | |||
| 9142b6929f | |||
| 5a97108c6e | |||
| 78ced4c9ef | |||
| df628a1409 | |||
| 44379dc422 | |||
| 80ef3056dc | |||
| e2bec04986 | |||
| f778277931 | |||
| 861a86e500 | |||
| aa6efda41d | |||
| 5b06bd3451 | |||
| 8671ca2677 | |||
| a7fa7519b6 | |||
| 4bae47bf94 | |||
| e3ef75c352 | |||
| 8a6bfbde42 | |||
| 65f928fcde | |||
| a1aae5f8d2 | |||
| 2b0fd5c55b | |||
| 94ca0508dd | |||
| 46c13e9e9d | |||
| 5683746983 | |||
| 5931b591c5 | |||
| 23510b2d3c | |||
| aa0904a420 | |||
| 9a7e23f8f4 | |||
| 99e80b1b9a | |||
| 23a78365b1 | |||
| bfb1edb40b | |||
| 5fe3166773 | |||
| 19d33cca18 | |||
| be7b70ccae | |||
| c82a076e38 |
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"antelope-spring-dev":{
|
||||
"target":"release/2.0",
|
||||
"prerelease":false
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"ubuntu18": {
|
||||
"dockerfile": ".cicd/platforms/ubuntu18.Dockerfile"
|
||||
},
|
||||
"ubuntu20": {
|
||||
"dockerfile": ".cicd/platforms/ubuntu20.Dockerfile"
|
||||
},
|
||||
"ubuntu22": {
|
||||
"dockerfile": ".cicd/platforms/ubuntu22.Dockerfile"
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
FROM ubuntu:bionic
|
||||
|
||||
RUN apt-get update && apt-get upgrade -y && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential \
|
||||
g++-8 \
|
||||
curl \
|
||||
ninja-build \
|
||||
software-properties-common \
|
||||
zlib1g-dev \
|
||||
pkg-config \
|
||||
libboost-all-dev \
|
||||
libcurl4-gnutls-dev
|
||||
|
||||
RUN curl -L https://cmake.org/files/v3.13/cmake-3.13.5.tar.gz | tar zx && \
|
||||
cd cmake-3.13.5 && \
|
||||
./configure && \
|
||||
make -j$(nproc) install && \
|
||||
cd .. && \
|
||||
rm -rf cmake-3.13.5
|
||||
|
||||
RUN add-apt-repository ppa:git-core/ppa && apt update && apt install -y git
|
||||
|
||||
RUN curl -L https://www.python.org/ftp/python/3.10.6/Python-3.10.6.tgz | tar zx && \
|
||||
cd Python* && \
|
||||
./configure --enable-optimizations --prefix=/usr && \
|
||||
make -j$(nproc) install && \
|
||||
cd .. && \
|
||||
rm -rf Python*
|
||||
|
||||
ENV CC=gcc-8
|
||||
ENV CXX=g++-8
|
||||
@@ -0,0 +1,23 @@
|
||||
FROM ubuntu:jammy
|
||||
|
||||
RUN apt-get update && apt-get upgrade -y && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential \
|
||||
cmake \
|
||||
wget \
|
||||
git \
|
||||
ninja-build \
|
||||
python3 \
|
||||
pkg-config \
|
||||
libboost-all-dev \
|
||||
libcurl4-gnutls-dev \
|
||||
lsb-release \
|
||||
software-properties-common \
|
||||
gnupg \
|
||||
clang-tidy
|
||||
|
||||
RUN wget https://apt.llvm.org/llvm.sh
|
||||
RUN chmod +x llvm.sh
|
||||
RUN ./llvm.sh 16
|
||||
|
||||
ENV CC=clang-16
|
||||
ENV CXX=clang++-16
|
||||
@@ -0,0 +1,12 @@
|
||||
FROM ubuntu:noble
|
||||
|
||||
RUN apt-get update && apt-get upgrade -y && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential \
|
||||
cmake \
|
||||
git \
|
||||
ninja-build \
|
||||
python3 \
|
||||
pkg-config \
|
||||
libboost-all-dev \
|
||||
libcurl4-gnutls-dev \
|
||||
clang-tidy
|
||||
@@ -7,6 +7,17 @@ on:
|
||||
- "release/*"
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
override-antelope-spring-dev:
|
||||
description: Override antelope-spring-dev target
|
||||
type: string
|
||||
override-antelope-spring-dev-prerelease:
|
||||
type: choice
|
||||
description: Override antelope-spring-dev prelease
|
||||
options:
|
||||
- default
|
||||
- true
|
||||
- false
|
||||
|
||||
permissions:
|
||||
packages: write
|
||||
@@ -17,73 +28,69 @@ defaults:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
d:
|
||||
name: Discover Platforms
|
||||
platform-cache:
|
||||
name: Platform Cache
|
||||
uses: AntelopeIO/platform-cache-workflow/.github/workflows/platformcache.yaml@v1
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
with:
|
||||
runs-on: '["self-hosted", "enf-x86-beefy"]'
|
||||
platform-files: .cicd/platforms
|
||||
|
||||
versions:
|
||||
name: Determine Versions
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
missing-platforms: ${{steps.discover.outputs.missing-platforms}}
|
||||
p: ${{steps.discover.outputs.platforms}}
|
||||
antelope-spring-dev-target: ${{steps.versions.outputs.antelope-spring-dev-target}}
|
||||
antelope-spring-dev-prerelease: ${{steps.versions.outputs.antelope-spring-dev-prerelease}}
|
||||
steps:
|
||||
- name: Discover Platforms
|
||||
id: discover
|
||||
uses: AntelopeIO/discover-platforms-action@v1
|
||||
with:
|
||||
platform-file: .cicd/platforms.json
|
||||
password: ${{secrets.GITHUB_TOKEN}}
|
||||
package-name: builders
|
||||
build-platforms:
|
||||
name: Build Platforms
|
||||
needs: d
|
||||
if: needs.d.outputs.missing-platforms != '[]'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: ${{fromJSON(needs.d.outputs.missing-platforms)}}
|
||||
runs-on: ["self-hosted", "enf-x86-beefy"]
|
||||
steps:
|
||||
- name: Login to Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{github.repository_owner}}
|
||||
password: ${{secrets.GITHUB_TOKEN}}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
push: true
|
||||
tags: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}}
|
||||
file: ${{fromJSON(needs.d.outputs.p)[matrix.platform].dockerfile}}
|
||||
- name: Setup versions from input or defaults
|
||||
id: versions
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
run: |
|
||||
DEFAULTS_JSON=$(curl -sSfL $(gh api https://api.github.com/repos/${{github.repository}}/contents/.cicd/defaults.json?ref=${{github.sha}} --jq .download_url))
|
||||
echo antelope-spring-dev-target=$(echo "$DEFAULTS_JSON" | jq -r '."antelope-spring-dev".target') >> $GITHUB_OUTPUT
|
||||
echo antelope-spring-dev-prerelease=$(echo "$DEFAULTS_JSON" | jq -r '."antelope-spring-dev".prerelease') >> $GITHUB_OUTPUT
|
||||
|
||||
if [[ "${{inputs.override-antelope-spring-dev}}" != "" ]]; then
|
||||
echo antelope-spring-dev-target=${{inputs.override-antelope-spring-dev}} >> $GITHUB_OUTPUT
|
||||
fi
|
||||
if [[ "${{inputs.override-antelope-spring-dev-prerelease}}" == +(true|false) ]]; then
|
||||
echo antelope-spring-dev-prerelease=${{inputs.override-antelope-spring-dev-prerelease}} >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
Build:
|
||||
name: Build & Test
|
||||
needs: [d, build-platforms]
|
||||
if: always() && needs.d.result == 'success' && (needs.build-platforms.result == 'success' || needs.build-platforms.result == 'skipped')
|
||||
needs: [platform-cache, versions]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [ubuntu18, ubuntu20, ubuntu22]
|
||||
platform: [ubuntu20, ubuntu22, ubuntu22-llvm, ubuntu24]
|
||||
runs-on: ["self-hosted", "enf-x86-beefy"]
|
||||
container: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}}
|
||||
container: ${{fromJSON(needs.platform-cache.outputs.platforms)[matrix.platform].image}}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Download leap-dev.deb (Ubuntu 20 only)
|
||||
if: matrix.platform == 'ubuntu20'
|
||||
uses: AntelopeIO/asset-artifact-download-action@v2
|
||||
- name: Download antelope-spring-dev.deb (Ubuntu 22 only)
|
||||
if: matrix.platform == 'ubuntu22'
|
||||
uses: AntelopeIO/asset-artifact-download-action@v3
|
||||
with:
|
||||
owner: AntelopeIO
|
||||
repo: leap
|
||||
file: 'leap-dev.*(x86_64|amd64).deb'
|
||||
target: 4.0
|
||||
artifact-name: leap-dev-ubuntu20-amd64
|
||||
container-package: experimental-binaries
|
||||
token: ${{github.token}}
|
||||
- name: Install leap-dev.deb (Ubuntu 20 only)
|
||||
if: matrix.platform == 'ubuntu20'
|
||||
repo: spring
|
||||
file: 'antelope-spring-dev.*ubuntu22\.04_amd64.deb'
|
||||
target: '${{needs.versions.outputs.antelope-spring-dev-target}}'
|
||||
prereleases: ${{fromJSON(needs.versions.outputs.antelope-spring-dev-prerelease)}}
|
||||
artifact-name: antelope-spring-dev-ubuntu22-amd64
|
||||
container-package: antelope-spring-experimental-binaries
|
||||
- name: Install antelope-spring-dev.deb (Ubuntu 22 only)
|
||||
if: matrix.platform == 'ubuntu22'
|
||||
run: |
|
||||
apt-get update && apt-get upgrade -y
|
||||
apt install -y ./leap-dev*.deb
|
||||
rm ./leap-dev*.deb
|
||||
apt install -y ./antelope-spring-dev*.deb
|
||||
rm ./antelope-spring-dev*.deb
|
||||
- name: Build & Test
|
||||
run: |
|
||||
mkdir build
|
||||
@@ -92,14 +99,14 @@ jobs:
|
||||
make -j $(nproc)
|
||||
cd tests
|
||||
ctest -j $(nproc) --output-on-failure
|
||||
- name: Package (Ubuntu 18 only)
|
||||
if: matrix.platform == 'ubuntu18'
|
||||
- name: Package (Ubuntu 20 only)
|
||||
if: matrix.platform == 'ubuntu20'
|
||||
run: |
|
||||
cd build/packages
|
||||
bash generate_package.sh deb ubuntu amd64
|
||||
- name: Upload (Ubuntu 18 only)
|
||||
if: matrix.platform == 'ubuntu18'
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload (Ubuntu 20 only)
|
||||
if: matrix.platform == 'ubuntu20'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cdt_ubuntu_package_amd64
|
||||
path: build/packages/cdt*amd64.deb
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
name: Upload Release .deb
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
eb:
|
||||
name: Upload Release .deb
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
actions: read
|
||||
steps:
|
||||
- name: Get cdt.deb
|
||||
id: getter
|
||||
uses: AntelopeIO/asset-artifact-download-action@v3
|
||||
with:
|
||||
owner: ${{github.repository_owner}}
|
||||
repo: ${{github.event.repository.name}}
|
||||
file: cdt_.*_amd64.deb
|
||||
target: ${{github.sha}}
|
||||
artifact-name: cdt_ubuntu_package_amd64
|
||||
wait-for-exact-target: true
|
||||
- run: |
|
||||
curl -LsSf \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{github.token}}" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary "@${{steps.getter.outputs.downloaded-file}}" \
|
||||
"https://uploads.github.com/repos/${{github.repository}}/releases/${{github.event.release.id}}/assets?name=${{steps.getter.outputs.downloaded-file}}"
|
||||
+1
-1
@@ -9,4 +9,4 @@
|
||||
url = https://github.com/AntelopeIO/cdt-libcxx
|
||||
[submodule "libraries/native/softfloat"]
|
||||
path = libraries/native/softfloat
|
||||
url = https://github.com/AntelopeIO/berkeley-softfloat-3
|
||||
url = https://github.com/AntelopeIO/berkeley-softfloat-3
|
||||
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.5...4.0)
|
||||
|
||||
# Sanity check our source directory to make sure that we are not trying to
|
||||
# generate an in-source build, and to make
|
||||
@@ -13,10 +13,10 @@ endif()
|
||||
|
||||
project(cdt)
|
||||
|
||||
set(VERSION_MAJOR 4)
|
||||
set(VERSION_MAJOR 5)
|
||||
set(VERSION_MINOR 0)
|
||||
set(VERSION_PATCH 1)
|
||||
set(VERSION_SUFFIX "rc1")
|
||||
set(VERSION_PATCH 0)
|
||||
set(VERSION_SUFFIX "dev1")
|
||||
|
||||
if (VERSION_SUFFIX)
|
||||
set(VERSION_FULL "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_SUFFIX}")
|
||||
|
||||
@@ -15,8 +15,8 @@ CDT currently supports Linux x86_64 Debian packages. Visit the [release page](ht
|
||||
Download the appropriate version of the Debian package and then install it. To download and install the latest version, run the following:
|
||||
|
||||
```sh
|
||||
wget https://github.com/AntelopeIO/cdt/releases/download/v4.0.0/cdt_4.0.0_amd64.deb
|
||||
sudo apt install ./cdt_4.0.0_amd64.deb
|
||||
wget https://github.com/AntelopeIO/cdt/releases/download/v4.1.0/cdt_4.1.0_amd64.deb
|
||||
sudo apt install ./cdt_4.1.0_amd64.deb
|
||||
```
|
||||
### Debian package uninstall
|
||||
|
||||
@@ -28,9 +28,9 @@ sudo apt remove cdt
|
||||
|
||||
## Building from source
|
||||
|
||||
Recent Ubuntu LTS releases are the only Linux distributions that we fully support. Other Linux distros and other POSIX operating systems (such as macOS) are tended to on a best-effort basis and may not be full featured.
|
||||
Recent Ubuntu LTS releases are the only Linux distributions that we fully support. Other Linux distros and other POSIX operating systems (such as macOS) are tended to on a best-effort basis and may not be full featured.
|
||||
|
||||
The instructions below assume that you are building on Ubuntu 20.04.
|
||||
The instructions below assume that you are building on Ubuntu 20.04.
|
||||
|
||||
### Install dependencies
|
||||
|
||||
@@ -38,6 +38,7 @@ The instructions below assume that you are building on Ubuntu 20.04.
|
||||
apt-get update && apt-get install \
|
||||
build-essential \
|
||||
clang \
|
||||
clang-tidy \
|
||||
cmake \
|
||||
git \
|
||||
libxml2-dev \
|
||||
@@ -53,19 +54,19 @@ python3 -m pip install pygments
|
||||
|
||||
### Allowing integration tests to build
|
||||
|
||||
Integration tests require access to a build of [Leap](https://github.com/AntelopeIO/leap), a C++ implementation of the Antelope protocol. Simply installing Leap from a binary package will not be sufficient.
|
||||
Integration tests require access to a build of [Spring](https://github.com/AntelopeIO/spring), a C++ implementation of the Antelope protocol. Simply installing Spring from a binary package will not be sufficient.
|
||||
|
||||
If you do not wish to build Leap, you can continue with building CDT but without building the integration tests. Otherwise, follow the instructions below before running `cmake`.
|
||||
If you do not wish to build Spring, you can continue with building CDT but without building the integration tests. Otherwise, follow the instructions below before running `cmake`.
|
||||
|
||||
First, ensure that Leap has been built from source (see Leap's [README](https://github.com/AntelopeIO/leap#building-from-source) for details) and identify the build path, e.g. `/path/to/leap/build/`.
|
||||
First, ensure that Spring has been built from source (see Spring's [README](https://github.com/AntelopeIO/spring#building-from-source) for details) and identify the build path, e.g. `/path/to/spring/build/`.
|
||||
|
||||
Then, execute the following command in the same terminal session that you will use to build CDT:
|
||||
|
||||
```sh
|
||||
export leap_DIR=/path/to/leap/build/lib/cmake/leap
|
||||
export spring_DIR=/path/to/spring/build/lib/cmake/spring
|
||||
```
|
||||
|
||||
Now you can continue with the steps to build CDT as described. When you run `cmake` make sure that it does not report `leap package not found`. If it does, this means CDT was not able to find a build of Leap at the specified path in `leap_DIR` and will therefore continue without building the integration tests.
|
||||
Now you can continue with the steps to build CDT as described. When you run `cmake` make sure that it does not report `spring package not found`. If it does, this means CDT was not able to find a build of Spring at the specified path in `spring_DIR` and will therefore continue without building the integration tests.
|
||||
|
||||
### ccache
|
||||
|
||||
@@ -135,7 +136,7 @@ Installing CDT globally on your system will install the following tools in a loc
|
||||
* cdt-strip
|
||||
* eosio-pp
|
||||
* eosio-wasm2wast
|
||||
* eosio-wast2wasm
|
||||
* eosio-wast2wasm
|
||||
|
||||
It will also install CMake files for CDT accessible within a `cmake/cdt` directory located within your system's `lib` directory.
|
||||
#### Manual installation
|
||||
|
||||
+1
-1
Submodule cdt-llvm updated: 6650e8c6b4...34c0de5404
@@ -47,7 +47,7 @@ compiler options:
|
||||
-finline-hint-functions - Inline functions which are (explicitly or implicitly) marked inline
|
||||
-fmerge-all-constants - Allow merging of constants
|
||||
-fnative - Compile and link for x86-64
|
||||
-fno-cfl-aa - Disable CFL Alias Analysis
|
||||
-fcfl-aa - Enable CFL Alias Analysis
|
||||
-fno-elide-constructors - Disable C++ copy constructor elision
|
||||
-fno-lto - Disable LTO
|
||||
-fno-post-pass - Don't run post processing pass
|
||||
|
||||
@@ -49,7 +49,7 @@ compiler options:
|
||||
-finline-hint-functions - Inline functions which are (explicitly or implicitly) marked inline
|
||||
-fmerge-all-constants - Allow merging of constants
|
||||
-fnative - Compile and link for x86-64
|
||||
-fno-cfl-aa - Disable CFL Alias Analysis
|
||||
-cfl-aa - Enable CFL Alias Analysis
|
||||
-fno-elide-constructors - Disable C++ copy constructor elision
|
||||
-fno-lto - Disable LTO
|
||||
-fno-post-pass - Don't run post processing pass
|
||||
|
||||
@@ -21,7 +21,7 @@ ld options:
|
||||
-L=<string> - Add directory to library search path
|
||||
-fasm - Assemble file for x86-64
|
||||
-fnative - Compile and link for x86-64
|
||||
-fno-cfl-aa - Disable CFL Alias Analysis
|
||||
-fcfl-aa - Enable CFL Alias Analysis
|
||||
-fno-lto - Disable LTO
|
||||
-fno-post-pass - Don't run post processing pass
|
||||
-fno-stack-first - Don't set the stack first in memory
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
---
|
||||
content_title: Crypto Extensions
|
||||
content_title: Crypto Extensions API
|
||||
---
|
||||
|
||||
As of `v3.0` crypto host functions were extended to include
|
||||
- `mod_exp`: Big integer modular exponentiation
|
||||
- `alt_bn128_add`, `alt_bn128_mul`, `alt_bn128_pair`: Add, multiply, and pairing check functions for the `alt_bn128` elliptic curve
|
||||
- `blake2_f`: `BLAKE2b F` compression function
|
||||
- `sha3`: sha3` hash function using `SHA3 NIST`
|
||||
- `Keccak256`: `sha3` hash function using `SHA3 Keccak`
|
||||
- `k1_recover`: Safe `ECDSA` uncompressed pubkey recover for the `secp256k1` curve
|
||||
|
||||
In `v3.0`, `C` format was supported; in `v3.1`, `C++` format was added for better data abstraction.
|
||||
Antelope blockchain implements cryptographic functions for operations on points on elliptic curves, computing hashes
|
||||
of big integers, big integer modular exponentiation, and other operations useful for implementing
|
||||
cryptographic algorithms in your contracts.
|
||||
|
||||
## Prerequisites
|
||||
In order to use the Crypto Extensions API you need to activate a protocol feature `CRYPTO_PRIMITIVES`
|
||||
in `nodeos`. To do this you should call the following command in your command line:
|
||||
|
||||
- In `nodeos`, activate protocol feature `CRYPTO_PRIMITIVES` (`68d6405cb8df3de95bd834ebb408196578500a9f818ff62ccc68f60b932f7d82`)
|
||||
- In smart contract code, include `crypto_ext.hpp`
|
||||
`"cleos push action eosio activate ["6bcb40a24e49c26d0a60513b6aeb8551d264e4717f306b81a37a5afb3b47cedc"] -p eosio@active"`
|
||||
|
||||
## C Format
|
||||
And you need to include in the source code of your contract the following header: [crypto_ext.hpp](https://github.com/AntelopeIO/cdt/blob/main/libraries/eosiolib/core/eosio/crypto_ext.hpp)
|
||||
|
||||
The header declares following basic plain C functions which implement the core functionality:
|
||||
|
||||
## Plain C API
|
||||
|
||||
- `int32_t alt_bn128_add( const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* result, uint32_t result_len )`
|
||||
Perform addition operation on the elliptic curve `alt_bn128`, store the result in `result`, and return `0` if success otherwise `-1`
|
||||
@@ -40,154 +39,92 @@ Test if the SHA3 keccak hash generated from data matches the provided digest
|
||||
- `int32_t k1_recover( const char* sig, uint32_t sig_len, const char* dig, uint32_t dig_len, char* pub, uint32_t pub_len )`
|
||||
Calculates the uncompressed public key used for a given signature on a given digest. Return `0` if success otherwise `-1`
|
||||
|
||||
## C++ Format
|
||||
|
||||
C++ types were added to represent `G1` and `G2` points (read and write) and views (read-only), and represent big integers. Their definitions are
|
||||
Also, the header contains a set of handy C++ wrappers to simplify the contracts code.
|
||||
|
||||
### Types
|
||||
## C++ API
|
||||
|
||||
`ec_point` type was added to represent `G1` and `G2` points on the elliptic curve.
|
||||
`ec_point_view` type was added to provide a read-only interface for access to `G1` and `G2` points data.
|
||||
|
||||
### Data Types
|
||||
|
||||
```c++
|
||||
/**
|
||||
* Abstracts mutable G1 and G2 points
|
||||
*
|
||||
*/
|
||||
// Abstracts mutable G1 and G2 points
|
||||
template <std::size_t Size = 32>
|
||||
struct ec_point {
|
||||
/**
|
||||
* Bytes of the x coordinate
|
||||
*/
|
||||
std::vector<char> x;
|
||||
|
||||
/**
|
||||
* Bytes of the y coordinate
|
||||
*/
|
||||
std::vector<char> y;
|
||||
|
||||
/**
|
||||
* Construct a point given x and y
|
||||
*
|
||||
* @param x_ - The x coordinate, a vector of chars
|
||||
* @param y_ - The y coordinate, a vector of chars
|
||||
*/
|
||||
std::vector<char> x; // x coordinate
|
||||
std::vector<char> y; // y coordinate
|
||||
// Construct from two coordinates represented by big integers
|
||||
ec_point(std::vector<char>& x_, std::vector<char>& y_);
|
||||
|
||||
/**
|
||||
* Construct a point given a serialized point
|
||||
*
|
||||
* @param p - The serialized point
|
||||
*/
|
||||
// Construct from a serialized point
|
||||
ec_point(std::vector<char>& p);
|
||||
|
||||
/**
|
||||
* Return serialzed point containing only x and y
|
||||
*/
|
||||
// Return a serialized point containing only x and y
|
||||
std::vector<char> serialized() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstracts read-only G1 and G2 points
|
||||
*/
|
||||
|
||||
// Abstracts read-only G1 and G2 points
|
||||
template <std::size_t Size = 32>
|
||||
struct ec_point_view {
|
||||
/**
|
||||
* Pointer to the x coordinate
|
||||
*/
|
||||
const char* x;
|
||||
|
||||
/**
|
||||
* Pointer to the y coordinate
|
||||
*/
|
||||
const char* y;
|
||||
|
||||
/**
|
||||
* Number of bytes in each of x and y
|
||||
*/
|
||||
// Number of bytes in each of x and y
|
||||
uint32_t size;
|
||||
|
||||
/**
|
||||
* Construct a point view from x and y
|
||||
*
|
||||
* @param x_ - The x coordinate, poiter to chars
|
||||
* @param x_size - x's size
|
||||
* @param y_ - The y coordinate, poiter to chars
|
||||
* @param y_size - y's size
|
||||
*/
|
||||
// Construct from two coordinates. Their sizes must be equal
|
||||
ec_point_view(const char* x_, uint32_t x_size, const char* y_, uint32_t y_size);
|
||||
|
||||
/**
|
||||
* Construct a point view from a serialized point
|
||||
*
|
||||
* @param p - The serialized point
|
||||
*/
|
||||
// Construct from a serialized point
|
||||
ec_point_view(const std::vector<char>& p);
|
||||
|
||||
/**
|
||||
* Construct a point view from a point
|
||||
*
|
||||
* @param p - The point
|
||||
*/
|
||||
// Construct a point view from a point
|
||||
ec_point_view(const ec_point<Size>& p);
|
||||
|
||||
/**
|
||||
* Return serialzed point containing only x and y
|
||||
*/
|
||||
// Return serialized point containing only x and y
|
||||
std::vector<char> serialized() const;
|
||||
};
|
||||
|
||||
static constexpr size_t g1_coordinate_size = 32;
|
||||
static constexpr size_t g2_coordinate_size = 64;
|
||||
|
||||
using g1_point = ec_point<g1_coordinate_size>;
|
||||
using g2_point = ec_point<g2_coordinate_size>;
|
||||
using g1_point_view = ec_point_view<g1_coordinate_size>;
|
||||
using g2_point_view = ec_point_view<g2_coordinate_size>;
|
||||
|
||||
/**
|
||||
* Big integer.
|
||||
*
|
||||
* @ingroup crypto
|
||||
*/
|
||||
using bigint = std::vector<char>;
|
||||
|
||||
// Big integer.
|
||||
using bigint = std::vector<char>;
|
||||
```
|
||||
|
||||
### Methods
|
||||
|
||||
- `alt_bn128_add`
|
||||
- Addition operation on the elliptic curve `alt_bn128`
|
||||
```c++
|
||||
template <typename T>
|
||||
g1_point alt_bn128_add( const T& op1, const T& op2 )
|
||||
```
|
||||
Take two G1 points or G1 views as input and return a G1 point.
|
||||
- `alt_bn128_mul`
|
||||
|
||||
- Scalar multiplication operation on the elliptic curve `alt_bn128`
|
||||
```c++
|
||||
template <typename T>
|
||||
g1_point alt_bn128_mul( const T& g1, const bigint& scalar)
|
||||
```
|
||||
Take a G1 point or view and a bigint as input and return a G1 point
|
||||
- `alt_bn128_pair`
|
||||
|
||||
- Optimal-Ate pairing check elliptic curve `alt_bn128`
|
||||
```c++
|
||||
template <typename G1_T, typename G2_T>
|
||||
int32_t alt_bn128_pair( const std::vector<std::pair<G1_T, G2_T>>& pairs )
|
||||
```
|
||||
Take a pair of G1 and G2 as input.
|
||||
- `mod_exp`
|
||||
|
||||
- Big integer modular exponentiation returns `( BASE^EXP ) % MOD`
|
||||
```c++
|
||||
int32_t mod_exp( const bigint& base, const bigint& exp, const bigint& mod, bigint& result )
|
||||
```
|
||||
Take bigints as input
|
||||
|
||||
Please take a look into a [crypto_ext.hpp](https://github.com/AntelopeIO/cdt/blob/main/libraries/eosiolib/core/eosio/crypto_ext.hpp)
|
||||
header file, it contains more wrappers and helper functions which may be useful in your code.
|
||||
|
||||
### Examples
|
||||
|
||||
- `alt_bn128_add`
|
||||
```c++
|
||||
std::vector<char> x1, y1, x2, y2;
|
||||
std::vector<char> x1, y1, x2, y2; // Declare coordinates for points on an elliptic curve
|
||||
|
||||
// point
|
||||
// Create the points on the curve
|
||||
eosio::g1_point point1 {x1, y1};
|
||||
eosio::g1_point point2 {x2, y2};
|
||||
// Add two points and get a third point on the curve as result
|
||||
auto result = eosio::alt_bn128_add(point1, point2);
|
||||
|
||||
// view
|
||||
// Do the same addition but with g1_point_view data types
|
||||
eosio::g1_point_view point_view1 {x1.data(), x1.size(), y1.data(), y1.size()};
|
||||
eosio::g1_point_view point_view2 {x2.data(), x2.size(), y2.data(), y2.size()};
|
||||
result = eosio::alt_bn128_add(point_view1, point_view2);
|
||||
@@ -195,32 +132,45 @@ Take bigints as input
|
||||
|
||||
- `alt_bn128_mul`
|
||||
```c++
|
||||
std::vector<char> x, y, scaler;
|
||||
// Declare coordinates for a point on an elliptic curve and a big integer
|
||||
std::vector<char> x, y, scalar;
|
||||
eosio::bigint s {scalar};
|
||||
|
||||
// point
|
||||
// Create the point object with given coordinates
|
||||
eosio::g1_point g1_point {x, y};
|
||||
// Multiply the point with a big integer and get a point on the curve as result
|
||||
auto result = eosio::alt_bn128_mul(g1_point, s);
|
||||
|
||||
// view
|
||||
// Do the same multiplication but with g1_point_view data type
|
||||
eosio::g1_point_view g1_view {x.data(), x.size(), y.data(), y.size()};
|
||||
result = eosio::alt_bn128_mul(g1_view, s);
|
||||
```
|
||||
|
||||
- `alt_bn128_pair`
|
||||
```c++
|
||||
// Declare coordinates for the pairs of points on an elliptic curve
|
||||
std::vector<char> g1_a_x, g1_a_y, g2_a_x, g2_a_y, g1_b_x, g1_b_y, g2_b_x, g2_b_y;
|
||||
|
||||
|
||||
// point
|
||||
// Create the point object by given coordinates
|
||||
// First pair
|
||||
eosio::g1_point g1_a {g1_a_x, g1_a_y};
|
||||
eosio::g2_point g2_a {g2_a_x, g2_a_y};
|
||||
// Second pair
|
||||
eosio::g1_point g1_b {g1_b_x, g1_b_y};
|
||||
eosio::g2_point g2_b {g2_b_x, g2_b_y};
|
||||
|
||||
// Create the pairs object
|
||||
std::vector<std::pair<eosio::g1_point, eosio::g2_point>> pairs { {g1_a, g2_a}, {g1_b, g2_b} };
|
||||
|
||||
// Perform the pairing check
|
||||
// Return:
|
||||
// -1 if there is an error
|
||||
// 1 if the points not in a target group
|
||||
// 0 if the points in a target group
|
||||
auto result = eosio::alt_bn128_pair(pairs);
|
||||
|
||||
// view
|
||||
// Do the same pairing check but with g1_point_view and g2_point_view data types
|
||||
eosio::g1_point_view g1_view_a {g1_a_x.data(), g1_a_x.size(), g1_a_y.data(), g1_a_y.size()};
|
||||
eosio::g2_point_view g2_view_a {g2_a_x.data(), g2_a_x.size(), g2_a_y.data(), g2_a_y.size()};
|
||||
eosio::g1_point_view g1_view_b {g1_b_x.data(), g1_b_x.size(), g1_b_y.data(), g1_b_y.size()};
|
||||
@@ -231,11 +181,14 @@ Take bigints as input
|
||||
|
||||
- `mod_exp`
|
||||
```c++
|
||||
// Declare big integer variables for the base, the exponent and the modulo
|
||||
std::vector<char> base, exp, modulo;
|
||||
eosio::bigint base_val {base};
|
||||
eosio::bigint exp_val {exp};
|
||||
eosio::bigint modulo_val {modulo};
|
||||
// Declare and init a big integer variable for the result of exponentiation
|
||||
eosio::bigint result( modulo.size(), '\0' );
|
||||
|
||||
// Perform the exponentiation
|
||||
// return -1 if there is an error otherwise 0
|
||||
auto rc = eosio::mod_exp(base_val, exp_val, modulo_val, result);
|
||||
```
|
||||
|
||||
@@ -35,7 +35,7 @@ Start with an empty ABI, for exemplification we will work based on the `eosio.to
|
||||
An ABI enables any client or interface to interpret and even generate a GUI for your contract. For this to work consistently, describe the custom types that are used as a parameter in any public action or struct that needs to be described in the ABI.
|
||||
|
||||
[[info | Built-in Types]]
|
||||
| Antelope implements a number of custom built-ins. Built-in types don't need to be described in an ABI file. If you would like to familiarize yourself with Antelope's built-ins, they are defined [here](https://github.com/AntelopeIO/leap/blob/6817911900a088c60f91563995cf482d6b380b2d/libraries/chain/abi_serializer.cpp#L88-L129)
|
||||
| Antelope implements a number of custom built-ins. Built-in types don't need to be described in an ABI file. If you would like to familiarize yourself with Antelope's built-ins, they are defined [here](https://github.com/AntelopeIO/spring/blob/5a3550a6fec4c1865e8aca07aa97693f720afe72/libraries/chain/abi_serializer.cpp#L92-L130)
|
||||
|
||||
|
||||
```json
|
||||
|
||||
@@ -35,7 +35,7 @@ An ABI enables any client or interface to interpret and even generate an GUI for
|
||||
[[info]]
|
||||
|Built-in Types
|
||||
|
||||
Antelope implements a number of custom built-ins. Built-in types don't need to be described in an ABI file. If you would like to familiarize yourself with Antelope's built-ins, they are defined [here](https://github.com/AntelopeIO/leap/blob/6817911900a088c60f91563995cf482d6b380b2d/libraries/chain/abi_serializer.cpp#L88-L129).
|
||||
Antelope implements a number of custom built-ins. Built-in types don't need to be described in an ABI file. If you would like to familiarize yourself with Antelope's built-ins, they are defined [here](https://github.com/AntelopeIO/spring/blob/5a3550a6fec4c1865e8aca07aa97693f720afe72/libraries/chain/abi_serializer.cpp#L92-L130).
|
||||
|
||||
Using **eosio.token** as an example, the only type that requires a description in the ABI file is `account_name`. The ABI uses "new_type_name" to describe explicit types, in this case `account_name`, and `account_name` is an alias of `name` type.
|
||||
|
||||
|
||||
@@ -167,9 +167,9 @@ execution in Antelope block chain virtual machines.
|
||||
|
||||
Compile and link for x86-64
|
||||
|
||||
**`--fno-cfl-aa`**
|
||||
**`--fcfl-aa`**
|
||||
|
||||
Disable CFL Alias Analysis
|
||||
Enable CFL Alias Analysis
|
||||
|
||||
**`--fno-elide-constructors`**
|
||||
|
||||
|
||||
@@ -187,9 +187,9 @@ execution in Antelope block chain virtual machines.
|
||||
|
||||
Compile and link for x86-64
|
||||
|
||||
**`--fno-cfl-aa`**
|
||||
**`--fcfl-aa`**
|
||||
|
||||
Disable CFL Alias Analysis
|
||||
Enable CFL Alias Analysis
|
||||
|
||||
**`--fno-elide-constructors`**
|
||||
|
||||
|
||||
@@ -39,9 +39,9 @@ execution in Antelope block chain virtual machines.
|
||||
|
||||
Compile and link for x86-64
|
||||
|
||||
**`--fno-cfl-aa`**
|
||||
**`--fcfl-aa`**
|
||||
|
||||
Disable CFL Alias Analysis
|
||||
Enable CFL Alias Analysis
|
||||
|
||||
**`--fno-lto`**
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Roadmap for CDT
|
||||
|
||||
## Summary Milestone 5
|
||||
Top priority is clean-up of the code and optimizing for support. Target Date for Milestone 5 is May/June 2024.
|
||||
- Remove AntlerProj repos from build and archive AntlerProj
|
||||
- Move to C++20 - allow contracts to compile C++20
|
||||
- Vanilla Clang/LLVM
|
||||
- Upgrade to LLVM
|
||||
|
||||
|
||||
## Antler
|
||||
We lack the resources to complete the Antler project and support it going forward. Removing dependencies will simplify the build process and simplify things.
|
||||
|
||||
## Move to C++20
|
||||
Allow contracts to compile C++20. In addition to the benefits from the latest language features. Currently, ENF maintains an additional fork of one of our upstream dependencies for EOS EVM simply to get around the fact that the upstream assumes C++20 but we cannot build C++20 code in our contracts.
|
||||
|
||||
## Vanilla Clang/LLVM
|
||||
Try eosio extension free llvm and if it works with no issues then remove extensions to Clang/LLVM. The hope we will enable us to use Vanilla versions of the packages. This will allow us to use the latest, and will lead to improvements in functionality and performance.
|
||||
|
||||
## Upgrade to LLVM 16
|
||||
Upgrade to the latest
|
||||
@@ -4,6 +4,7 @@ file(GLOB HEADERS "*.hpp"
|
||||
add_library(eosio
|
||||
eosiolib.cpp
|
||||
crypto.cpp
|
||||
base64.cpp
|
||||
${HEADERS})
|
||||
|
||||
add_library(eosio_malloc
|
||||
@@ -40,6 +41,7 @@ if (ENABLE_NATIVE_COMPILER)
|
||||
eosiolib.cpp
|
||||
crypto.cpp
|
||||
malloc.cpp
|
||||
base64.cpp
|
||||
${HEADERS})
|
||||
|
||||
add_dependencies( native_eosio eosio )
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
#include "core/eosio/base64.hpp"
|
||||
|
||||
namespace eosio::detail {
|
||||
|
||||
unsigned int pos_of_char(const unsigned char chr, bool url) {
|
||||
// Return the position of chr within base64_encode()
|
||||
constexpr unsigned char from_base64_chars[2][256] = {
|
||||
{ // for base64
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
|
||||
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
|
||||
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
|
||||
},
|
||||
{ // for base64url
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
|
||||
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 63,
|
||||
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
|
||||
}};
|
||||
|
||||
auto c = from_base64_chars[url][chr];
|
||||
eosio::check(c != 64, "encountered non-base64 character");
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len, bool url) {
|
||||
|
||||
const size_t len_encoded = (in_len +2) / 3 * 4;
|
||||
const unsigned char trailing_char = '=';
|
||||
|
||||
// Includes performance improvement from unmerged PR: https://github.com/ReneNyffenegger/cpp-base64/pull/27
|
||||
|
||||
// Depending on the url parameter in base64_chars, one of
|
||||
// two sets of base64 characters needs to be chosen.
|
||||
// They differ in their last two characters.
|
||||
const char* base64_chars[2] = {
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789"
|
||||
"+/",
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789"
|
||||
"-_"};
|
||||
|
||||
// Choose set of base64 characters. They differ
|
||||
// for the last two positions, depending on the url
|
||||
// parameter.
|
||||
// A bool (as is the parameter url) is guaranteed
|
||||
// to evaluate to either 0 or 1 in C++ therefore,
|
||||
// the correct character set is chosen by subscripting
|
||||
// base64_chars with url.
|
||||
const char* base64_chars_ = base64_chars[url];
|
||||
|
||||
std::string ret;
|
||||
ret.reserve(len_encoded);
|
||||
|
||||
unsigned int pos = 0;
|
||||
|
||||
while (pos < in_len) {
|
||||
ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]);
|
||||
|
||||
if (pos+1 < in_len) {
|
||||
ret.push_back(base64_chars_[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]);
|
||||
|
||||
if (pos+2 < in_len) {
|
||||
ret.push_back(base64_chars_[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]);
|
||||
ret.push_back(base64_chars_[ bytes_to_encode[pos + 2] & 0x3f]);
|
||||
}
|
||||
else {
|
||||
ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & 0x0f) << 2]);
|
||||
if (!url) ret.push_back(trailing_char);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0x03) << 4]);
|
||||
if (!url) ret.push_back(trailing_char);
|
||||
if (!url) ret.push_back(trailing_char);
|
||||
}
|
||||
|
||||
pos += 3;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string base64_decode(std::string_view encoded_string, bool remove_linebreaks, bool url) {
|
||||
if (encoded_string.empty()) return std::string{};
|
||||
|
||||
if (remove_linebreaks) {
|
||||
|
||||
std::string copy(encoded_string);
|
||||
|
||||
copy.erase(std::remove(copy.begin(), copy.end(), '\n'), copy.end());
|
||||
|
||||
return base64_decode(copy, false, url);
|
||||
}
|
||||
|
||||
size_t length_of_string = encoded_string.length();
|
||||
size_t pos = 0;
|
||||
|
||||
//
|
||||
// The approximate length (bytes) of the decoded string might be one or
|
||||
// two bytes smaller, depending on the amount of trailing equal signs
|
||||
// in the encoded string. This approximation is needed to reserve
|
||||
// enough space in the string to be returned.
|
||||
//
|
||||
size_t approx_length_of_decoded_string = length_of_string / 4 * 3;
|
||||
std::string ret;
|
||||
ret.reserve(approx_length_of_decoded_string);
|
||||
|
||||
while (pos < length_of_string) {
|
||||
//
|
||||
// Iterate over encoded input string in chunks. The size of all
|
||||
// chunks except the last one is 4 bytes.
|
||||
//
|
||||
// The last chunk might be padded with equal signs or dots
|
||||
// in order to make it 4 bytes in size as well, but this
|
||||
// is not required as per RFC 2045.
|
||||
//
|
||||
// All chunks except the last one produce three output bytes.
|
||||
//
|
||||
// The last chunk produces at least one and up to three bytes.
|
||||
//
|
||||
eosio::check(pos+1 < length_of_string, "wrong encoded string size");
|
||||
size_t pos_of_char_1 = pos_of_char(encoded_string.at(pos+1), url);
|
||||
|
||||
//
|
||||
// Emit the first output byte that is produced in each chunk:
|
||||
//
|
||||
ret.push_back(static_cast<std::string::value_type>( ( (pos_of_char(encoded_string.at(pos+0), url) ) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4)));
|
||||
|
||||
if ( ( pos + 2 < length_of_string ) && // Check for data that is not padded with equal signs (which is allowed by RFC 2045)
|
||||
encoded_string.at(pos+2) != '=' &&
|
||||
encoded_string.at(pos+2) != '.' // accept URL-safe base 64 strings, too, so check for '.' also.
|
||||
)
|
||||
{
|
||||
//
|
||||
// Emit a chunk's second byte (which might not be produced in the last chunk).
|
||||
//
|
||||
unsigned int pos_of_char_2 = pos_of_char(encoded_string.at(pos+2), url);
|
||||
ret.push_back(static_cast<std::string::value_type>( (( pos_of_char_1 & 0x0f) << 4) + (( pos_of_char_2 & 0x3c) >> 2)));
|
||||
|
||||
if ( ( pos + 3 < length_of_string ) &&
|
||||
encoded_string.at(pos+3) != '=' &&
|
||||
encoded_string.at(pos+3) != '.'
|
||||
)
|
||||
{
|
||||
//
|
||||
// Emit a chunk's third byte (which might not be produced in the last chunk).
|
||||
//
|
||||
ret.push_back(static_cast<std::string::value_type>( ( (pos_of_char_2 & 0x03 ) << 6 ) + pos_of_char(encoded_string.at(pos+3), url)));
|
||||
}
|
||||
}
|
||||
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}//eosio::detail
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup call_c Call C API
|
||||
* @ingroup c_api
|
||||
* @brief Defines API for querying call object and making a sync call
|
||||
*/
|
||||
|
||||
/**
|
||||
* Make a sync call in the context of this call's parent action or parent call
|
||||
*
|
||||
* @param receiver - the name of the account that the sync call is made to
|
||||
* @param flags - flags (bits) representing blockchain level requirements about
|
||||
* the call. Currently LSB bit indicates read-only. All other bits
|
||||
* are reserved to be 0
|
||||
* @param data - the data of the sync call, which may include function name, arguments, and other information
|
||||
* @return -1 if the receiver contract does not have sync call entry point or the entry point's signature is invalid, otherwise
|
||||
* @return the number of bytes of the return value of the call. If the function is `void`, return `0`
|
||||
*
|
||||
*/
|
||||
__attribute__((eosio_wasm_import))
|
||||
int64_t call(capi_name receiver, uint64_t flags, const char* data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Copy up to `len` bytes of the return value of the most recent call to `mem`,
|
||||
* in the context of this call's parent action or parent call
|
||||
*
|
||||
* @brief Copy the return value of the most recent call to the specified location
|
||||
* @param mem - a pointer where up to `len` bytes of the return value will be copied
|
||||
* @param len - length of the return value to be copied
|
||||
* @return the number of bytes of the return value that can be retrieved (the number of total bytes of return value)
|
||||
*/
|
||||
__attribute__((eosio_wasm_import))
|
||||
uint32_t get_call_return_value( void* mem, uint32_t len );
|
||||
|
||||
/**
|
||||
* Copy up to `len` bytes of the current call data to `mem`
|
||||
*
|
||||
* @brief Copy current call data to the specified location
|
||||
* @param mem - a pointer where up to `len` bytes of the current call data will be copied
|
||||
* @param len - length of the current call data to be copied
|
||||
* @return the number of bytes of the data that can be retrieved (the number of total bytes of the data)
|
||||
*/
|
||||
__attribute__((eosio_wasm_import))
|
||||
uint32_t get_call_data( void* mem, uint32_t len );
|
||||
|
||||
/**
|
||||
* Set the return value from `mem` with `len` bytes. This is to be retrieved by parent action
|
||||
* or parent call using `get_call_return_value`
|
||||
*
|
||||
* @brief Copy the return value from the specified location
|
||||
* @param mem - a pointer where `len` bytes of the return value will be copied from
|
||||
*/
|
||||
__attribute__((eosio_wasm_import))
|
||||
void set_call_return_value( void* mem, uint32_t len );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/// @} call
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_g1_add(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_g2_add(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_g1_weighted_sum(const char* points, uint32_t points_len, const char* scalars, uint32_t scalars_len, uint32_t n, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_g2_weighted_sum(const char* points, uint32_t points_len, const char* scalars, uint32_t scalars_len, uint32_t n, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_pairing(const char* g1_points, uint32_t g1_points_len, const char* g2_points, uint32_t g2_points_len, uint32_t n, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_g1_map(const char* e, uint32_t e_len, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_g2_map(const char* e, uint32_t e_len, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_fp_mod(const char* s, uint32_t s_len, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_fp_mul(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_fp_exp(const char* base, uint32_t base_len, const char* exp, uint32_t exp_len, char* res, uint32_t res_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup instant_finality_c Instant_finality C API
|
||||
* @ingroup c_api
|
||||
* @brief Defines %C Instant_finality API
|
||||
*/
|
||||
|
||||
/**
|
||||
* Submits a finalizer policy change to Instant Finality
|
||||
*
|
||||
* @param packed_finalizer_format - format of the finalizer_policy object, currently only supports 0
|
||||
* @param data - pointer finalizer_policy object packed as bytes
|
||||
* @param len - size of packed finalazer_policy object
|
||||
* @pre `data` is a valid pointer to a range of memory at least `len` bytes long that contains packed abi_finalizer_policy data
|
||||
* abi_finalizer_policy structure is defined in instant_finality.hpp
|
||||
*/
|
||||
__attribute__((eosio_wasm_import))
|
||||
void set_finalizers( uint64_t packed_finalizer_format, const char* data, uint32_t len );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,56 +0,0 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Propose new participants to the security group.
|
||||
*
|
||||
* @param data - the buffer containing the packed participants.
|
||||
* @param datalen - size of the packed participants
|
||||
* @pre `data` is a valid pointer to a range of memory at least `datalen` bytes long that contains packed participants data
|
||||
*
|
||||
* @return -1 if proposing a new security group was unsuccessful, otherwise returns 0.
|
||||
*/
|
||||
__attribute__((eosio_wasm_import))
|
||||
int64_t add_security_group_participants(const char* data, uint32_t datalen);
|
||||
|
||||
/**
|
||||
* Propose to remove participants from the security group.
|
||||
*
|
||||
* @param data - the buffer containing the packed participants.
|
||||
* @param datalen - size of the packed participants
|
||||
* @pre `data` is a valid pointer to a range of memory at least `datalen` bytes long that contains packed participants data
|
||||
*
|
||||
* @return -1 if proposing a new security group was unsuccessful, otherwise returns 0.
|
||||
*/
|
||||
__attribute__((eosio_wasm_import))
|
||||
int64_t remove_security_group_participants(const char* data, uint32_t datalen);
|
||||
|
||||
/**
|
||||
* Check if the specified accounts are all in the active security group.
|
||||
*
|
||||
* @param data - the buffer containing the packed participants.
|
||||
* @param datalen - size of the packed participants
|
||||
*
|
||||
* @return Returns true if the specified accounts are all in the active security group.
|
||||
*/
|
||||
__attribute__((eosio_wasm_import))
|
||||
bool in_active_security_group(const char* data, uint32_t datalen);
|
||||
|
||||
/**
|
||||
* Gets the active security group
|
||||
*
|
||||
* @param[out] data - the output buffer containing the packed security group.
|
||||
* @param datalen - size of the `data` buffer
|
||||
*
|
||||
* @return Returns the size required in the buffer (if the buffer is too small, nothing is written).
|
||||
*
|
||||
*/
|
||||
__attribute__((eosio_wasm_import))
|
||||
uint32_t get_active_security_group(char* data, uint32_t datalen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -6,11 +6,11 @@
|
||||
#include <cstdlib>
|
||||
#include <type_traits>
|
||||
|
||||
#include "detail.hpp"
|
||||
#include "../../core/eosio/serialize.hpp"
|
||||
#include "../../core/eosio/datastream.hpp"
|
||||
#include "../../core/eosio/name.hpp"
|
||||
#include "../../core/eosio/fixed_bytes.hpp"
|
||||
#include "../../core/eosio/ignore.hpp"
|
||||
#include "../../core/eosio/time.hpp"
|
||||
|
||||
namespace eosio {
|
||||
@@ -409,84 +409,6 @@ namespace eosio {
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
/// @cond INTERNAL
|
||||
|
||||
template <typename T>
|
||||
struct unwrap { typedef T type; };
|
||||
|
||||
template <typename T>
|
||||
struct unwrap<ignore<T>> { typedef T type; };
|
||||
|
||||
template <typename R, typename Act, typename... Args>
|
||||
auto get_args(R(Act::*p)(Args...)) {
|
||||
return std::tuple<std::decay_t<typename unwrap<Args>::type>...>{};
|
||||
}
|
||||
|
||||
template <typename R, typename Act, typename... Args>
|
||||
auto get_args_nounwrap(R(Act::*p)(Args...)) {
|
||||
return std::tuple<std::decay_t<Args>...>{};
|
||||
}
|
||||
|
||||
template <auto Action>
|
||||
using deduced = decltype(get_args(Action));
|
||||
|
||||
template <auto Action>
|
||||
using deduced_nounwrap = decltype(get_args_nounwrap(Action));
|
||||
|
||||
template <typename T>
|
||||
struct convert { typedef T type; };
|
||||
|
||||
template <>
|
||||
struct convert<const char*> { typedef std::string type; };
|
||||
|
||||
template <>
|
||||
struct convert<char*> { typedef std::string type; };
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_same { static constexpr bool value = std::is_convertible<T,U>::value; };
|
||||
|
||||
template <typename U>
|
||||
struct is_same<bool,U> { static constexpr bool value = std::is_integral<U>::value; };
|
||||
|
||||
template <typename T>
|
||||
struct is_same<T,bool> { static constexpr bool value = std::is_integral<T>::value; };
|
||||
|
||||
template <size_t N, size_t I, auto Arg, auto... Args>
|
||||
struct get_nth_impl { static constexpr auto value = get_nth_impl<N,I+1,Args...>::value; };
|
||||
|
||||
template <size_t N, auto Arg, auto... Args>
|
||||
struct get_nth_impl<N, N, Arg, Args...> { static constexpr auto value = Arg; };
|
||||
|
||||
template <size_t N, auto... Args>
|
||||
struct get_nth { static constexpr auto value = get_nth_impl<N,0,Args...>::value; };
|
||||
|
||||
template <auto Action, size_t I, typename T, typename... Rest>
|
||||
struct check_types {
|
||||
static_assert(detail::is_same<typename convert<T>::type, typename convert<typename std::tuple_element<I, deduced<Action>>::type>::type>::value);
|
||||
using type = check_types<Action, I+1, Rest...>;
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
template <auto Action, size_t I, typename T>
|
||||
struct check_types<Action, I, T> {
|
||||
static_assert(detail::is_same<typename convert<T>::type, typename convert<typename std::tuple_element<I, deduced<Action>>::type>::type>::value);
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template <auto Action, typename... Ts>
|
||||
constexpr bool type_check() {
|
||||
static_assert(sizeof...(Ts) == std::tuple_size<deduced<Action>>::value);
|
||||
if constexpr (sizeof...(Ts) != 0)
|
||||
return check_types<Action, 0, Ts...>::value;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for an action object.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* @file
|
||||
*/
|
||||
#pragma once
|
||||
#include <cstdlib>
|
||||
#include <type_traits>
|
||||
|
||||
#include "detail.hpp"
|
||||
#include "../../core/eosio/serialize.hpp"
|
||||
#include "../../core/eosio/datastream.hpp"
|
||||
#include "../../core/eosio/name.hpp"
|
||||
#include "../../core/eosio/hash_id.hpp"
|
||||
|
||||
namespace eosio {
|
||||
|
||||
namespace internal_use_do_not_use {
|
||||
extern "C" {
|
||||
__attribute__((eosio_wasm_import))
|
||||
int64_t call(uint64_t receiver, uint64_t flags, const char* data, size_t data_size);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
uint32_t get_call_return_value( void* mem, uint32_t len );
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
uint32_t get_call_data( void* mem, uint32_t len );
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
void set_call_return_value( void* mem, uint32_t len );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @defgroup call call
|
||||
* @ingroup contracts
|
||||
* @brief Defines type-safe C++ wrappers for querying call and sending call
|
||||
* @note There are some methods from the @ref call that can be used directly from C++
|
||||
*/
|
||||
|
||||
inline int64_t call(eosio::name receiver, uint64_t flags, const char* data, size_t data_size) {
|
||||
return internal_use_do_not_use::call(receiver.value, flags, data, data_size);
|
||||
}
|
||||
|
||||
inline uint32_t get_call_return_value( void* mem, uint32_t len ) {
|
||||
return internal_use_do_not_use::get_call_return_value(mem, len);
|
||||
}
|
||||
|
||||
inline uint32_t get_call_data( void* mem, uint32_t len ) {
|
||||
return internal_use_do_not_use::get_call_data(mem, len);
|
||||
}
|
||||
|
||||
inline void set_call_return_value( void* mem, uint32_t len ) {
|
||||
internal_use_do_not_use::set_call_return_value(mem, len);
|
||||
}
|
||||
|
||||
// Indicate whether a sync call is read_write or read_only. Default is read_write
|
||||
enum class access_mode { read_write = 0, read_only = 1 };
|
||||
|
||||
// Indicate the action to take if the receiver does not support sync calls.
|
||||
// Default is abort_op
|
||||
enum class support_mode { abort_op = 0, no_op = 1 };
|
||||
|
||||
// For a void function, when support_mode is set to no_op, the call_wrapper.
|
||||
// returns `std::optional<void_call>`. If the optional has no value, it indicates
|
||||
// the call was op-op; if the optional has a value of `void_call`, the call
|
||||
// executed successfully.
|
||||
struct void_call {
|
||||
};
|
||||
|
||||
struct call_data_header {
|
||||
uint32_t version = 0;
|
||||
uint64_t func_name = 0; // At WASM level, function name is a short ID of uint64_t.
|
||||
|
||||
EOSLIB_SERIALIZE(call_data_header, (version)(func_name))
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper for simplifying making a sync call
|
||||
*
|
||||
* @brief Used to wrap a particular sync call to simplify the process of other contracts making sync calls to the "wrapped" call.
|
||||
* Example:
|
||||
* @code
|
||||
* // defined by contract writer of the sync call functions
|
||||
* using get_func = call_wrapper<"get"_i, &callee::get>;
|
||||
* // usage by different contract writer
|
||||
* get_func{"callee"_n}();
|
||||
* // or
|
||||
* get_func get{"callee"_n};
|
||||
* get();
|
||||
* @endcode
|
||||
*/
|
||||
template <eosio::hash_id::raw Func_Name, auto Func_Ref, access_mode Access_Mode=access_mode::read_write, support_mode Support_Mode = support_mode::abort_op>
|
||||
struct call_wrapper {
|
||||
template <typename Receiver>
|
||||
constexpr call_wrapper(Receiver&& receiver)
|
||||
: receiver(std::forward<Receiver>(receiver))
|
||||
{}
|
||||
|
||||
static constexpr eosio::hash_id function_name = eosio::hash_id(Func_Name);
|
||||
eosio::name receiver {};
|
||||
|
||||
using orig_ret_type = typename detail::function_traits<decltype(Func_Ref)>::return_type;
|
||||
|
||||
using return_type = std::conditional_t<
|
||||
Support_Mode == support_mode::abort_op,// if Support_Mode is abort_op
|
||||
orig_ret_type, // use the original return type
|
||||
std::conditional_t< // else
|
||||
std::is_void<orig_ret_type>::value, // original return type is void
|
||||
std::optional<void_call>, // use optional of empty struct
|
||||
std::optional<orig_ret_type> // use optional of original return type
|
||||
>
|
||||
>;
|
||||
|
||||
template <typename... Args>
|
||||
return_type operator()(Args&&... args)const {
|
||||
static_assert(detail::type_check<Func_Ref, Args...>());
|
||||
|
||||
uint64_t flags = 0x00;
|
||||
if constexpr (Access_Mode == access_mode::read_only) {
|
||||
flags = 0x01;
|
||||
}
|
||||
|
||||
call_data_header header{ .version = 0,
|
||||
.func_name = function_name.id };
|
||||
|
||||
const std::vector<char> data{ pack(std::forward_as_tuple(header, detail::deduced<Func_Ref>{std::forward<Args>(args)...})) };
|
||||
|
||||
auto ret_val_size = internal_use_do_not_use::call(receiver.value, flags, data.data(), data.size());
|
||||
|
||||
if (ret_val_size < 0) { // the receiver does not support sync calls
|
||||
if constexpr (Support_Mode == support_mode::abort_op) {
|
||||
check(false, "receiver does not support sync call but support_mode is set to abort_op");
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
// The sync call has been executed by the receiver
|
||||
if constexpr (std::is_void<return_type>::value) {
|
||||
return;
|
||||
} else {
|
||||
if constexpr (Support_Mode == support_mode::no_op && std::is_void<orig_ret_type>::value) {
|
||||
return void_call{};
|
||||
} else {
|
||||
constexpr size_t max_stack_buffer_size = 512;
|
||||
char* buffer = (char*)(max_stack_buffer_size < ret_val_size ? malloc(ret_val_size) : alloca(ret_val_size)); // intentionally no `free()` is called. the memory will be freed at the end of callers wasm execution.
|
||||
internal_use_do_not_use::get_call_return_value(buffer, ret_val_size);
|
||||
orig_ret_type ret_val = unpack<orig_ret_type>(buffer, ret_val_size);
|
||||
|
||||
if constexpr (Support_Mode == support_mode::no_op) {
|
||||
return std::make_optional(ret_val);
|
||||
} else {
|
||||
return ret_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace eosio
|
||||
@@ -29,6 +29,12 @@ namespace eosio {
|
||||
*/
|
||||
class contract {
|
||||
public:
|
||||
enum class exec_type_t : uint8_t {
|
||||
action,
|
||||
call,
|
||||
unknown
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct a new contract given the contract name
|
||||
*
|
||||
@@ -75,7 +81,27 @@ class contract {
|
||||
*/
|
||||
inline const datastream<const char*>& get_datastream()const { return _ds; }
|
||||
|
||||
/**
|
||||
* Whether this contract is for a sync call
|
||||
*
|
||||
* @return bool - Whether this contract is for a sync call
|
||||
*/
|
||||
inline bool is_sync_call()const {
|
||||
check(_exec_type != exec_type_t::unknown, "too early to call is_sync_call(). _exec_type has not been set yet");
|
||||
return (_exec_type == exec_type_t::call);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the exectution type.
|
||||
*
|
||||
* @param type - The exectution type to be set.
|
||||
*/
|
||||
inline void set_exec_type(exec_type_t type) {
|
||||
_exec_type = type;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* The name of the account this contract is deployed on.
|
||||
*/
|
||||
@@ -90,5 +116,10 @@ class contract {
|
||||
* The datastream for this contract
|
||||
*/
|
||||
datastream<const char*> _ds = datastream<const char*>(nullptr, 0);
|
||||
|
||||
/**
|
||||
* The execution type: action or sync call
|
||||
*/
|
||||
exec_type_t _exec_type = exec_type_t::unknown;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright defined in eos/LICENSE
|
||||
*/
|
||||
#pragma once
|
||||
#include "system.hpp"
|
||||
#include "transaction.hpp"
|
||||
#include "../../core/eosio/serialize.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace eosio {
|
||||
namespace internal_use_do_not_use {
|
||||
extern "C" {
|
||||
__attribute__((eosio_wasm_import))
|
||||
void send_deferred(const uint128_t&, uint64_t, const char*, size_t, uint32_t);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int cancel_deferred(const uint128_t&);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @defgroup deferred_transaction Transaction
|
||||
* @ingroup contracts
|
||||
* @brief Type-safe C++ wrappers for transaction C API
|
||||
*
|
||||
* deferred_transaction is no longer supported on Vaulta. This class is provided to
|
||||
* support legacy test contracts that use deferred transactions.
|
||||
*
|
||||
* @details An inline message allows one contract to send another contract a message
|
||||
* which is processed immediately after the current message's processing
|
||||
* ends such that the success or failure of the parent transaction is
|
||||
* dependent on the success of the message. If an inline message fails in
|
||||
* processing then the whole tree of transactions and actions rooted in the
|
||||
* block will me marked as failing and none of effects on the database will
|
||||
* persist.
|
||||
*
|
||||
* Inline actions and Deferred transactions must adhere to the permissions
|
||||
* available to the parent transaction or, in the future, delegated to the
|
||||
* contract account for future use.
|
||||
*
|
||||
* @note There are some methods from the @ref transactioncapi that can be used directly from C++
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class transaction contains the actions, context_free_actions and extensions type for a transaction
|
||||
*
|
||||
* @ingroup transaction
|
||||
*/
|
||||
class deferred_transaction : public transaction {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct a new deferred_transaction with an expiration of now + 60 seconds.
|
||||
*/
|
||||
deferred_transaction(time_point_sec exp = time_point_sec(current_time_point()) + 60) : transaction( exp ) {}
|
||||
|
||||
/**
|
||||
* Sends this transaction, packs the transaction then sends it as a deferred transaction
|
||||
*
|
||||
* @details Writes the symbol_code as a string to the provided char buffer
|
||||
* @param sender_id - ID of sender
|
||||
* @param payer - Account paying for RAM
|
||||
* @param replace_existing - Defaults to false, if this is `0`/false then if the provided sender_id is already in use by an in-flight transaction from this contract, which will be a failing assert. If `1` then transaction will atomically cancel/replace the inflight transaction
|
||||
*/
|
||||
void send(const uint128_t& sender_id, name payer, bool replace_existing = false) const {
|
||||
auto serialize = pack(*static_cast<const transaction*>(this));
|
||||
internal_use_do_not_use::send_deferred(sender_id, payer.value, serialize.data(), serialize.size(), replace_existing);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct onerror contains and sender id and packed transaction
|
||||
*
|
||||
* @ingroup transaction
|
||||
*/
|
||||
struct onerror {
|
||||
uint128_t sender_id;
|
||||
std::vector<char> sent_trx;
|
||||
|
||||
/**
|
||||
* from_current_action unpacks and returns a onerror struct
|
||||
*
|
||||
* @ingroup transaction
|
||||
*/
|
||||
static onerror from_current_action() {
|
||||
return unpack_action_data<onerror>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpacks and returns a transaction
|
||||
*/
|
||||
transaction unpack_sent_trx() const {
|
||||
return unpack<transaction>(sent_trx);
|
||||
}
|
||||
|
||||
EOSLIB_SERIALIZE( onerror, (sender_id)(sent_trx) )
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a deferred transaction
|
||||
*
|
||||
* @ingroup transaction
|
||||
* @param sender_id - Account name of the sender of this deferred transaction
|
||||
* @param payer - Account name responsible for paying the RAM for this deferred transaction
|
||||
* @param serialized_transaction - The packed transaction to be deferred
|
||||
* @param size - The size of the packed transaction, required for persistence.
|
||||
* @param replace - If true, will replace an existing transaction.
|
||||
*/
|
||||
inline void send_deferred(const uint128_t& sender_id, name payer, const char* serialized_transaction, size_t size, bool replace = false) {
|
||||
internal_use_do_not_use::send_deferred(sender_id, payer.value, serialized_transaction, size, replace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a deferred transaction.
|
||||
*
|
||||
* @ingroup transaction
|
||||
* @param sender_id - The id of the sender
|
||||
*
|
||||
* @pre The deferred transaction ID exists.
|
||||
* @pre The deferred transaction ID has not yet been published.
|
||||
* @post Deferred transaction canceled.
|
||||
*
|
||||
* @return 1 if transaction was canceled, 0 if transaction was not found
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @code
|
||||
* id = 0xffffffffffffffff
|
||||
* cancel_deferred( id );
|
||||
* @endcode
|
||||
*/
|
||||
inline int cancel_deferred(const uint128_t& sender_id) {
|
||||
return internal_use_do_not_use::cancel_deferred(sender_id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../core/eosio/ignore.hpp"
|
||||
|
||||
namespace eosio { namespace detail {
|
||||
|
||||
/// @cond INTERNAL
|
||||
|
||||
template <typename T>
|
||||
struct unwrap { typedef T type; };
|
||||
|
||||
template <typename T>
|
||||
struct unwrap<ignore<T>> { typedef T type; };
|
||||
|
||||
template <typename R, typename Act, typename... Args>
|
||||
auto get_args(R(Act::*p)(Args...)) {
|
||||
return std::tuple<std::decay_t<typename unwrap<Args>::type>...>{};
|
||||
}
|
||||
|
||||
template <typename R, typename Act, typename... Args>
|
||||
auto get_args_nounwrap(R(Act::*p)(Args...)) {
|
||||
return std::tuple<std::decay_t<Args>...>{};
|
||||
}
|
||||
|
||||
template <auto Function>
|
||||
using deduced = decltype(get_args(Function));
|
||||
|
||||
template <auto Function>
|
||||
using deduced_nounwrap = decltype(get_args_nounwrap(Function));
|
||||
|
||||
template <typename T>
|
||||
struct convert { typedef T type; };
|
||||
|
||||
template <>
|
||||
struct convert<const char*> { typedef std::string type; };
|
||||
|
||||
template <>
|
||||
struct convert<char*> { typedef std::string type; };
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_same { static constexpr bool value = std::is_convertible<T,U>::value; };
|
||||
|
||||
template <typename U>
|
||||
struct is_same<bool,U> { static constexpr bool value = std::is_integral<U>::value; };
|
||||
|
||||
template <typename T>
|
||||
struct is_same<T,bool> { static constexpr bool value = std::is_integral<T>::value; };
|
||||
|
||||
// Full specialization to resolve ambiguity introduced by partial specializations
|
||||
// of is_same<bool,U> and is_same<T,bool>
|
||||
template <>
|
||||
struct is_same<bool, bool> { static constexpr bool value = true; };
|
||||
|
||||
template <size_t N, size_t I, auto Arg, auto... Args>
|
||||
struct get_nth_impl { static constexpr auto value = get_nth_impl<N,I+1,Args...>::value; };
|
||||
|
||||
template <size_t N, auto Arg, auto... Args>
|
||||
struct get_nth_impl<N, N, Arg, Args...> { static constexpr auto value = Arg; };
|
||||
|
||||
template <size_t N, auto... Args>
|
||||
struct get_nth { static constexpr auto value = get_nth_impl<N,0,Args...>::value; };
|
||||
|
||||
template <auto Function, size_t I, typename T, typename... Rest>
|
||||
struct check_types {
|
||||
static_assert(detail::is_same<typename convert<T>::type, typename convert<typename std::tuple_element<I, deduced<Function>>::type>::type>::value);
|
||||
using type = check_types<Function, I+1, Rest...>;
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
template <auto Function, size_t I, typename T>
|
||||
struct check_types<Function, I, T> {
|
||||
static_assert(detail::is_same<typename convert<T>::type, typename convert<typename std::tuple_element<I, deduced<Function>>::type>::type>::value);
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template <auto Function, typename... Ts>
|
||||
constexpr bool type_check() {
|
||||
static_assert(sizeof...(Ts) == std::tuple_size<deduced<Function>>::value);
|
||||
if constexpr (sizeof...(Ts) != 0)
|
||||
return check_types<Function, 0, Ts...>::value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// For non-function-pointers (function_traits is undefined)
|
||||
template <typename T>
|
||||
struct function_traits;
|
||||
|
||||
// For non-const member function
|
||||
template <typename Class, typename Ret, typename... Args>
|
||||
struct function_traits<Ret (Class::*)(Args...)> {
|
||||
using return_type = Ret;
|
||||
};
|
||||
|
||||
// For const member function
|
||||
template <typename Class, typename Ret, typename... Args>
|
||||
struct function_traits<Ret (Class::*)(Args...) const> {
|
||||
using return_type = Ret;
|
||||
};
|
||||
/// @endcond
|
||||
}} // eosio detail
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../capi/eosio/types.h"
|
||||
#include "../../core/eosio/crypto_bls_ext.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @defgroup instant_finality Instant_finality
|
||||
* @ingroup instant_finality
|
||||
* @ingroup contracts
|
||||
* @brief Defines C++ Instant Finality API
|
||||
*/
|
||||
|
||||
namespace eosio {
|
||||
namespace internal_use_do_not_use {
|
||||
extern "C" {
|
||||
__attribute__((eosio_wasm_import))
|
||||
void set_finalizers( uint64_t packed_finalizer_format, const char* data, uint32_t len );
|
||||
} // extern "C"
|
||||
} //internal_use_do_not_use
|
||||
|
||||
struct finalizer_authority {
|
||||
std::string description;
|
||||
uint64_t weight = 0; // weight that this finalizer's vote has for meeting threshold
|
||||
std::vector<char> public_key; // Affine little endian non-montgomery g1
|
||||
|
||||
EOSLIB_SERIALIZE(finalizer_authority, (description)(weight)(public_key));
|
||||
};
|
||||
struct finalizer_policy {
|
||||
uint64_t threshold = 0;
|
||||
std::vector<finalizer_authority> finalizers;
|
||||
|
||||
EOSLIB_SERIALIZE(finalizer_policy, (threshold)(finalizers));
|
||||
};
|
||||
|
||||
/**
|
||||
* Submits a finalizer policy change to Instant Finality
|
||||
*
|
||||
* @param finalizer_policy - finalizer policy to be set
|
||||
*/
|
||||
inline void set_finalizers( const finalizer_policy& finalizer_policy ) {
|
||||
for (const auto& finalizer : finalizer_policy.finalizers)
|
||||
eosio::check(finalizer.public_key.size() == sizeof(bls_g1), "public key has a wrong size" );
|
||||
auto packed = eosio::pack(finalizer_policy);
|
||||
// 0 is packed format, currently only 0 is supported
|
||||
internal_use_do_not_use::set_finalizers(0, packed.data(), packed.size());
|
||||
}
|
||||
|
||||
} //eosio
|
||||
@@ -1,86 +0,0 @@
|
||||
#pragma once
|
||||
#include <set>
|
||||
#include "../../core/eosio/name.hpp"
|
||||
#include "../../core/eosio/serialize.hpp"
|
||||
|
||||
namespace eosio {
|
||||
|
||||
namespace internal_use_do_not_use {
|
||||
extern "C" {
|
||||
__attribute__((eosio_wasm_import)) int64_t add_security_group_participants(const char* data, uint32_t datalen);
|
||||
|
||||
__attribute__((eosio_wasm_import)) int64_t remove_security_group_participants(const char* data, uint32_t datalen);
|
||||
|
||||
__attribute__((eosio_wasm_import)) bool in_active_security_group(const char* data, uint32_t datalen);
|
||||
|
||||
__attribute__((eosio_wasm_import)) uint32_t get_active_security_group(char* data, uint32_t datalen);
|
||||
}
|
||||
} // namespace internal_use_do_not_use
|
||||
|
||||
/**
|
||||
* @defgroup security_group Security Group
|
||||
* @ingroup contracts
|
||||
* @brief Defines C++ security group API
|
||||
*/
|
||||
|
||||
struct security_group {
|
||||
uint32_t version;
|
||||
std::set<name> participants;
|
||||
CDT_REFLECT(version, participants);
|
||||
};
|
||||
|
||||
/**
|
||||
* Propose new participants to the security group.
|
||||
*
|
||||
* @ingroup security_group
|
||||
* @param participants - the participants.
|
||||
*
|
||||
* @return -1 if proposing a new security group was unsuccessful, otherwise returns 0.
|
||||
*/
|
||||
inline int64_t add_security_group_participants(const std::set<name>& participants) {
|
||||
auto packed_participants = eosio::pack( participants );
|
||||
return internal_use_do_not_use::add_security_group_participants( packed_participants.data(), packed_participants.size() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Propose to remove participants from the security group.
|
||||
*å
|
||||
* @ingroup security_group
|
||||
* @param participants - the participants.
|
||||
*å
|
||||
* @return -1 if proposing a new security group was unsuccessful, otherwise returns 0.
|
||||
*/
|
||||
inline int64_t remove_security_group_participants(const std::set<name>& participants){
|
||||
auto packed_participants = eosio::pack( participants );
|
||||
return internal_use_do_not_use::remove_security_group_participants( packed_participants.data(), packed_participants.size() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the specified accounts are all in the active security group.
|
||||
*
|
||||
* @ingroup security_group
|
||||
* @param participants - the participants.
|
||||
*
|
||||
* @return Returns true if the specified accounts are all in the active security group.
|
||||
*/
|
||||
inline bool in_active_security_group(const std::set<name>& participants){
|
||||
auto packed_participants = eosio::pack( participants );
|
||||
return internal_use_do_not_use::in_active_security_group( packed_participants.data(), packed_participants.size() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the active security group
|
||||
*
|
||||
* @ingroup security_group
|
||||
* @param[out] packed_security_group - the buffer containing the packed security_group.
|
||||
*
|
||||
* @return Returns the size required in the buffer (if the buffer is too small, nothing is written).
|
||||
*
|
||||
*/
|
||||
inline security_group get_active_security_group() {
|
||||
size_t buffer_size = internal_use_do_not_use::get_active_security_group(0, 0);
|
||||
std::vector<char> buffer(buffer_size);
|
||||
internal_use_do_not_use::get_active_security_group(buffer.data(), buffer_size);
|
||||
return eosio::unpack<security_group>(buffer);
|
||||
}
|
||||
} // namespace eosio
|
||||
@@ -62,7 +62,7 @@ namespace eosio {
|
||||
* @return true - if exists
|
||||
* @return false - otherwise
|
||||
*/
|
||||
bool exists() {
|
||||
bool exists() const {
|
||||
return _t.find( pk_value ) != _t.end();
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace eosio {
|
||||
* @brief Get the value stored inside the singleton table
|
||||
* @return T - The value stored
|
||||
*/
|
||||
T get() {
|
||||
T get() const {
|
||||
auto itr = _t.find( pk_value );
|
||||
eosio::check( itr != _t.end(), "singleton does not exist" );
|
||||
return itr->value;
|
||||
@@ -84,7 +84,7 @@ namespace eosio {
|
||||
* @param def - The default value to be returned in case the data doesn't exist
|
||||
* @return T - The value stored
|
||||
*/
|
||||
T get_or_default( const T& def = T() ) {
|
||||
T get_or_default( const T& def = T() ) const {
|
||||
auto itr = _t.find( pk_value );
|
||||
return itr != _t.end() ? itr->value : def;
|
||||
}
|
||||
|
||||
@@ -13,12 +13,6 @@
|
||||
namespace eosio {
|
||||
namespace internal_use_do_not_use {
|
||||
extern "C" {
|
||||
__attribute__((eosio_wasm_import))
|
||||
void send_deferred(const uint128_t&, uint64_t, const char*, size_t, uint32_t);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int cancel_deferred(const uint128_t&);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
size_t read_transaction(char*, size_t);
|
||||
|
||||
@@ -47,17 +41,7 @@ namespace eosio {
|
||||
* @ingroup contracts
|
||||
* @brief Type-safe C++ wrappers for transaction C API
|
||||
*
|
||||
* @details An inline message allows one contract to send another contract a message
|
||||
* which is processed immediately after the current message's processing
|
||||
* ends such that the success or failure of the parent transaction is
|
||||
* dependent on the success of the message. If an inline message fails in
|
||||
* processing then the whole tree of transactions and actions rooted in the
|
||||
* block will me marked as failing and none of effects on the database will
|
||||
* persist.
|
||||
*
|
||||
* Inline actions and Deferred transactions must adhere to the permissions
|
||||
* available to the parent transaction or, in the future, delegated to the
|
||||
* contract account for future use.
|
||||
* @details See action for the ability to send an inline action.
|
||||
*
|
||||
* @note There are some methods from the @ref transactioncapi that can be used directly from C++
|
||||
*/
|
||||
@@ -83,17 +67,17 @@ namespace eosio {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct a new transaction_header with an expiration of now + 60 seconds.
|
||||
* Construct a new transaction_header
|
||||
*
|
||||
* @brief Construct a new transaction_header object initialising the transaction header expiration to now + 60 seconds
|
||||
* @brief Construct a new transaction_header object
|
||||
*/
|
||||
transaction_header( time_point_sec exp = time_point_sec(current_time_point()) + 60)
|
||||
transaction_header( time_point_sec exp = time_point_sec{} )
|
||||
:expiration(exp)
|
||||
{}
|
||||
|
||||
time_point_sec expiration;
|
||||
uint16_t ref_block_num;
|
||||
uint32_t ref_block_prefix;
|
||||
uint16_t ref_block_num = 0UL;
|
||||
uint32_t ref_block_prefix = 0UL;
|
||||
unsigned_int max_net_usage_words = 0UL; /// number of 8 byte words this transaction can serialize into after compressions
|
||||
uint8_t max_cpu_usage_ms = 0UL; /// number of CPU usage units to bill transaction for
|
||||
unsigned_int delay_sec = 0UL; /// number of seconds to delay transaction, default: 0
|
||||
@@ -110,22 +94,9 @@ namespace eosio {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct a new transaction with an expiration of now + 60 seconds.
|
||||
* Construct a new transaction
|
||||
*/
|
||||
transaction(time_point_sec exp = time_point_sec(current_time_point()) + 60) : transaction_header( exp ) {}
|
||||
|
||||
/**
|
||||
* Sends this transaction, packs the transaction then sends it as a deferred transaction
|
||||
*
|
||||
* @details Writes the symbol_code as a string to the provided char buffer
|
||||
* @param sender_id - ID of sender
|
||||
* @param payer - Account paying for RAM
|
||||
* @param replace_existing - Defaults to false, if this is `0`/false then if the provided sender_id is already in use by an in-flight transaction from this contract, which will be a failing assert. If `1` then transaction will atomically cancel/replace the inflight transaction
|
||||
*/
|
||||
void send(const uint128_t& sender_id, name payer, bool replace_existing = false) const {
|
||||
auto serialize = pack(*this);
|
||||
internal_use_do_not_use::send_deferred(sender_id, payer.value, serialize.data(), serialize.size(), replace_existing);
|
||||
}
|
||||
transaction(time_point_sec exp = time_point_sec{}) : transaction_header( exp ) {}
|
||||
|
||||
std::vector<action> context_free_actions;
|
||||
std::vector<action> actions;
|
||||
@@ -134,47 +105,6 @@ namespace eosio {
|
||||
EOSLIB_SERIALIZE_DERIVED( transaction, transaction_header, (context_free_actions)(actions)(transaction_extensions) )
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct onerror contains and sender id and packed transaction
|
||||
*
|
||||
* @ingroup transaction
|
||||
*/
|
||||
struct onerror {
|
||||
uint128_t sender_id;
|
||||
std::vector<char> sent_trx;
|
||||
|
||||
/**
|
||||
* from_current_action unpacks and returns a onerror struct
|
||||
*
|
||||
* @ingroup transaction
|
||||
*/
|
||||
static onerror from_current_action() {
|
||||
return unpack_action_data<onerror>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpacks and returns a transaction
|
||||
*/
|
||||
transaction unpack_sent_trx() const {
|
||||
return unpack<transaction>(sent_trx);
|
||||
}
|
||||
|
||||
EOSLIB_SERIALIZE( onerror, (sender_id)(sent_trx) )
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a deferred transaction
|
||||
*
|
||||
* @ingroup transaction
|
||||
* @param sender_id - Account name of the sender of this deferred transaction
|
||||
* @param payer - Account name responsible for paying the RAM for this deferred transaction
|
||||
* @param serialized_transaction - The packed transaction to be deferred
|
||||
* @param size - The size of the packed transaction, required for persistence.
|
||||
* @param replace - If true, will replace an existing transaction.
|
||||
*/
|
||||
inline void send_deferred(const uint128_t& sender_id, name payer, const char* serialized_transaction, size_t size, bool replace = false) {
|
||||
internal_use_do_not_use::send_deferred(sender_id, payer.value, serialized_transaction, size, replace);
|
||||
}
|
||||
/**
|
||||
* Retrieve the indicated action from the active transaction.
|
||||
*
|
||||
@@ -204,29 +134,6 @@ namespace eosio {
|
||||
return internal_use_do_not_use::read_transaction( ptr, sz );
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a deferred transaction.
|
||||
*
|
||||
* @ingroup transaction
|
||||
* @param sender_id - The id of the sender
|
||||
*
|
||||
* @pre The deferred transaction ID exists.
|
||||
* @pre The deferred transaction ID has not yet been published.
|
||||
* @post Deferred transaction canceled.
|
||||
*
|
||||
* @return 1 if transaction was canceled, 0 if transaction was not found
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @code
|
||||
* id = 0xffffffffffffffff
|
||||
* cancel_deferred( id );
|
||||
* @endcode
|
||||
*/
|
||||
inline int cancel_deferred(const uint128_t& sender_id) {
|
||||
return internal_use_do_not_use::cancel_deferred(sender_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the currently executing transaction.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
base64 encoding and decoding with C++.
|
||||
More information at
|
||||
https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp
|
||||
https://github.com/ReneNyffenegger/cpp-base64
|
||||
|
||||
Version: 2.rc.09 (release candidate)
|
||||
|
||||
Copyright (C) 2004-2017, 2020-2022 René Nyffenegger
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
|
||||
|
||||
*/
|
||||
|
||||
#include "check.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
|
||||
namespace eosio {
|
||||
|
||||
namespace detail {
|
||||
std::string base64_encode(unsigned char const*, size_t len, bool url = false);
|
||||
std::string base64_decode(std::string_view s, bool remove_linebreaks = false, bool url = false);
|
||||
|
||||
} // detail namespace
|
||||
|
||||
inline std::string base64_encode(std::string_view enc) {
|
||||
return detail::base64_encode(reinterpret_cast<const unsigned char*>(enc.data()), enc.size(), false);
|
||||
}
|
||||
inline std::string base64_decode(std::string_view encoded_string) {
|
||||
return detail::base64_decode(encoded_string, false);
|
||||
}
|
||||
inline std::string base64url_encode(std::string_view enc) {
|
||||
return detail::base64_encode(reinterpret_cast<const unsigned char*>(enc.data()), enc.size(), true);
|
||||
}
|
||||
inline std::string base64url_decode(std::string_view encoded_string) {
|
||||
return detail::base64_decode(encoded_string, true, true);
|
||||
}
|
||||
|
||||
} // namespace eosio
|
||||
@@ -0,0 +1,225 @@
|
||||
#pragma once
|
||||
|
||||
#include "serialize.hpp"
|
||||
#include "print.hpp"
|
||||
#include "check.hpp"
|
||||
#include "varint.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace eosio {
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// see https://github.com/AntelopeIO/spring/wiki/ABI-1.3:-bitset-type
|
||||
// -------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// stores a bitset in a std::vector<uint8_t>
|
||||
//
|
||||
// - bits 0-7 in first byte, 8-15 in second, ...
|
||||
// - least significant bit of byte 0 is bit 0 of bitset.
|
||||
// - unused bits must be zero.
|
||||
// ---------------------------------------------------------------------------------
|
||||
struct bitset {
|
||||
using buffer_type = std::vector<uint8_t>;
|
||||
using size_type = uint32_t;
|
||||
static constexpr size_type bits_per_block = 8;
|
||||
static constexpr size_type npos = static_cast<size_type>(-1);
|
||||
|
||||
static constexpr size_type calc_num_blocks(size_type num_bits) {
|
||||
return (num_bits + bits_per_block - 1) / bits_per_block;
|
||||
}
|
||||
|
||||
static size_type block_index(size_type pos) noexcept { return pos / bits_per_block; }
|
||||
static uint8_t bit_index(size_type pos) noexcept { return static_cast<uint8_t>(pos % bits_per_block); }
|
||||
static uint8_t bit_mask(size_type pos) noexcept { return uint8_t(1) << bit_index(pos); }
|
||||
|
||||
size_type size() const { return m_num_bits; }
|
||||
|
||||
size_type num_blocks() const {
|
||||
assert(m_bits.size() == calc_num_blocks(m_num_bits));
|
||||
return m_bits.size();
|
||||
}
|
||||
|
||||
void resize(size_type num_bits) {
|
||||
m_bits.resize(calc_num_blocks(num_bits), 0);
|
||||
m_num_bits = num_bits;
|
||||
zero_unused_bits();
|
||||
}
|
||||
|
||||
void set(size_type pos) {
|
||||
assert(pos < m_num_bits);
|
||||
m_bits[block_index(pos)] |= bit_mask(pos);
|
||||
}
|
||||
|
||||
void clear(size_type pos) {
|
||||
assert(pos < m_num_bits);
|
||||
m_bits[block_index(pos)] &= ~bit_mask(pos);
|
||||
}
|
||||
|
||||
bool test(size_type pos) const {
|
||||
return (*this)[pos];
|
||||
}
|
||||
|
||||
bool operator[](size_type pos) const {
|
||||
assert(pos < m_num_bits);
|
||||
return !!(m_bits[block_index(pos)] & bit_mask(pos));
|
||||
}
|
||||
|
||||
void flip(size_type pos) {
|
||||
assert(pos < m_num_bits);
|
||||
if (test(pos))
|
||||
clear(pos);
|
||||
else
|
||||
set(pos);
|
||||
}
|
||||
|
||||
void flip() {
|
||||
for (auto& byte : m_bits)
|
||||
byte = ~byte;
|
||||
zero_unused_bits();
|
||||
}
|
||||
|
||||
bool all() const {
|
||||
auto sz = size();
|
||||
for (size_t i=0; i<sz; ++i)
|
||||
if (!test(i))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool none() const {
|
||||
for (auto& byte : m_bits)
|
||||
if (byte)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void zero_all_bits() {
|
||||
for (auto& byte : m_bits)
|
||||
byte = 0;
|
||||
}
|
||||
|
||||
bitset operator|=(const bitset& o) {
|
||||
assert(size() == o.size());
|
||||
for (size_t i=0; i<m_bits.size(); ++i)
|
||||
m_bits[i] |= o.m_bits[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
void zero_unused_bits() {
|
||||
assert (m_bits.size() == calc_num_blocks(m_num_bits));
|
||||
|
||||
// if != 0 this is the number of bits used in the last block
|
||||
const size_type extra_bits = bit_index(size());
|
||||
|
||||
if (extra_bits != 0)
|
||||
m_bits.back() &= (uint8_t(1) << extra_bits) - 1;
|
||||
}
|
||||
|
||||
bool unused_bits_zeroed() const {
|
||||
// if != 0 this is the number of bits used in the last block
|
||||
const size_type extra_bits = bit_index(size());
|
||||
return extra_bits == 0 || (m_bits.back() & ~((uint8_t(1) << extra_bits) - 1)) == 0;
|
||||
}
|
||||
|
||||
friend auto operator<(const bitset& a, const bitset& b) {
|
||||
return std::tuple(a.m_num_bits, a.m_bits) < std::tuple(b.m_num_bits, b.m_bits);
|
||||
}
|
||||
|
||||
friend bool operator==(const bitset& a, const bitset& b) {
|
||||
return std::tuple(a.m_num_bits, a.m_bits) == std::tuple(b.m_num_bits, b.m_bits);
|
||||
}
|
||||
|
||||
uint8_t& byte(size_t i) {
|
||||
assert(i < m_bits.size());
|
||||
return m_bits[i];
|
||||
}
|
||||
|
||||
const uint8_t& byte(size_t i) const {
|
||||
assert(i < m_bits.size());
|
||||
return m_bits[i];
|
||||
}
|
||||
|
||||
std::string to_string() const {
|
||||
std::string res;
|
||||
res.resize(size());
|
||||
size_t idx = 0;
|
||||
for (auto i = size(); i-- > 0;)
|
||||
res[idx++] = (*this)[i] ? '1' : '0';
|
||||
return res;
|
||||
}
|
||||
|
||||
static bitset from_string(std::string_view s) {
|
||||
bitset bs;
|
||||
auto num_bits = s.size();
|
||||
bs.resize(num_bits);
|
||||
|
||||
for (size_t i = 0; i < num_bits; ++i) {
|
||||
switch (s[i]) {
|
||||
case '0':
|
||||
break; // nothing to do, all bits initially 0
|
||||
case '1':
|
||||
bs.set(num_bits - i - 1); // high bitset indexes come first in the JSON representation
|
||||
break;
|
||||
default:
|
||||
eosio::check(false, "unexpected character in bitset string representation");
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(bs.unused_bits_zeroed());
|
||||
return bs;
|
||||
}
|
||||
|
||||
void print() const {
|
||||
auto s = to_string();
|
||||
if (!s.empty())
|
||||
printl(s.data(), s.size());
|
||||
}
|
||||
|
||||
// binary representation
|
||||
// ---------------------
|
||||
// The bitset first encodes the number of bits it contains as a varint, then encodes
|
||||
// (size+8-1)/8 bytes into the stream. The first byte represents bits 0-7, the next 8-15,
|
||||
// and so on; i.e. LSB first.
|
||||
// Within a byte, the least significant bit stores the smaller bitset index.
|
||||
// Unused bits should be written as 0.
|
||||
//
|
||||
// This matches the storage scheme of bitset above
|
||||
// ---------------------------------------------------------------------------------------
|
||||
template <typename DataStream>
|
||||
friend DataStream& operator>>(DataStream& stream, bitset& obj) {
|
||||
unsigned_int num_bits(0);
|
||||
stream >> num_bits;
|
||||
obj.resize(num_bits.value);
|
||||
if (obj.size() > 0) {
|
||||
auto num_blocks = bitset::calc_num_blocks(obj.size());
|
||||
for (size_t i = 0; i < num_blocks; ++i)
|
||||
stream >> obj.byte(i);
|
||||
obj.zero_unused_bits();
|
||||
assert(obj.unused_bits_zeroed());
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
template <typename DataStream>
|
||||
friend DataStream& operator<<(DataStream& stream, const bitset& obj) {
|
||||
unsigned_int num_bits(obj.size());
|
||||
stream << num_bits;
|
||||
if (obj.size() > 0) {
|
||||
auto num_blocks = bitset::calc_num_blocks(obj.size());
|
||||
assert(num_blocks >= 1);
|
||||
for (size_t i = 0; i < num_blocks; ++i)
|
||||
stream << obj.byte(i);
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
private:
|
||||
size_type m_num_bits{0}; // members order matters for comparison operators
|
||||
buffer_type m_bits; // must be after `m_num_bits`
|
||||
};
|
||||
|
||||
constexpr const char* get_type_name(bitset*) { return "bitset"; }
|
||||
|
||||
} // namespace eosio
|
||||
@@ -22,6 +22,15 @@ namespace eosio {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return codes returned by host functions
|
||||
*/
|
||||
enum return_code : int32_t {
|
||||
failure = -1,
|
||||
success = 0
|
||||
};
|
||||
|
||||
/**
|
||||
* @defgroup system System
|
||||
* @ingroup core
|
||||
|
||||
@@ -0,0 +1,502 @@
|
||||
#pragma once
|
||||
|
||||
#include "crypto.hpp"
|
||||
|
||||
#include "fixed_bytes.hpp"
|
||||
#include "varint.hpp"
|
||||
#include "serialize.hpp"
|
||||
#include "base64.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <span>
|
||||
|
||||
namespace bls12_381 {
|
||||
class sha256 {
|
||||
public:
|
||||
sha256(): m_blocklen(0), m_bitlen(0) {
|
||||
m_state[0] = 0x6a09e667;
|
||||
m_state[1] = 0xbb67ae85;
|
||||
m_state[2] = 0x3c6ef372;
|
||||
m_state[3] = 0xa54ff53a;
|
||||
m_state[4] = 0x510e527f;
|
||||
m_state[5] = 0x9b05688c;
|
||||
m_state[6] = 0x1f83d9ab;
|
||||
m_state[7] = 0x5be0cd19;
|
||||
}
|
||||
void update(const uint8_t * data, size_t length) {
|
||||
for(size_t i = 0 ; i < length ; i++) {
|
||||
m_data[m_blocklen++] = data[i];
|
||||
if (m_blocklen == 64) {
|
||||
transform();
|
||||
|
||||
// End of the block
|
||||
m_bitlen += 512;
|
||||
m_blocklen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
inline void update(const char* data, size_t length) {
|
||||
update(reinterpret_cast<const uint8_t*>(data), length);
|
||||
}
|
||||
inline void update(const std::string &data) {
|
||||
update(reinterpret_cast<const char*>(data.data()), data.size());
|
||||
}
|
||||
std::array<uint8_t, 32> digest() {
|
||||
std::array<uint8_t, 32> hash;
|
||||
|
||||
pad();
|
||||
revert(hash);
|
||||
|
||||
return hash;
|
||||
}
|
||||
void digest(uint8_t* dst) {
|
||||
std::array<uint8_t, 32>* phash = reinterpret_cast<std::array<uint8_t, 32>*>(dst);
|
||||
|
||||
pad();
|
||||
revert(*phash);
|
||||
}
|
||||
|
||||
//static string toString(const array<uint8_t, 32>& digest);
|
||||
|
||||
private:
|
||||
uint8_t m_data[64];
|
||||
uint32_t m_blocklen;
|
||||
uint64_t m_bitlen;
|
||||
uint32_t m_state[8]; //A, B, C, D, E, F, G, H
|
||||
|
||||
static constexpr std::array<uint32_t, 64> K = {
|
||||
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,
|
||||
0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
|
||||
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,
|
||||
0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
|
||||
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,
|
||||
0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
|
||||
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,
|
||||
0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
|
||||
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,
|
||||
0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
|
||||
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,
|
||||
0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
|
||||
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,
|
||||
0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
|
||||
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,
|
||||
0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
|
||||
};
|
||||
|
||||
static uint32_t rotr(uint32_t x, uint32_t n) {
|
||||
return (x >> n) | (x << (32 - n));
|
||||
}
|
||||
static uint32_t choose(uint32_t e, uint32_t f, uint32_t g) {
|
||||
return (e & f) ^ (~e & g);
|
||||
}
|
||||
static uint32_t majority(uint32_t a, uint32_t b, uint32_t c) {
|
||||
return (a & (b | c)) | (b & c);
|
||||
}
|
||||
static uint32_t sig0(uint32_t x) {
|
||||
return sha256::rotr(x, 7) ^ sha256::rotr(x, 18) ^ (x >> 3);
|
||||
}
|
||||
static uint32_t sig1(uint32_t x) {
|
||||
return sha256::rotr(x, 17) ^ sha256::rotr(x, 19) ^ (x >> 10);
|
||||
}
|
||||
void transform() {
|
||||
uint32_t maj, xorA, ch, xorE, sum, newA, newE, m[64];
|
||||
uint32_t state[8];
|
||||
|
||||
for(uint8_t i = 0, j = 0; i < 16; i++, j += 4) {
|
||||
// Split data in 32 bit blocks for the 16 first words
|
||||
m[i] = (m_data[j] << 24) | (m_data[j + 1] << 16) | (m_data[j + 2] << 8) | (m_data[j + 3]);
|
||||
}
|
||||
|
||||
for(uint8_t k = 16 ; k < 64; k++) {
|
||||
// Remaining 48 blocks
|
||||
m[k] = sha256::sig1(m[k - 2]) + m[k - 7] + sha256::sig0(m[k - 15]) + m[k - 16];
|
||||
}
|
||||
|
||||
for(uint8_t i = 0 ; i < 8 ; i++) {
|
||||
state[i] = m_state[i];
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < 64; i++) {
|
||||
maj = sha256::majority(state[0], state[1], state[2]);
|
||||
xorA = sha256::rotr(state[0], 2) ^ sha256::rotr(state[0], 13) ^ sha256::rotr(state[0], 22);
|
||||
|
||||
ch = choose(state[4], state[5], state[6]);
|
||||
|
||||
xorE = sha256::rotr(state[4], 6) ^ sha256::rotr(state[4], 11) ^ sha256::rotr(state[4], 25);
|
||||
|
||||
sum = m[i] + K[i] + state[7] + ch + xorE;
|
||||
newA = xorA + maj + sum;
|
||||
newE = state[3] + sum;
|
||||
|
||||
state[7] = state[6];
|
||||
state[6] = state[5];
|
||||
state[5] = state[4];
|
||||
state[4] = newE;
|
||||
state[3] = state[2];
|
||||
state[2] = state[1];
|
||||
state[1] = state[0];
|
||||
state[0] = newA;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0 ; i < 8 ; i++) {
|
||||
m_state[i] += state[i];
|
||||
}
|
||||
}
|
||||
void pad() {
|
||||
uint64_t i = m_blocklen;
|
||||
uint8_t end = m_blocklen < 56 ? 56 : 64;
|
||||
|
||||
m_data[i++] = 0x80; // Append a bit 1
|
||||
while(i < end) {
|
||||
m_data[i++] = 0x00; // Pad with zeros
|
||||
}
|
||||
|
||||
if(m_blocklen >= 56) {
|
||||
transform();
|
||||
memset(m_data, 0, 56);
|
||||
}
|
||||
|
||||
// Append to the padding the total message's length in bits and transform.
|
||||
m_bitlen += m_blocklen * 8;
|
||||
m_data[63] = m_bitlen;
|
||||
m_data[62] = m_bitlen >> 8;
|
||||
m_data[61] = m_bitlen >> 16;
|
||||
m_data[60] = m_bitlen >> 24;
|
||||
m_data[59] = m_bitlen >> 32;
|
||||
m_data[58] = m_bitlen >> 40;
|
||||
m_data[57] = m_bitlen >> 48;
|
||||
m_data[56] = m_bitlen >> 56;
|
||||
transform();
|
||||
}
|
||||
void revert(std::array<uint8_t, 32>& hash) {
|
||||
// SHA uses big endian byte ordering
|
||||
// Revert all bytes
|
||||
for(uint8_t i = 0 ; i < 4 ; i++) {
|
||||
for(uint8_t j = 0 ; j < 8 ; j++) {
|
||||
hash[i + (j * 4)] = (m_state[j] >> (24 - i * 8)) & 0x000000ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace bls12_381
|
||||
|
||||
namespace eosio {
|
||||
|
||||
namespace internal_use_do_not_use {
|
||||
extern "C" {
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_g1_add(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_g2_add(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_g1_weighted_sum(const char* points, uint32_t points_len, const char* scalars, uint32_t scalars_len, uint32_t n, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_g2_weighted_sum(const char* points, uint32_t points_len, const char* scalars, uint32_t scalars_len, uint32_t n, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_pairing(const char* g1_points, uint32_t g1_points_len, const char* g2_points, uint32_t g2_points_len, uint32_t n, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_g1_map(const char* e, uint32_t e_len, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_g2_map(const char* e, uint32_t e_len, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_fp_mod(const char* s, uint32_t s_len, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_fp_mul(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len);
|
||||
|
||||
__attribute__((eosio_wasm_import))
|
||||
int32_t bls_fp_exp(const char* base, uint32_t base_len, const char* exp, uint32_t exp_len, char* res, uint32_t res_len);
|
||||
}
|
||||
}
|
||||
|
||||
using bls_scalar = std::array<char, 32>;
|
||||
using bls_fp = std::array<char, 48>;
|
||||
using bls_s = std::array<char, 64>;
|
||||
using bls_fp2 = std::array<bls_fp, 2>;
|
||||
using bls_g1 = std::array<char, 96>; // affine little-endian
|
||||
using bls_g2 = std::array<char, 192>; // affine little-endian
|
||||
using bls_gt = std::array<char, 576>; // group fp12
|
||||
|
||||
inline int32_t bls_g1_add(const bls_g1& op1, const bls_g1& op2, bls_g1& res) {
|
||||
return internal_use_do_not_use::bls_g1_add(
|
||||
op1.data(), op1.size(),
|
||||
op2.data(), op2.size(),
|
||||
res.data(), res.size()
|
||||
);
|
||||
}
|
||||
|
||||
inline int32_t bls_g2_add(const bls_g2& op1, const bls_g2& op2, bls_g2& res) {
|
||||
return internal_use_do_not_use::bls_g2_add(
|
||||
op1.data(), op1.size(),
|
||||
op2.data(), op2.size(),
|
||||
res.data(), res.size()
|
||||
);
|
||||
}
|
||||
|
||||
inline int32_t bls_g1_weighted_sum(const bls_g1 g1_points[], const bls_scalar scalars[], uint32_t num, bls_g1& res) {
|
||||
if (num == 0)
|
||||
return return_code::failure;
|
||||
return internal_use_do_not_use::bls_g1_weighted_sum(
|
||||
g1_points[0].data(), num * g1_points[0].size(),
|
||||
scalars[0].data(), num * scalars[0].size(),
|
||||
num,
|
||||
res.data(), res.size()
|
||||
);
|
||||
}
|
||||
|
||||
inline int32_t bls_g2_weighted_sum(const bls_g2 g2_points[], const bls_scalar scalars[], uint32_t num, bls_g2& res) {
|
||||
if (num == 0)
|
||||
return return_code::failure;
|
||||
return internal_use_do_not_use::bls_g2_weighted_sum(
|
||||
g2_points[0].data(), num * g2_points[0].size(),
|
||||
scalars[0].data(), num * scalars[0].size(),
|
||||
num,
|
||||
res.data(), res.size()
|
||||
);
|
||||
}
|
||||
|
||||
inline int32_t bls_pairing(const bls_g1 g1_points[], const bls_g2 g2_points[], const uint32_t num, bls_gt& res) {
|
||||
if (num == 0)
|
||||
return return_code::failure;
|
||||
return internal_use_do_not_use::bls_pairing(
|
||||
g1_points[0].data(), num * g1_points[0].size(),
|
||||
g2_points[0].data(), num * g2_points[0].size(),
|
||||
num,
|
||||
res.data(), res.size()
|
||||
);
|
||||
}
|
||||
|
||||
inline int32_t bls_g1_map(const bls_fp& e, bls_g1& res) {
|
||||
return internal_use_do_not_use::bls_g1_map(
|
||||
e.data(), e.size(),
|
||||
res.data(), res.size()
|
||||
);
|
||||
}
|
||||
|
||||
inline int32_t bls_g2_map(const bls_fp2& e, bls_g2& res) {
|
||||
return internal_use_do_not_use::bls_g2_map(
|
||||
e[0].data(), 2 * e[0].size(),
|
||||
res.data(), res.size()
|
||||
);
|
||||
}
|
||||
|
||||
inline int32_t bls_fp_mod(const bls_s& s, bls_fp& res) {
|
||||
return internal_use_do_not_use::bls_fp_mod(
|
||||
s.data(), s.size(),
|
||||
res.data(), res.size()
|
||||
);
|
||||
}
|
||||
|
||||
inline int32_t bls_fp_mul(const bls_fp& op1, const bls_fp& op2, bls_fp& res) {
|
||||
return internal_use_do_not_use::bls_fp_mul(
|
||||
op1.data(), op1.size(),
|
||||
op2.data(), op2.size(),
|
||||
res.data(), res.size()
|
||||
);
|
||||
}
|
||||
|
||||
inline int32_t bls_fp_exp(const bls_fp& base, const bls_s& exp, bls_fp& res) {
|
||||
return internal_use_do_not_use::bls_fp_exp(
|
||||
base.data(), base.size(),
|
||||
exp.data(), exp.size(),
|
||||
res.data(), res.size()
|
||||
);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
const inline std::string bls_public_key_prefix = "PUB_BLS_";
|
||||
constexpr inline uint32_t bls_checksum_size = sizeof(uint32_t);
|
||||
const inline std::string bls_signature_prefix = "SIG_BLS_";
|
||||
|
||||
template<typename T, const std::string& Prefix>
|
||||
std::string bls_type_to_base64url(const T& g1) {
|
||||
std::array<char, sizeof(T) + bls_checksum_size> g1_with_checksum;
|
||||
auto it = std::copy(g1.begin(), g1.end(), g1_with_checksum.begin());
|
||||
|
||||
auto csum = ripemd160(g1.data(), g1.size()).extract_as_byte_array();
|
||||
std::copy(reinterpret_cast<const char*>(csum.data()),
|
||||
reinterpret_cast<const char*>(csum.data())+bls_checksum_size,
|
||||
it);
|
||||
|
||||
return Prefix + eosio::base64url_encode({g1_with_checksum.data(), g1_with_checksum.size()});
|
||||
}
|
||||
|
||||
template<typename T, const std::string& Prefix>
|
||||
T bls_base64url_to_type(const char* data, size_t size) {
|
||||
eosio::check(size > Prefix.size(), "encoded base64 key is too short");
|
||||
eosio::check(0 == memcmp(data, Prefix.data(), Prefix.size()), "base64 encoded type must begin from corresponding prefix");
|
||||
|
||||
std::string decoded = eosio::base64url_decode({data+Prefix.size(), size - Prefix.size()});
|
||||
T ret;
|
||||
eosio::check(decoded.size() == ret.size() + bls_checksum_size, "decoded size " + std::to_string(decoded.size()) +
|
||||
" doesn't match structure size " + std::to_string(ret.size()) +
|
||||
" + checksum " + std::to_string(bls_checksum_size));
|
||||
|
||||
auto it = decoded.end();
|
||||
std::advance(it, -bls_checksum_size);
|
||||
std::copy(decoded.begin(), it, ret.begin());
|
||||
|
||||
auto csum = ripemd160(ret.data(), ret.size()).extract_as_byte_array();
|
||||
eosio::check(0 == memcmp(&*it, csum.data(), bls_checksum_size), "checksum of structure doesn't match");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const inline std::string CIPHERSUITE_ID = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_"; // basic DST
|
||||
const inline std::string POP_CIPHERSUITE_ID = "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; // proof of possession DST
|
||||
|
||||
// g1::one().negate().toAffineBytesLE(), 96 bytes
|
||||
const inline std::vector<uint8_t> G1_ONE_NEG = {0xbb, 0xc6, 0x22, 0xdb, 0xa, 0xf0, 0x3a, 0xfb, 0xef, 0x1a, 0x7a, 0xf9,
|
||||
0x3f, 0xe8, 0x55, 0x6c, 0x58, 0xac, 0x1b, 0x17, 0x3f, 0x3a, 0x4e, 0xa1,
|
||||
0x5, 0xb9, 0x74, 0x97, 0x4f, 0x8c, 0x68, 0xc3, 0xf, 0xac, 0xa9, 0x4f,
|
||||
0x8c, 0x63, 0x95, 0x26, 0x94, 0xd7, 0x97, 0x31, 0xa7, 0xd3, 0xf1, 0x17,
|
||||
0xca, 0xc2, 0x39, 0xb9, 0xd6, 0xdc, 0x54, 0xad, 0x1b, 0x75, 0xcb, 0xe,
|
||||
0xba, 0x38, 0x6f, 0x4e, 0x36, 0x42, 0xac, 0xca, 0xd5, 0xb9, 0x55, 0x66,
|
||||
0xc9, 0x7, 0xb5, 0x1d, 0xef, 0x6a, 0x81, 0x67, 0xf2, 0x21, 0x2e, 0xcf,
|
||||
0xc8, 0x76, 0x7d, 0xaa, 0xa8, 0x45, 0xd5, 0x55, 0x68, 0x1d, 0x4d, 0x11};
|
||||
|
||||
// fp12::one().toBytesLE(), 576 bytes
|
||||
const inline std::vector<uint8_t> GT_ONE = []{ std::vector<uint8_t> r(576, 0); r[0] = 1; return r; }();
|
||||
|
||||
// Construct an extensible-output function based on SHA256
|
||||
inline void xmd_sh256(
|
||||
char *buf,
|
||||
int buf_len,
|
||||
const char *in,
|
||||
int in_len,
|
||||
const char *dst,
|
||||
int dst_len
|
||||
) {
|
||||
const unsigned int SHA256HashSize = 32;
|
||||
const unsigned int SHA256_Message_Block_Size = 64;
|
||||
const unsigned ell = (buf_len + SHA256HashSize - 1) / SHA256HashSize;
|
||||
if (buf_len < 0 || ell > 255 || dst_len > 255) {
|
||||
return;
|
||||
}
|
||||
const uint8_t Z_pad[SHA256_Message_Block_Size] = { 0, };
|
||||
const uint8_t l_i_b_0_str[] = {
|
||||
static_cast<uint8_t>(buf_len >> 8),
|
||||
static_cast<uint8_t>(buf_len & 0xff),
|
||||
0,
|
||||
static_cast<uint8_t>(dst_len)
|
||||
};
|
||||
const uint8_t *dstlen_str = l_i_b_0_str + 3;
|
||||
uint8_t b_0[SHA256HashSize];
|
||||
bls12_381::sha256 sha;
|
||||
sha.update(Z_pad, SHA256_Message_Block_Size);
|
||||
sha.update(in, in_len);
|
||||
sha.update(l_i_b_0_str, 3);
|
||||
sha.update(dst, dst_len);
|
||||
sha.update(dstlen_str, 1);
|
||||
sha.digest(b_0);
|
||||
uint8_t b_i[SHA256HashSize + 1] = { 0, };
|
||||
for (unsigned i = 1; i <= ell; ++i) {
|
||||
for (unsigned j = 0; j < SHA256HashSize; ++j) {
|
||||
b_i[j] = b_0[j] ^ b_i[j];
|
||||
}
|
||||
b_i[SHA256HashSize] = i;
|
||||
bls12_381::sha256 s;
|
||||
s.update(b_i, SHA256HashSize + 1);
|
||||
s.update(dst, dst_len);
|
||||
s.update(dstlen_str, 1);
|
||||
s.digest(b_i);
|
||||
const int rem_after = buf_len - i * SHA256HashSize;
|
||||
const int copy_len = SHA256HashSize + (rem_after < 0 ? rem_after : 0);
|
||||
memcpy(buf + (i - 1) * SHA256HashSize, b_i, copy_len);
|
||||
}
|
||||
}
|
||||
|
||||
inline bls_s scalar_fromBE(const bls_s& in) {
|
||||
bls_s out;
|
||||
constexpr size_t last_index = sizeof(out) - 1;
|
||||
for(size_t i = 0; i <= last_index; ++i)
|
||||
{
|
||||
out[i] = in[last_index - i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
inline void g2_fromMessage(std::span<const char> msg, const std::string& dst, bls_g2& res) {
|
||||
|
||||
std::array<bls_s, 4> buf;
|
||||
xmd_sh256(buf.data()->data(), sizeof(buf), msg.data(), msg.size(), dst.data(), dst.length());
|
||||
|
||||
bls_s k;
|
||||
bls_fp2 t;
|
||||
bls_g2 p, q;
|
||||
|
||||
k = scalar_fromBE(buf[0]);
|
||||
bls_fp_mod(k, t[0]);
|
||||
k = scalar_fromBE(buf[1]);
|
||||
bls_fp_mod(k, t[1]);
|
||||
|
||||
bls_g2_map(t, p);
|
||||
|
||||
k = scalar_fromBE(buf[2]);
|
||||
bls_fp_mod(k, t[0]);
|
||||
k = scalar_fromBE(buf[3]);
|
||||
bls_fp_mod(k, t[1]);
|
||||
|
||||
bls_g2_map(t, q);
|
||||
bls_g2_add(p, q, res);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
inline std::string encode_g1_to_bls_public_key(const bls_g1& g1) {
|
||||
return detail::bls_type_to_base64url<bls_g1, detail::bls_public_key_prefix>(g1);
|
||||
}
|
||||
inline bls_g1 decode_bls_public_key_to_g1(std::string_view public_key) {
|
||||
return detail::bls_base64url_to_type<bls_g1, detail::bls_public_key_prefix>(public_key.data(), public_key.size());
|
||||
}
|
||||
inline std::string encode_g2_to_bls_signature(const bls_g2& g2) {
|
||||
return detail::bls_type_to_base64url<bls_g2, detail::bls_signature_prefix>(g2);
|
||||
}
|
||||
inline bls_g2 decode_bls_signature_to_g2(std::string_view public_key) {
|
||||
return detail::bls_base64url_to_type<bls_g2, detail::bls_signature_prefix>(public_key.data(), public_key.size());
|
||||
}
|
||||
|
||||
// pubkey and signature are assumed to be in RAW affine little-endian bytes
|
||||
inline bool bls_pop_verify(const bls_g1& pubkey, const bls_g2& signature_proof) {
|
||||
using namespace detail;
|
||||
|
||||
bls_g1 g1_points[2] = {0};
|
||||
bls_g2 g2_points[2] = {0};
|
||||
|
||||
std::memcpy(g1_points[0].data(), G1_ONE_NEG.data(), G1_ONE_NEG.size());
|
||||
std::memcpy(g2_points[0].data(), signature_proof.data(), signature_proof.size());
|
||||
|
||||
std::memcpy(g1_points[1].data(), pubkey.data(), pubkey.size());
|
||||
g2_fromMessage(pubkey, POP_CIPHERSUITE_ID, g2_points[1]);
|
||||
|
||||
bls_gt r;
|
||||
bls_pairing(g1_points, g2_points, 2, r);
|
||||
|
||||
return 0 == std::memcmp(r.data(), GT_ONE.data(), GT_ONE.size());
|
||||
}
|
||||
|
||||
// pubkey and signature are assumed to be in RAW affine little-endian bytes
|
||||
inline bool bls_signature_verify(const bls_g1& pubkey, const bls_g2& signature_proof, const std::string& msg) {
|
||||
bls_g1 g1_points[2];
|
||||
bls_g2 g2_points[2];
|
||||
|
||||
std::memcpy(g1_points[0].data(), detail::G1_ONE_NEG.data(), detail::G1_ONE_NEG.size());
|
||||
std::memcpy(g2_points[0].data(), signature_proof.data(), signature_proof.size());
|
||||
|
||||
std::memcpy(g1_points[1].data(), pubkey.data(), pubkey.size());
|
||||
detail::g2_fromMessage(msg, detail::CIPHERSUITE_ID, g2_points[1]);
|
||||
|
||||
bls_gt r;
|
||||
bls_pairing(g1_points, g2_points, 2, r);
|
||||
|
||||
return 0 == std::memcmp(r.data(), detail::GT_ONE.data(), detail::GT_ONE.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,7 +456,7 @@ inline datastream<Stream>& operator>>(datastream<Stream>& ds, std::optional<T>&
|
||||
T val;
|
||||
ds >> val;
|
||||
opt = val;
|
||||
}
|
||||
} else { opt.reset(); }
|
||||
return ds;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include "check.hpp"
|
||||
#include "serialize.hpp"
|
||||
#include "reflect.hpp"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace eosio {
|
||||
struct hash_id {
|
||||
public:
|
||||
static constexpr uint32_t max_length = 128;
|
||||
|
||||
enum class raw : uint64_t {};
|
||||
|
||||
constexpr explicit hash_id( hash_id::raw r )
|
||||
:id(static_cast<uint64_t>(r)) {}
|
||||
|
||||
constexpr hash_id() : id(0) {}
|
||||
|
||||
constexpr explicit hash_id( std::string_view s )
|
||||
: id(djbh_hash(s))
|
||||
{
|
||||
validate(s);
|
||||
}
|
||||
|
||||
constexpr void validate(std::string_view str) {
|
||||
if (str.empty()) {
|
||||
eosio::check(false, "string cannot be empty to be an hash_id");
|
||||
}
|
||||
|
||||
if (str.length() > max_length) {
|
||||
eosio::check(false, "string is too long be a valid hash_id. must be less than or equal to " + std::to_string(max_length));
|
||||
}
|
||||
|
||||
// cannot use std::isalpha in constexpr function
|
||||
if (! ((str[0] >= 'A' && str[0] <= 'Z') || (str[0] >= 'a' && str[0] <= 'z') || str[0] == '_') ) {
|
||||
eosio::check(false, "string must start with a letter or _ to be a valid hash_id.");
|
||||
}
|
||||
|
||||
for (char c : str.substr(1)) {
|
||||
// cannot use std::isalnum in constexpr function
|
||||
if (! ((str[0] >= 'A' && str[0] <= 'Z') || (str[0] >= 'a' && str[0] <= 'z') || (str[0] >= '0' && str[0] <= '9') || str[0] == '_') ) {
|
||||
eosio::check(false, "string contains a character " + std::string{c} + " that is not a letter, number, or _");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr uint64_t djbh_hash(std::string_view s) {
|
||||
uint64_t hash = 5381;
|
||||
for (char c : s) {
|
||||
hash = ((hash << 5) + hash) + static_cast<uint8_t>(c); // hash * 33 + c
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
constexpr operator raw()const { return raw(id); }
|
||||
|
||||
uint64_t id = 0;
|
||||
|
||||
CDT_REFLECT(id);
|
||||
EOSLIB_SERIALIZE( hash_id, (id) )
|
||||
}; /// namespace hash_id
|
||||
} /// namespace eosio
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
|
||||
template <typename T, T... Str>
|
||||
inline constexpr eosio::hash_id operator""_i() {
|
||||
constexpr auto x = eosio::hash_id{std::string_view{eosio::detail::to_const_char_arr<Str...>::value, sizeof...(Str)}};
|
||||
return x;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
@@ -65,11 +65,6 @@ namespace bluegrass { namespace meta {
|
||||
template <typename T>
|
||||
constexpr bool pass_type() { return true; }
|
||||
|
||||
template <typename>
|
||||
constexpr bool is_callable_impl(...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct wrapper_t {
|
||||
using type = T;
|
||||
|
||||
@@ -16,7 +16,7 @@ if (NOT ${found_project})
|
||||
ExternalProject_Add(
|
||||
catch2_external_proj
|
||||
GIT_REPOSITORY "https://github.com/catchorg/Catch2"
|
||||
GIT_TAG "v2.12.2"
|
||||
GIT_TAG "v2.13.10"
|
||||
SOURCE_DIR @CATCH2_DIRECTORY@/catch2
|
||||
BINARY_DIR @CATCH2_DIRECTORY@/catch2
|
||||
BUILD_ALWAYS 0
|
||||
|
||||
+193
-143
@@ -17,334 +17,346 @@
|
||||
using namespace eosio::native;
|
||||
extern "C" {
|
||||
void get_resource_limits( capi_name account, int64_t* ram_bytes, int64_t* net_weight, int64_t* cpu_weight ) {
|
||||
return intrinsics::get().call<intrinsics::get_resource_limits>(account, ram_bytes, net_weight, cpu_weight);
|
||||
return intrinsics::get().exec<intrinsics::get_resource_limits>(account, ram_bytes, net_weight, cpu_weight);
|
||||
}
|
||||
void set_resource_limits( capi_name account, int64_t ram_bytes, int64_t net_weight, int64_t cpu_weight ) {
|
||||
return intrinsics::get().call<intrinsics::set_resource_limits>(account, ram_bytes, net_weight, cpu_weight);
|
||||
return intrinsics::get().exec<intrinsics::set_resource_limits>(account, ram_bytes, net_weight, cpu_weight);
|
||||
}
|
||||
int64_t set_proposed_producers( char *producer_data, uint32_t producer_data_size ) {
|
||||
return intrinsics::get().call<intrinsics::set_proposed_producers>(producer_data, producer_data_size);
|
||||
return intrinsics::get().exec<intrinsics::set_proposed_producers>(producer_data, producer_data_size);
|
||||
}
|
||||
int64_t set_proposed_producers_ex( uint64_t producer_data_format, char *producer_data, uint32_t producer_data_size ) {
|
||||
return intrinsics::get().call<intrinsics::set_proposed_producers_ex>(producer_data_format, producer_data, producer_data_size);
|
||||
return intrinsics::get().exec<intrinsics::set_proposed_producers_ex>(producer_data_format, producer_data, producer_data_size);
|
||||
}
|
||||
uint32_t get_blockchain_parameters_packed( char* data, uint32_t datalen ) {
|
||||
return intrinsics::get().call<intrinsics::get_blockchain_parameters_packed>(data, datalen);
|
||||
return intrinsics::get().exec<intrinsics::get_blockchain_parameters_packed>(data, datalen);
|
||||
}
|
||||
void set_blockchain_parameters_packed( char* data, uint32_t datalen ) {
|
||||
return intrinsics::get().call<intrinsics::set_blockchain_parameters_packed>(data, datalen);
|
||||
return intrinsics::get().exec<intrinsics::set_blockchain_parameters_packed>(data, datalen);
|
||||
}
|
||||
bool is_privileged( capi_name account ) {
|
||||
return intrinsics::get().call<intrinsics::is_privileged>(account);
|
||||
return intrinsics::get().exec<intrinsics::is_privileged>(account);
|
||||
}
|
||||
void set_privileged( capi_name account, bool is_priv ) {
|
||||
return intrinsics::get().call<intrinsics::set_privileged>(account, is_priv);
|
||||
return intrinsics::get().exec<intrinsics::set_privileged>(account, is_priv);
|
||||
}
|
||||
bool is_feature_activated( const capi_checksum256* feature_digest ) {
|
||||
return intrinsics::get().call<intrinsics::is_feature_activated>(feature_digest);
|
||||
return intrinsics::get().exec<intrinsics::is_feature_activated>(feature_digest);
|
||||
}
|
||||
void preactivate_feature( const capi_checksum256* feature_digest ) {
|
||||
return intrinsics::get().call<intrinsics::preactivate_feature>(feature_digest);
|
||||
return intrinsics::get().exec<intrinsics::preactivate_feature>(feature_digest);
|
||||
}
|
||||
uint32_t get_active_producers( capi_name* producers, uint32_t datalen ) {
|
||||
return intrinsics::get().call<intrinsics::get_active_producers>(producers, datalen);
|
||||
return intrinsics::get().exec<intrinsics::get_active_producers>(producers, datalen);
|
||||
}
|
||||
int32_t db_idx64_store(uint64_t scope, capi_name table, capi_name payer, uint64_t id, const uint64_t* secondary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx64_store>(scope, table, payer, id, secondary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx64_store>(scope, table, payer, id, secondary);
|
||||
}
|
||||
void db_idx64_remove(int32_t iterator) {
|
||||
return intrinsics::get().call<intrinsics::db_idx64_remove>(iterator);
|
||||
return intrinsics::get().exec<intrinsics::db_idx64_remove>(iterator);
|
||||
}
|
||||
void db_idx64_update(int32_t iterator, capi_name payer, const uint64_t* secondary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx64_update>(iterator, payer, secondary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx64_update>(iterator, payer, secondary);
|
||||
}
|
||||
int32_t db_idx64_find_primary(capi_name code, uint64_t scope, capi_name table, uint64_t* secondary, uint64_t primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx64_find_primary>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx64_find_primary>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx64_find_secondary(capi_name code, uint64_t scope, capi_name table, const uint64_t* secondary, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx64_find_secondary>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx64_find_secondary>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx64_lowerbound(capi_name code, uint64_t scope, capi_name table, uint64_t* secondary, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx64_lowerbound>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx64_lowerbound>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx64_upperbound(capi_name code, uint64_t scope, capi_name table, uint64_t* secondary, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx64_upperbound>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx64_upperbound>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx64_end(capi_name code, uint64_t scope, capi_name table) {
|
||||
return intrinsics::get().call<intrinsics::db_idx64_end>(code, scope, table);
|
||||
return intrinsics::get().exec<intrinsics::db_idx64_end>(code, scope, table);
|
||||
}
|
||||
int32_t db_idx64_next(int32_t iterator, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx64_next>(iterator, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx64_next>(iterator, primary);
|
||||
}
|
||||
int32_t db_idx64_previous(int32_t iterator, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx64_previous>(iterator, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx64_previous>(iterator, primary);
|
||||
}
|
||||
int32_t db_idx128_store(uint64_t scope, capi_name table, capi_name payer, uint64_t id, const uint128_t* secondary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx128_store>(scope, table, payer, id, secondary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx128_store>(scope, table, payer, id, secondary);
|
||||
}
|
||||
void db_idx128_remove(int32_t iterator) {
|
||||
return intrinsics::get().call<intrinsics::db_idx128_remove>(iterator);
|
||||
return intrinsics::get().exec<intrinsics::db_idx128_remove>(iterator);
|
||||
}
|
||||
void db_idx128_update(int32_t iterator, capi_name payer, const uint128_t* secondary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx128_update>(iterator, payer, secondary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx128_update>(iterator, payer, secondary);
|
||||
}
|
||||
int32_t db_idx128_find_primary(capi_name code, uint64_t scope, capi_name table, uint128_t* secondary, uint64_t primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx128_find_primary>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx128_find_primary>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx128_find_secondary(capi_name code, uint64_t scope, capi_name table, const uint128_t* secondary, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx128_find_secondary>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx128_find_secondary>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx128_lowerbound(capi_name code, uint64_t scope, capi_name table, uint128_t* secondary, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx128_lowerbound>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx128_lowerbound>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx128_upperbound(capi_name code, uint64_t scope, capi_name table, uint128_t* secondary, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx128_upperbound>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx128_upperbound>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx128_end(capi_name code, uint64_t scope, capi_name table) {
|
||||
return intrinsics::get().call<intrinsics::db_idx128_end>(code, scope, table);
|
||||
return intrinsics::get().exec<intrinsics::db_idx128_end>(code, scope, table);
|
||||
}
|
||||
int32_t db_idx128_next(int32_t iterator, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx128_next>(iterator, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx128_next>(iterator, primary);
|
||||
}
|
||||
int32_t db_idx128_previous(int32_t iterator, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx128_previous>(iterator, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx128_previous>(iterator, primary);
|
||||
}
|
||||
int32_t db_idx256_store(uint64_t scope, capi_name table, capi_name payer, uint64_t id, const uint128_t* data, uint32_t datalen) {
|
||||
return intrinsics::get().call<intrinsics::db_idx256_store>(scope, table, payer, id, data, datalen);
|
||||
return intrinsics::get().exec<intrinsics::db_idx256_store>(scope, table, payer, id, data, datalen);
|
||||
}
|
||||
void db_idx256_remove(int32_t iterator) {
|
||||
return intrinsics::get().call<intrinsics::db_idx256_remove>(iterator);
|
||||
return intrinsics::get().exec<intrinsics::db_idx256_remove>(iterator);
|
||||
}
|
||||
void db_idx256_update(int32_t iterator, capi_name payer, const uint128_t* data, uint32_t datalen) {
|
||||
return intrinsics::get().call<intrinsics::db_idx256_update>(iterator, payer, data, datalen);
|
||||
return intrinsics::get().exec<intrinsics::db_idx256_update>(iterator, payer, data, datalen);
|
||||
}
|
||||
int32_t db_idx256_find_primary(capi_name code, uint64_t scope, capi_name table, uint128_t* data, uint32_t datalen, uint64_t primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx256_find_primary>(code, scope, table, data, datalen, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx256_find_primary>(code, scope, table, data, datalen, primary);
|
||||
}
|
||||
int32_t db_idx256_find_secondary(capi_name code, uint64_t scope, capi_name table, const uint128_t* data, uint32_t datalen, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx256_find_secondary>(code, scope, table, data, datalen, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx256_find_secondary>(code, scope, table, data, datalen, primary);
|
||||
}
|
||||
int32_t db_idx256_lowerbound(capi_name code, uint64_t scope, capi_name table, uint128_t* data, uint32_t datalen, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx256_lowerbound>(code, scope, table, data, datalen, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx256_lowerbound>(code, scope, table, data, datalen, primary);
|
||||
}
|
||||
int32_t db_idx256_upperbound(capi_name code, uint64_t scope, capi_name table, uint128_t* data, uint32_t datalen, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx256_upperbound>(code, scope, table, data, datalen, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx256_upperbound>(code, scope, table, data, datalen, primary);
|
||||
}
|
||||
int32_t db_idx256_end(capi_name code, uint64_t scope, capi_name table) {
|
||||
return intrinsics::get().call<intrinsics::db_idx256_end>(code, scope, table);
|
||||
return intrinsics::get().exec<intrinsics::db_idx256_end>(code, scope, table);
|
||||
}
|
||||
int32_t db_idx256_next(int32_t iterator, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx256_next>(iterator, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx256_next>(iterator, primary);
|
||||
}
|
||||
int32_t db_idx256_previous(int32_t iterator, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx256_previous>(iterator, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx256_previous>(iterator, primary);
|
||||
}
|
||||
int32_t db_idx_double_store(uint64_t scope, capi_name table, capi_name payer, uint64_t id, const double* secondary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_double_store>(scope, table, payer, id, secondary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_double_store>(scope, table, payer, id, secondary);
|
||||
}
|
||||
void db_idx_double_remove(int32_t iterator) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_double_remove>(iterator);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_double_remove>(iterator);
|
||||
}
|
||||
void db_idx_double_update(int32_t iterator, capi_name payer, const double* secondary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_double_update>(iterator, payer, secondary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_double_update>(iterator, payer, secondary);
|
||||
}
|
||||
int32_t db_idx_double_find_primary(capi_name code, uint64_t scope, capi_name table, double* secondary, uint64_t primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_double_find_primary>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_double_find_primary>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx_double_find_secondary(capi_name code, uint64_t scope, capi_name table, const double* secondary, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_double_find_secondary>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_double_find_secondary>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx_double_lowerbound(capi_name code, uint64_t scope, capi_name table, double* secondary, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_double_lowerbound>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_double_lowerbound>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx_double_upperbound(capi_name code, uint64_t scope, capi_name table, double* secondary, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_double_upperbound>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_double_upperbound>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx_double_end(capi_name code, uint64_t scope, capi_name table) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_double_end>(code, scope, table);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_double_end>(code, scope, table);
|
||||
}
|
||||
int32_t db_idx_double_next(int32_t iterator, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_double_next>(iterator, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_double_next>(iterator, primary);
|
||||
}
|
||||
int32_t db_idx_double_previous(int32_t iterator, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_double_previous>(iterator, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_double_previous>(iterator, primary);
|
||||
}
|
||||
int32_t db_idx_long_double_store(uint64_t scope, capi_name table, capi_name payer, uint64_t id, const long double* secondary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_long_double_store>(scope, table, payer, id, secondary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_long_double_store>(scope, table, payer, id, secondary);
|
||||
}
|
||||
void db_idx_long_double_remove(int32_t iterator) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_long_double_remove>(iterator);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_long_double_remove>(iterator);
|
||||
}
|
||||
void db_idx_long_double_update(int32_t iterator, capi_name payer, const long double* secondary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_long_double_update>(iterator, payer, secondary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_long_double_update>(iterator, payer, secondary);
|
||||
}
|
||||
int32_t db_idx_long_double_find_primary(capi_name code, uint64_t scope, capi_name table, long double* secondary, uint64_t primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_long_double_find_primary>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_long_double_find_primary>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx_long_double_find_secondary(capi_name code, uint64_t scope, capi_name table, const long double* secondary, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_long_double_find_secondary>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_long_double_find_secondary>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx_long_double_lowerbound(capi_name code, uint64_t scope, capi_name table, long double* secondary, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_long_double_lowerbound>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_long_double_lowerbound>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx_long_double_upperbound(capi_name code, uint64_t scope, capi_name table, long double* secondary, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_long_double_upperbound>(code, scope, table, secondary, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_long_double_upperbound>(code, scope, table, secondary, primary);
|
||||
}
|
||||
int32_t db_idx_long_double_end(capi_name code, uint64_t scope, capi_name table) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_long_double_end>(code, scope, table);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_long_double_end>(code, scope, table);
|
||||
}
|
||||
int32_t db_idx_long_double_next(int32_t iterator, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_long_double_next>(iterator, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_long_double_next>(iterator, primary);
|
||||
}
|
||||
int32_t db_idx_long_double_previous(int32_t iterator, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_idx_long_double_previous>(iterator, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_idx_long_double_previous>(iterator, primary);
|
||||
}
|
||||
int32_t db_store_i64(uint64_t scope, capi_name table, capi_name payer, uint64_t id, const void* data, uint32_t len) {
|
||||
return intrinsics::get().call<intrinsics::db_store_i64>(scope, table, payer, id, data, len);
|
||||
return intrinsics::get().exec<intrinsics::db_store_i64>(scope, table, payer, id, data, len);
|
||||
}
|
||||
void db_update_i64(int32_t iterator, capi_name payer, const void* data, uint32_t len) {
|
||||
return intrinsics::get().call<intrinsics::db_update_i64>(iterator, payer, data, len);
|
||||
return intrinsics::get().exec<intrinsics::db_update_i64>(iterator, payer, data, len);
|
||||
}
|
||||
void db_remove_i64(int32_t iterator) {
|
||||
return intrinsics::get().call<intrinsics::db_remove_i64>(iterator);
|
||||
return intrinsics::get().exec<intrinsics::db_remove_i64>(iterator);
|
||||
}
|
||||
int32_t db_get_i64(int32_t iterator, const void* data, uint32_t len) {
|
||||
return intrinsics::get().call<intrinsics::db_get_i64>(iterator, data, len);
|
||||
return intrinsics::get().exec<intrinsics::db_get_i64>(iterator, data, len);
|
||||
}
|
||||
int32_t db_next_i64(int32_t iterator, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_next_i64>(iterator, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_next_i64>(iterator, primary);
|
||||
}
|
||||
int32_t db_previous_i64(int32_t iterator, uint64_t* primary) {
|
||||
return intrinsics::get().call<intrinsics::db_previous_i64>(iterator, primary);
|
||||
return intrinsics::get().exec<intrinsics::db_previous_i64>(iterator, primary);
|
||||
}
|
||||
int32_t db_find_i64(capi_name code, uint64_t scope, capi_name table, uint64_t id) {
|
||||
return intrinsics::get().call<intrinsics::db_find_i64>(code, scope, table, id);
|
||||
return intrinsics::get().exec<intrinsics::db_find_i64>(code, scope, table, id);
|
||||
}
|
||||
int32_t db_lowerbound_i64(capi_name code, uint64_t scope, capi_name table, uint64_t id) {
|
||||
return intrinsics::get().call<intrinsics::db_lowerbound_i64>(code, scope, table, id);
|
||||
return intrinsics::get().exec<intrinsics::db_lowerbound_i64>(code, scope, table, id);
|
||||
}
|
||||
int32_t db_upperbound_i64(capi_name code, uint64_t scope, capi_name table, uint64_t id) {
|
||||
return intrinsics::get().call<intrinsics::db_upperbound_i64>(code, scope, table, id);
|
||||
return intrinsics::get().exec<intrinsics::db_upperbound_i64>(code, scope, table, id);
|
||||
}
|
||||
int32_t db_end_i64(capi_name code, uint64_t scope, capi_name table) {
|
||||
return intrinsics::get().call<intrinsics::db_end_i64>(code, scope, table);
|
||||
return intrinsics::get().exec<intrinsics::db_end_i64>(code, scope, table);
|
||||
}
|
||||
void assert_recover_key( const capi_checksum256* digest, const char* sig, size_t siglen, const char* pub, size_t publen ) {
|
||||
return intrinsics::get().call<intrinsics::assert_recover_key>(digest, sig, siglen, pub, publen);
|
||||
return intrinsics::get().exec<intrinsics::assert_recover_key>(digest, sig, siglen, pub, publen);
|
||||
}
|
||||
int recover_key( const capi_checksum256* digest, const char* sig, size_t siglen, char* pub, size_t publen ) {
|
||||
return intrinsics::get().call<intrinsics::recover_key>(digest, sig, siglen, pub, publen);
|
||||
return intrinsics::get().exec<intrinsics::recover_key>(digest, sig, siglen, pub, publen);
|
||||
}
|
||||
void assert_sha256( const char* data, uint32_t length, const capi_checksum256* hash ) {
|
||||
return intrinsics::get().call<intrinsics::assert_sha256>(data, length, hash);
|
||||
return intrinsics::get().exec<intrinsics::assert_sha256>(data, length, hash);
|
||||
}
|
||||
void assert_sha1( const char* data, uint32_t length, const capi_checksum160* hash ) {
|
||||
return intrinsics::get().call<intrinsics::assert_sha1>(data, length, hash);
|
||||
return intrinsics::get().exec<intrinsics::assert_sha1>(data, length, hash);
|
||||
}
|
||||
void assert_sha512( const char* data, uint32_t length, const capi_checksum512* hash ) {
|
||||
return intrinsics::get().call<intrinsics::assert_sha512>(data, length, hash);
|
||||
return intrinsics::get().exec<intrinsics::assert_sha512>(data, length, hash);
|
||||
}
|
||||
void assert_ripemd160( const char* data, uint32_t length, const capi_checksum160* hash ) {
|
||||
return intrinsics::get().call<intrinsics::assert_ripemd160>(data, length, hash);
|
||||
return intrinsics::get().exec<intrinsics::assert_ripemd160>(data, length, hash);
|
||||
}
|
||||
void sha256( const char* data, uint32_t length, capi_checksum256* hash ) {
|
||||
return intrinsics::get().call<intrinsics::sha256>(data, length, hash);
|
||||
return intrinsics::get().exec<intrinsics::sha256>(data, length, hash);
|
||||
}
|
||||
void sha1( const char* data, uint32_t length, capi_checksum160* hash ) {
|
||||
return intrinsics::get().call<intrinsics::sha1>(data, length, hash);
|
||||
return intrinsics::get().exec<intrinsics::sha1>(data, length, hash);
|
||||
}
|
||||
void sha512( const char* data, uint32_t length, capi_checksum512* hash ) {
|
||||
return intrinsics::get().call<intrinsics::sha512>(data, length, hash);
|
||||
return intrinsics::get().exec<intrinsics::sha512>(data, length, hash);
|
||||
}
|
||||
void ripemd160( const char* data, uint32_t length, capi_checksum160* hash ) {
|
||||
return intrinsics::get().call<intrinsics::ripemd160>(data, length, hash);
|
||||
return intrinsics::get().exec<intrinsics::ripemd160>(data, length, hash);
|
||||
}
|
||||
int32_t check_transaction_authorization( const char* trx_data, uint32_t trx_size,
|
||||
const char* pubkeys_data, uint32_t pubkeys_size,
|
||||
const char* perms_data, uint32_t perms_size
|
||||
) {
|
||||
return intrinsics::get().call<intrinsics::check_transaction_authorization>(trx_data, trx_size, pubkeys_data, pubkeys_size, perms_data, perms_size);
|
||||
return intrinsics::get().exec<intrinsics::check_transaction_authorization>(trx_data, trx_size, pubkeys_data, pubkeys_size, perms_data, perms_size);
|
||||
}
|
||||
int32_t check_permission_authorization( capi_name account, capi_name permission,
|
||||
const char* pubkeys_data, uint32_t pubkeys_size,
|
||||
const char* perms_data, uint32_t perms_size, uint64_t delay_us
|
||||
) {
|
||||
return intrinsics::get().call<intrinsics::check_permission_authorization>(account, permission, pubkeys_data, pubkeys_size, perms_data, perms_size, delay_us);
|
||||
return intrinsics::get().exec<intrinsics::check_permission_authorization>(account, permission, pubkeys_data, pubkeys_size, perms_data, perms_size, delay_us);
|
||||
}
|
||||
int64_t get_permission_last_used( capi_name account, capi_name permission ) {
|
||||
return intrinsics::get().call<intrinsics::get_permission_last_used>(account, permission);
|
||||
return intrinsics::get().exec<intrinsics::get_permission_last_used>(account, permission);
|
||||
}
|
||||
int64_t get_account_creation_time( capi_name account ) {
|
||||
return intrinsics::get().call<intrinsics::get_account_creation_time>(account);
|
||||
return intrinsics::get().exec<intrinsics::get_account_creation_time>(account);
|
||||
}
|
||||
uint64_t current_time() {
|
||||
return intrinsics::get().call<intrinsics::current_time>();
|
||||
return intrinsics::get().exec<intrinsics::current_time>();
|
||||
}
|
||||
uint64_t publication_time() {
|
||||
return intrinsics::get().call<intrinsics::publication_time>();
|
||||
return intrinsics::get().exec<intrinsics::publication_time>();
|
||||
}
|
||||
uint32_t read_action_data( void* msg, uint32_t len ) {
|
||||
return intrinsics::get().call<intrinsics::read_action_data>(msg, len);
|
||||
return intrinsics::get().exec<intrinsics::read_action_data>(msg, len);
|
||||
}
|
||||
uint32_t action_data_size() {
|
||||
return intrinsics::get().call<intrinsics::action_data_size>();
|
||||
return intrinsics::get().exec<intrinsics::action_data_size>();
|
||||
}
|
||||
capi_name current_receiver() {
|
||||
return intrinsics::get().call<intrinsics::current_receiver>();
|
||||
return intrinsics::get().exec<intrinsics::current_receiver>();
|
||||
}
|
||||
void set_action_return_value( void* rv, size_t len ) {
|
||||
intrinsics::get().call<intrinsics::set_action_return_value>(rv, len);
|
||||
intrinsics::get().exec<intrinsics::set_action_return_value>(rv, len);
|
||||
}
|
||||
void require_recipient( capi_name name ) {
|
||||
return intrinsics::get().call<intrinsics::require_recipient>(name);
|
||||
return intrinsics::get().exec<intrinsics::require_recipient>(name);
|
||||
}
|
||||
void require_auth( capi_name name ) {
|
||||
return intrinsics::get().call<intrinsics::require_auth>(name);
|
||||
return intrinsics::get().exec<intrinsics::require_auth>(name);
|
||||
}
|
||||
void require_auth2( capi_name name, capi_name permission ) {
|
||||
return intrinsics::get().call<intrinsics::require_auth2>(name, permission);
|
||||
return intrinsics::get().exec<intrinsics::require_auth2>(name, permission);
|
||||
}
|
||||
bool has_auth( capi_name name ) {
|
||||
return intrinsics::get().call<intrinsics::has_auth>(name);
|
||||
return intrinsics::get().exec<intrinsics::has_auth>(name);
|
||||
}
|
||||
bool is_account( capi_name name ) {
|
||||
return intrinsics::get().call<intrinsics::is_account>(name);
|
||||
return intrinsics::get().exec<intrinsics::is_account>(name);
|
||||
}
|
||||
size_t read_transaction(char *buffer, size_t size) {
|
||||
return intrinsics::get().call<intrinsics::read_transaction>(buffer, size);
|
||||
return intrinsics::get().exec<intrinsics::read_transaction>(buffer, size);
|
||||
}
|
||||
size_t transaction_size() {
|
||||
return intrinsics::get().call<intrinsics::transaction_size>();
|
||||
return intrinsics::get().exec<intrinsics::transaction_size>();
|
||||
}
|
||||
uint32_t expiration() {
|
||||
return intrinsics::get().call<intrinsics::expiration>();
|
||||
return intrinsics::get().exec<intrinsics::expiration>();
|
||||
}
|
||||
int tapos_block_prefix() {
|
||||
return intrinsics::get().call<intrinsics::tapos_block_prefix>();
|
||||
return intrinsics::get().exec<intrinsics::tapos_block_prefix>();
|
||||
}
|
||||
int tapos_block_num() {
|
||||
return intrinsics::get().call<intrinsics::tapos_block_num>();
|
||||
return intrinsics::get().exec<intrinsics::tapos_block_num>();
|
||||
}
|
||||
int get_action( uint32_t type, uint32_t index, char* buff, size_t size ) {
|
||||
return intrinsics::get().call<intrinsics::get_action>(type, index, buff, size);
|
||||
return intrinsics::get().exec<intrinsics::get_action>(type, index, buff, size);
|
||||
}
|
||||
void send_inline(char *serialized_action, size_t size) {
|
||||
return intrinsics::get().call<intrinsics::send_inline>(serialized_action, size);
|
||||
return intrinsics::get().exec<intrinsics::send_inline>(serialized_action, size);
|
||||
}
|
||||
void send_context_free_inline(char *serialized_action, size_t size) {
|
||||
return intrinsics::get().call<intrinsics::send_context_free_inline>(serialized_action, size);
|
||||
return intrinsics::get().exec<intrinsics::send_context_free_inline>(serialized_action, size);
|
||||
}
|
||||
void send_deferred(const uint128_t* sender_id, capi_name payer, const char *serialized_transaction, size_t size, uint32_t replace_existing) {
|
||||
return intrinsics::get().call<intrinsics::send_deferred>(sender_id, payer, serialized_transaction, size, replace_existing);
|
||||
return intrinsics::get().exec<intrinsics::send_deferred>(sender_id, payer, serialized_transaction, size, replace_existing);
|
||||
}
|
||||
int cancel_deferred(const uint128_t* sender_id) {
|
||||
return intrinsics::get().call<intrinsics::cancel_deferred>(sender_id);
|
||||
return intrinsics::get().exec<intrinsics::cancel_deferred>(sender_id);
|
||||
}
|
||||
int get_context_free_data( uint32_t index, char* buff, size_t size ) {
|
||||
return intrinsics::get().call<intrinsics::get_context_free_data>(index, buff, size);
|
||||
return intrinsics::get().exec<intrinsics::get_context_free_data>(index, buff, size);
|
||||
}
|
||||
capi_name get_sender() {
|
||||
return intrinsics::get().call<intrinsics::get_sender>();
|
||||
return intrinsics::get().exec<intrinsics::get_sender>();
|
||||
}
|
||||
int64_t call(capi_name receiver, uint64_t flags, const char* data, size_t data_size) {
|
||||
return intrinsics::get().exec<intrinsics::call>(receiver, flags, data, data_size);
|
||||
}
|
||||
uint32_t get_call_return_value(void* mem, uint32_t len) {
|
||||
return intrinsics::get().exec<intrinsics::get_call_return_value>(mem, len);
|
||||
}
|
||||
uint32_t get_call_data(void* mem, uint32_t len) {
|
||||
return intrinsics::get().exec<intrinsics::get_call_data>(mem, len);
|
||||
}
|
||||
void set_call_return_value(void* mem, uint32_t len) {
|
||||
return intrinsics::get().exec<intrinsics::set_call_return_value>(mem, len);
|
||||
}
|
||||
|
||||
// softfloat
|
||||
@@ -786,47 +798,47 @@ extern "C" {
|
||||
}
|
||||
|
||||
void prints_l(const char* cstr, uint32_t len) {
|
||||
return intrinsics::get().call<intrinsics::prints_l>(cstr, len);
|
||||
return intrinsics::get().exec<intrinsics::prints_l>(cstr, len);
|
||||
}
|
||||
|
||||
void prints(const char* cstr) {
|
||||
return intrinsics::get().call<intrinsics::prints>(cstr);
|
||||
return intrinsics::get().exec<intrinsics::prints>(cstr);
|
||||
}
|
||||
|
||||
void printi(int64_t value) {
|
||||
return intrinsics::get().call<intrinsics::printi>(value);
|
||||
return intrinsics::get().exec<intrinsics::printi>(value);
|
||||
}
|
||||
|
||||
void printui(uint64_t value) {
|
||||
return intrinsics::get().call<intrinsics::printui>(value);
|
||||
return intrinsics::get().exec<intrinsics::printui>(value);
|
||||
}
|
||||
|
||||
void printi128(const int128_t* value) {
|
||||
return intrinsics::get().call<intrinsics::printi128>(value);
|
||||
return intrinsics::get().exec<intrinsics::printi128>(value);
|
||||
}
|
||||
|
||||
void printui128(const uint128_t* value) {
|
||||
return intrinsics::get().call<intrinsics::printui128>(value);
|
||||
return intrinsics::get().exec<intrinsics::printui128>(value);
|
||||
}
|
||||
|
||||
void printsf(float value) {
|
||||
return intrinsics::get().call<intrinsics::printsf>(value);
|
||||
return intrinsics::get().exec<intrinsics::printsf>(value);
|
||||
}
|
||||
|
||||
void printdf(double value) {
|
||||
return intrinsics::get().call<intrinsics::printdf>(value);
|
||||
return intrinsics::get().exec<intrinsics::printdf>(value);
|
||||
}
|
||||
|
||||
void printqf(const long double* value) {
|
||||
return intrinsics::get().call<intrinsics::printqf>(value);
|
||||
return intrinsics::get().exec<intrinsics::printqf>(value);
|
||||
}
|
||||
|
||||
void printn(uint64_t nm) {
|
||||
return intrinsics::get().call<intrinsics::printn>(nm);
|
||||
return intrinsics::get().exec<intrinsics::printn>(nm);
|
||||
}
|
||||
|
||||
void printhex(const void* data, uint32_t len) {
|
||||
return intrinsics::get().call<intrinsics::printhex>(data, len);
|
||||
return intrinsics::get().exec<intrinsics::printhex>(data, len);
|
||||
}
|
||||
|
||||
void* memset ( void* ptr, int value, size_t num ) {
|
||||
@@ -890,49 +902,87 @@ extern "C" {
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
int64_t add_security_group_participants(const char* data, uint32_t datalen) {
|
||||
return intrinsics::get().call<intrinsics::add_security_group_participants>(data, datalen);
|
||||
void set_finalizers(uint64_t packed_finalizer_format, const char* data, uint32_t len) {
|
||||
intrinsics::get().exec<intrinsics::set_finalizers>(packed_finalizer_format, data, len);
|
||||
}
|
||||
|
||||
int64_t remove_security_group_participants(const char* data, uint32_t datalen){
|
||||
return intrinsics::get().call<intrinsics::remove_security_group_participants>(data, datalen);
|
||||
}
|
||||
|
||||
bool in_active_security_group(const char* data, uint32_t datalen){
|
||||
return intrinsics::get().call<intrinsics::in_active_security_group>(data, datalen);
|
||||
}
|
||||
|
||||
uint32_t get_active_security_group(char* data, uint32_t datalen){
|
||||
return intrinsics::get().call<intrinsics::get_active_security_group>(data, datalen);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
int32_t blake2_f( uint32_t rounds, const char* state, uint32_t state_len, const char* msg, uint32_t msg_len,
|
||||
const char* t0_offset, uint32_t t0_len, const char* t1_offset, uint32_t t1_len, int32_t final, char* result, uint32_t result_len) {
|
||||
return intrinsics::get().call<intrinsics::blake2_f>(rounds, state, state_len, msg, msg_len, t0_offset, t0_len, t1_offset, t1_len, final, result, result_len);
|
||||
return intrinsics::get().exec<intrinsics::blake2_f>(rounds, state, state_len, msg, msg_len, t0_offset, t0_len, t1_offset, t1_len, final, result, result_len);
|
||||
}
|
||||
|
||||
int32_t k1_recover( const char* sig, uint32_t sig_len, const char* dig, uint32_t dig_len, char* pub, uint32_t pub_len) {
|
||||
return intrinsics::get().call<intrinsics::k1_recover>(sig, sig_len, dig, dig_len, pub, pub_len);
|
||||
return intrinsics::get().exec<intrinsics::k1_recover>(sig, sig_len, dig, dig_len, pub, pub_len);
|
||||
}
|
||||
|
||||
int32_t alt_bn128_add( const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* result, uint32_t result_len) {
|
||||
return intrinsics::get().call<intrinsics::alt_bn128_add>(op1, op1_len, op2, op2_len, result, result_len);
|
||||
return intrinsics::get().exec<intrinsics::alt_bn128_add>(op1, op1_len, op2, op2_len, result, result_len);
|
||||
}
|
||||
|
||||
int32_t alt_bn128_mul( const char* g1, uint32_t g1_len, const char* scalar, uint32_t scalar_len, char* result, uint32_t result_len) {
|
||||
return intrinsics::get().call<intrinsics::alt_bn128_mul>(g1, g1_len, scalar, scalar_len, result, result_len);
|
||||
return intrinsics::get().exec<intrinsics::alt_bn128_mul>(g1, g1_len, scalar, scalar_len, result, result_len);
|
||||
}
|
||||
|
||||
int32_t alt_bn128_pair( const char* pairs, uint32_t pairs_len) {
|
||||
return intrinsics::get().call<intrinsics::alt_bn128_pair>(pairs, pairs_len);
|
||||
return intrinsics::get().exec<intrinsics::alt_bn128_pair>(pairs, pairs_len);
|
||||
}
|
||||
|
||||
int32_t mod_exp( const char* base, uint32_t base_len, const char* exp, uint32_t exp_len, const char* mod, uint32_t mod_len, char* result, uint32_t result_len) {
|
||||
return intrinsics::get().call<intrinsics::mod_exp>(base, base_len, exp, exp_len, mod, mod_len, result, result_len);
|
||||
return intrinsics::get().exec<intrinsics::mod_exp>(base, base_len, exp, exp_len, mod, mod_len, result, result_len);
|
||||
}
|
||||
|
||||
void sha3( const char* data, uint32_t data_len, char* hash, uint32_t hash_len, int32_t keccak ) {
|
||||
intrinsics::get().call<intrinsics::sha3>(data, data_len, hash, hash_len, keccak);
|
||||
}
|
||||
intrinsics::get().exec<intrinsics::sha3>(data, data_len, hash, hash_len, keccak);
|
||||
}
|
||||
|
||||
int32_t bls_g1_add(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len)
|
||||
{
|
||||
return intrinsics::get().exec<intrinsics::bls_g1_add>(op1, op1_len, op2, op2_len, res, res_len);
|
||||
}
|
||||
|
||||
int32_t bls_g2_add(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len)
|
||||
{
|
||||
return intrinsics::get().exec<intrinsics::bls_g2_add>(op1, op1_len, op2, op2_len, res, res_len);
|
||||
}
|
||||
|
||||
int32_t bls_g1_weighted_sum(const char* points, uint32_t points_len, const char* scalars, uint32_t scalars_len, uint32_t n, char* res, uint32_t res_len)
|
||||
{
|
||||
return intrinsics::get().exec<intrinsics::bls_g1_weighted_sum>(points, points_len, scalars, scalars_len, n, res, res_len);
|
||||
}
|
||||
|
||||
int32_t bls_g2_weighted_sum(const char* points, uint32_t points_len, const char* scalars, uint32_t scalars_len, uint32_t n, char* res, uint32_t res_len)
|
||||
{
|
||||
return intrinsics::get().exec<intrinsics::bls_g2_weighted_sum>(points, points_len, scalars, scalars_len, n, res, res_len);
|
||||
}
|
||||
|
||||
int32_t bls_pairing(const char* g1_points, uint32_t g1_points_len, const char* g2_points, uint32_t g2_points_len, uint32_t n, char* res, uint32_t res_len)
|
||||
{
|
||||
return intrinsics::get().exec<intrinsics::bls_pairing>(g1_points, g1_points_len, g1_points, g1_points_len, n, res, res_len);
|
||||
}
|
||||
|
||||
int32_t bls_g1_map(const char* e, uint32_t e_len, char* res, uint32_t res_len)
|
||||
{
|
||||
return intrinsics::get().exec<intrinsics::bls_g1_map>(e, e_len, res, res_len);
|
||||
}
|
||||
|
||||
int32_t bls_g2_map(const char* e, uint32_t e_len, char* res, uint32_t res_len)
|
||||
{
|
||||
return intrinsics::get().exec<intrinsics::bls_g2_map>(e, e_len, res, res_len);
|
||||
}
|
||||
|
||||
int32_t bls_fp_mod(const char* s, uint32_t s_len, char* res, uint32_t res_len)
|
||||
{
|
||||
return intrinsics::get().exec<intrinsics::bls_fp_mod>(s, s_len, res, res_len);
|
||||
}
|
||||
|
||||
int32_t bls_fp_mul(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len)
|
||||
{
|
||||
return intrinsics::get().exec<intrinsics::bls_fp_mul>(op1, op1_len, op2, op2_len, res, res_len);
|
||||
}
|
||||
|
||||
int32_t bls_fp_exp(const char* base, uint32_t base_len, const char* exp, uint32_t exp_len, char* res, uint32_t res_len)
|
||||
{
|
||||
return intrinsics::get().exec<intrinsics::bls_fp_exp>(base, base_len, exp, exp_len, res, res_len);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace eosio { namespace native {
|
||||
};
|
||||
|
||||
template <intrinsic_name IN, typename... Args>
|
||||
auto call(Args... args) -> decltype(std::get<IN>(intrinsics::get().funcs)(args...)) {
|
||||
auto exec(Args... args) -> decltype(std::get<IN>(intrinsics::get().funcs)(args...)) {
|
||||
return std::get<IN>(intrinsics::get().funcs)(args...);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,14 +4,16 @@
|
||||
#include <eosio/chain.h>
|
||||
#include <eosio/crypto.h>
|
||||
#include <eosio/crypto_ext.h>
|
||||
#include <eosio/crypto_bls_ext.h>
|
||||
#include <eosio/db.h>
|
||||
#include <eosio/instant_finality.h>
|
||||
#include <eosio/call.h>
|
||||
#include <eosio/permission.h>
|
||||
#include <eosio/print.h>
|
||||
#include <eosio/privileged.h>
|
||||
#include <eosio/system.h>
|
||||
#include <eosio/transaction.h>
|
||||
#include <eosio/types.h>
|
||||
#include <eosio/security_group.h>
|
||||
|
||||
#include <type_traits>
|
||||
#include <functional>
|
||||
@@ -162,19 +164,28 @@ intrinsic_macro(cancel_deferred) \
|
||||
intrinsic_macro(get_context_free_data) \
|
||||
intrinsic_macro(get_sender) \
|
||||
intrinsic_macro(set_action_return_value) \
|
||||
intrinsic_macro(add_security_group_participants) \
|
||||
intrinsic_macro(remove_security_group_participants) \
|
||||
intrinsic_macro(in_active_security_group) \
|
||||
intrinsic_macro(get_active_security_group) \
|
||||
intrinsic_macro(blake2_f) \
|
||||
intrinsic_macro(sha3) \
|
||||
intrinsic_macro(k1_recover) \
|
||||
intrinsic_macro(alt_bn128_add) \
|
||||
intrinsic_macro(alt_bn128_mul) \
|
||||
intrinsic_macro(alt_bn128_pair) \
|
||||
intrinsic_macro(mod_exp)
|
||||
|
||||
|
||||
intrinsic_macro(mod_exp) \
|
||||
intrinsic_macro(bls_g1_add) \
|
||||
intrinsic_macro(bls_g2_add) \
|
||||
intrinsic_macro(bls_g1_weighted_sum) \
|
||||
intrinsic_macro(bls_g2_weighted_sum) \
|
||||
intrinsic_macro(bls_pairing) \
|
||||
intrinsic_macro(bls_g1_map) \
|
||||
intrinsic_macro(bls_g2_map) \
|
||||
intrinsic_macro(bls_fp_mod) \
|
||||
intrinsic_macro(bls_fp_mul) \
|
||||
intrinsic_macro(bls_fp_exp) \
|
||||
intrinsic_macro(set_finalizers) \
|
||||
intrinsic_macro(call) \
|
||||
intrinsic_macro(get_call_return_value) \
|
||||
intrinsic_macro(get_call_data) \
|
||||
intrinsic_macro(set_call_return_value)
|
||||
|
||||
#define CREATE_ENUM(name) \
|
||||
name,
|
||||
|
||||
@@ -16,9 +16,9 @@ ExternalProject_Add(
|
||||
)
|
||||
|
||||
|
||||
find_package(leap QUIET)
|
||||
find_package(spring QUIET)
|
||||
|
||||
if (leap_FOUND)
|
||||
if (spring_FOUND)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(TEST_BUILD_TYPE "Debug")
|
||||
else()
|
||||
@@ -32,7 +32,7 @@ if (leap_FOUND)
|
||||
CDTIntegrationTests
|
||||
SOURCE_DIR "${CMAKE_SOURCE_DIR}/tests/integration"
|
||||
BINARY_DIR "${CMAKE_BINARY_DIR}/tests/integration"
|
||||
CMAKE_ARGS -DCMAKE_BUILD_TYPE=${TEST_BUILD_TYPE} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_FRAMEWORK_PATH=${TEST_FRAMEWORK_PATH} -DCMAKE_MODULE_PATH=${TEST_MODULE_PATH} -Deosio_DIR=${eosio_DIR} -DLLVM_DIR=${LLVM_DIR} -DBOOST_ROOT=${BOOST_ROOT}
|
||||
CMAKE_ARGS -DCMAKE_BUILD_TYPE=${TEST_BUILD_TYPE} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_FRAMEWORK_PATH=${TEST_FRAMEWORK_PATH} -DCMAKE_MODULE_PATH=${TEST_MODULE_PATH} -Dspring_DIR=${spring_DIR} -Deosio_DIR=${eosio_DIR} -DLLVM_DIR=${LLVM_DIR} -DBOOST_ROOT=${BOOST_ROOT}
|
||||
UPDATE_COMMAND ""
|
||||
PATCH_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
@@ -40,5 +40,5 @@ if (leap_FOUND)
|
||||
BUILD_ALWAYS 1
|
||||
)
|
||||
else()
|
||||
message(STATUS "leap package not found, skipping building integration tests")
|
||||
message(STATUS "spring package not found, skipping building integration tests")
|
||||
endif()
|
||||
|
||||
@@ -4,6 +4,7 @@ macro(add_unit_test TEST_NAME)
|
||||
endmacro()
|
||||
|
||||
add_unit_test( asset_tests )
|
||||
add_unit_test( base64_tests )
|
||||
add_unit_test( binary_extension_tests )
|
||||
add_unit_test( crt_tests )
|
||||
add_unit_test( crypto_tests )
|
||||
@@ -28,7 +29,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/unit/version_tests.sh ${CMAKE_BINARY_
|
||||
add_test(NAME version_tests COMMAND ${CMAKE_BINARY_DIR}/tests/unit/version_tests.sh "${VERSION_FULL}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set_property(TEST version_tests PROPERTY LABELS unit_tests)
|
||||
|
||||
if (leap_FOUND)
|
||||
if (spring_FOUND)
|
||||
add_test(integration_tests ${CMAKE_BINARY_DIR}/tests/integration/integration_tests)
|
||||
set_property(TEST integration_tests PROPERTY LABELS integration_tests)
|
||||
endif()
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
cmake_minimum_required( VERSION 3.5 )
|
||||
|
||||
set(EOSIO_VERSION_MIN "3.1")
|
||||
set(EOSIO_VERSION_MIN "1.0")
|
||||
set(EOSIO_VERSION_SOFT_MAX "5.0")
|
||||
#set(EOSIO_VERSION_HARD_MAX "")
|
||||
|
||||
find_package(leap)
|
||||
find_package(spring)
|
||||
|
||||
find_path(GMP_INCLUDE_DIR NAMES gmp.h)
|
||||
find_library(GMP_LIBRARY gmp)
|
||||
@@ -17,11 +17,11 @@ EOSIO_CHECK_VERSION(VERSION_OUTPUT "${EOSIO_VERSION}"
|
||||
"${EOSIO_VERSION_HARD_MAX}"
|
||||
VERSION_MATCH_ERROR_MSG)
|
||||
if(VERSION_OUTPUT STREQUAL "MATCH")
|
||||
message(STATUS "Using Leap version ${EOSIO_VERSION}")
|
||||
message(STATUS "Using Spring version ${EOSIO_VERSION}")
|
||||
elseif(VERSION_OUTPUT STREQUAL "WARN")
|
||||
message(WARNING "Using Leap version ${EOSIO_VERSION} even though it exceeds the maximum supported version of ${EOSIO_VERSION_SOFT_MAX}; continuing with configuration, however build may fail.\nIt is recommended to use Leap version ${EOSIO_VERSION_SOFT_MAX}.x")
|
||||
message(WARNING "Using Spring version ${EOSIO_VERSION} even though it exceeds the maximum supported version of ${EOSIO_VERSION_SOFT_MAX}; continuing with configuration, however build may fail.\nIt is recommended to use Spring version ${EOSIO_VERSION_SOFT_MAX}.x")
|
||||
else() # INVALID OR MISMATCH
|
||||
message(FATAL_ERROR "Found Leap version ${EOSIO_VERSION} but it does not satisfy version requirements: ${VERSION_MATCH_ERROR_MSG}\nPlease use Leap version ${EOSIO_VERSION_SOFT_MAX}.x")
|
||||
message(FATAL_ERROR "Found Spring version ${EOSIO_VERSION} but it does not satisfy version requirements: ${VERSION_MATCH_ERROR_MSG}\nPlease use Spring version ${EOSIO_VERSION_SOFT_MAX}.x")
|
||||
endif(VERSION_OUTPUT STREQUAL "MATCH")
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <eosio/testing/tester.hpp>
|
||||
#include <eosio/chain/abi_serializer.hpp>
|
||||
|
||||
#include <fc/variant_object.hpp>
|
||||
|
||||
#include <contracts.hpp>
|
||||
|
||||
using namespace eosio;
|
||||
using namespace eosio::testing;
|
||||
using namespace eosio::chain;
|
||||
using namespace eosio::testing;
|
||||
using namespace fc;
|
||||
|
||||
using mvo = fc::mutable_variant_object;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(array_tests)
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( std_array_param, tester ) try {
|
||||
/* ----------- testpa action tests --------------------------------------------------
|
||||
[[eosio::action]]
|
||||
void testpa(std::array<int,4> input){
|
||||
std::array<int,4> arr = input;
|
||||
for(int i = 0; i < 4; ++i){
|
||||
eosio::cout << arr[i] << " ";
|
||||
}
|
||||
eosio::cout << "\n";
|
||||
}
|
||||
-------------------------------------------------------------------------------------- */
|
||||
create_accounts( { "test"_n } );
|
||||
produce_block();
|
||||
set_code( "test"_n, contracts::array_tests_wasm() );
|
||||
set_abi( "test"_n, contracts::array_tests_abi().data() );
|
||||
produce_blocks();
|
||||
|
||||
auto trace = push_action("test"_n, "testpa"_n, "test"_n, mvo()("input", {1,2,3,4}));
|
||||
auto& con = trace->action_traces[0].console;
|
||||
BOOST_REQUIRE_EQUAL(con, std::string("1 2 3 4 \n"));
|
||||
produce_block();
|
||||
|
||||
// size should be correct
|
||||
// ----------------------
|
||||
BOOST_CHECK_EXCEPTION( push_action("test"_n, "testpa"_n, "test"_n, mvo()("input", {1,2,3})),
|
||||
pack_exception,
|
||||
fc_exception_message_starts_with("Incorrect number of values provided (4) for fixed-size (3) array type"));
|
||||
|
||||
produce_block();
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( std_array_return_value, tester ) try {
|
||||
/* ----------- testre action tests --------------------------------------------------
|
||||
[[eosio::action]]
|
||||
std::array<int,4> testre(std::array<int,4> input){
|
||||
std::array<int,4> arr = input;
|
||||
for(auto & v : arr) v += 1;
|
||||
return arr;
|
||||
}
|
||||
-------------------------------------------------------------------------------------- */
|
||||
create_accounts( { "test"_n } );
|
||||
produce_block();
|
||||
set_code( "test"_n, contracts::array_tests_wasm() );
|
||||
set_abi( "test"_n, contracts::array_tests_abi().data() );
|
||||
produce_blocks();
|
||||
|
||||
auto trace = push_action("test"_n, "testre"_n, "test"_n, mvo()("input", {1, 2, 3, 4}));
|
||||
auto& rv = trace->action_traces[0].return_value;
|
||||
auto actual = fc::raw::unpack<std::array<int, 4>>(rv);
|
||||
auto expected = std::array<int, 4>{2, 3, 4, 5};
|
||||
BOOST_REQUIRE(actual == expected);
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( std_vector_return_value, tester ) try {
|
||||
/* ----------- testrev action tests --------------------------------------------------
|
||||
[[eosio::action]]
|
||||
std::vector<int> testrev(std::vector<int> input){
|
||||
std::vector<int> vec = input;
|
||||
for(auto & v : vec) v += 1;
|
||||
return vec;
|
||||
}
|
||||
-------------------------------------------------------------------------------------- */
|
||||
create_accounts( { "test"_n } );
|
||||
produce_block();
|
||||
set_code( "test"_n, contracts::array_tests_wasm() );
|
||||
set_abi( "test"_n, contracts::array_tests_abi().data() );
|
||||
produce_blocks();
|
||||
|
||||
auto trace = push_action("test"_n, "testrev"_n, "test"_n, mvo()("input", {1, 2, 3, 4}));
|
||||
auto& rv = trace->action_traces[0].return_value;
|
||||
auto actual = fc::raw::unpack<std::vector<int>>(rv);
|
||||
auto expected = std::vector<int>{2, 3, 4, 5};
|
||||
BOOST_REQUIRE(actual == expected);
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -0,0 +1,47 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <eosio/testing/tester.hpp>
|
||||
#include <eosio/chain/abi_serializer.hpp>
|
||||
|
||||
#include <fc/variant_object.hpp>
|
||||
|
||||
#include <contracts.hpp>
|
||||
#include "test_utils.hpp"
|
||||
|
||||
using namespace eosio;
|
||||
using namespace eosio::testing;
|
||||
using namespace eosio::chain;
|
||||
using namespace eosio::testing;
|
||||
using namespace fc;
|
||||
|
||||
using mvo = fc::mutable_variant_object;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(bitset_tests)
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( bitset_test, tester ) try {
|
||||
create_accounts( { "test"_n } );
|
||||
produce_block();
|
||||
set_code( "test"_n, contracts::simple_wasm() );
|
||||
set_abi( "test"_n, contracts::simple_abi().data() );
|
||||
produce_blocks();
|
||||
|
||||
auto trx_trace = push_action("test"_n, "testbs"_n, "test"_n, mvo()("b", "0010"));
|
||||
auto& act_trace = trx_trace->action_traces[0];
|
||||
BOOST_REQUIRE_EQUAL(fc::raw::unpack<fc::bitset>(act_trace.return_value), fc::bitset{"1101"});
|
||||
|
||||
{
|
||||
// because contract `simple_tests.cpp` uses the `bitset` type, the abi version should be 1.3 or greater
|
||||
auto abi_version = extract_version_from_json_abi(contracts::simple_abi());
|
||||
BOOST_REQUIRE(abi_version.is_valid());
|
||||
BOOST_REQUIRE_LT(version_t(1,2), abi_version);
|
||||
}
|
||||
|
||||
{
|
||||
// check that abi version of minimal contract is still 1.2.
|
||||
auto abi_version = extract_version_from_json_abi(contracts::malloc_tests_abi());
|
||||
BOOST_REQUIRE(abi_version.is_valid());
|
||||
BOOST_REQUIRE_EQUAL(version_t(1,2), abi_version);
|
||||
}
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -0,0 +1,143 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <eosio/testing/tester.hpp>
|
||||
#include <eosio/chain/abi_serializer.hpp>
|
||||
|
||||
#include <fc/variant_object.hpp>
|
||||
|
||||
#include <contracts.hpp>
|
||||
|
||||
using namespace eosio;
|
||||
using namespace eosio::testing;
|
||||
using namespace eosio::chain;
|
||||
using namespace eosio::testing;
|
||||
using namespace fc;
|
||||
|
||||
using mvo = fc::mutable_variant_object;
|
||||
|
||||
struct bls_primitives_tester : tester {
|
||||
bls_primitives_tester() {
|
||||
create_accounts( { "test"_n } );
|
||||
produce_block();
|
||||
|
||||
set_code( "eosio"_n, contracts::bls_primitives_test_wasm() );
|
||||
set_abi( "eosio"_n, contracts::bls_primitives_test_abi().data() );
|
||||
|
||||
produce_blocks();
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(bls_primitives_tests)
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( g1_add_test, bls_primitives_tester ) try {
|
||||
push_action("eosio"_n, "testg1add"_n, "test"_n, mvo()
|
||||
("op1", "aa83970268d80b50a68535d920954bd993217b9114cbe255e5c0b64e748c5683b6518071552148ec555cdb8fed0f07001e76e62761e8d828a74b81f216a0c5ebeb923550cafd110512cec20e33ec9b272c0ff2b88215953945153fc926691506")
|
||||
("op2", "e810c1d6ac7cbae0157a0fc958ef607c33e03dee20e72a97ae72de0dd9a0ef20d768ab4b659429255b87feda0be194062a77cd664976e6560b33c921d5968c19a5d5ae9e38c909690975c084c0a4e82481b01e4023b83d6a8ddcb9d38892f50f")
|
||||
("res", "145cae227562a69bbf270b8ec8d1783bed4ad0fd43e9c81ac5caa7d3e7feaa3acda07d6033ece1f7f0649d6b75009a03e83ab8f9b44f94c4ab762611266b7a530ce05092ad38b7554a95caa2b63ad0969a902d69f34531dbccf8a4f2e12cf60d"));
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( g2_add_test, bls_primitives_tester ) try {
|
||||
push_action("eosio"_n, "testg2add"_n, "test"_n, mvo()
|
||||
("op1", "a75a447bc0dd806bcdaee2cb429498193e409a4d370dfe0e9605c5a9ec4a09c0314c0321f2f918b72e5f37cf10ea7e0b69ac1a7fb3200e63e5cef9929cd2d9afde2fb957989e610c5b44649af8649d968baa0424b873b501be32c66ef040240b469127753f17ca28a072c2151b69d51fecff1ed0f4786b4e6fd4e52ec72f95ef73cf19fc2d6a28267bdf11a262b403110c2e901fb32d0e900082e4934a20c1c06c262533488fd7f9f47e4e2fde102fe98fb48344de25712d5e2e2887bc04d207")
|
||||
("op2", "11cc3115ad08c43ed0b7fc3945ca83c69d0a6663f05b25373ea3fdff14c722a7fddd7a1b4f1cf44290e1c480f50b6208419f6a208ea48a48cef5a345a35c052cf0db4a76c719eb90a5829a8f606e99c807a6ae71493f079c364d57f02cba7c124f344978bb539bea7c448eb96ccea9b6c7b7d2495212b88227fc269ac88391f4a6d23e2d47d4fe47e63f8e709b61450644ba13c08e29770bc397da41466cb26c9fa7a1ffd9b5dd5c51c3ddbfb88412998e41f72e63b7972dfd856b9f11530c01")
|
||||
("res", "d9458632a7cfcf59e72cf6d1ad70ec8d65d9e81edd0da77c2b10ec4d2a4169f1b0ac46419796d3ed6ef66b34eb76651288d916a5e5b44e75cc849ecd257a223398f92683f2318bf5fe7aa2b5d45e97dad6c415dac4b9cdc1c72071a4c9845c15096b203deb2e071d3856983cb26a101eb193cbfe914000ade94a62339b2e418c4a53578fb177af1986cc9dee3ce9ff0f9598925cb7e5a29af31404fa8cd9c22e17eb1a44b6b461dd9b7dc4d384ad60b82d94e431a389a244b1724a5441ac6009"));
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( g1_weighted_sum_test, bls_primitives_tester ) try {
|
||||
push_action("eosio"_n, "testg1wsum"_n, "test"_n, mvo()
|
||||
("points", "7a63674c35f9f2be4f0ec092110b82fad24a283316a846d960843b9a6a8a98bfdabd7e897b7da774fbbb05d7ad95fb18940a5f7a7345e1821e0203e156d677e88445385bc0779d25f51b772be3c3a6ba0b09b2533a8ee66053b2f3c853994112e74a97324685e515c86d44ff5a3ef5218e53c6f29e7df49a546c79cd1fb9d14e63f68aaf6b2df1f6f56e6250fdd6f20dcc36499a5aea69f4c77a18774eccf8460e77ab6b0236ce2d85083faeacf0f3378a3dcc95e1d3b0ae282b9bbec1ecee1793e63ca4730ec63df496546c07094e848625610a514d99dd0a6dd9f58d15c4e4ed5aca65025562177ebd0a4c2c3ae8139d24be936dd5dbec6a54897ba2a98a68a9c43ea3199695896789c958bc289a7275550b5670a351b262c10166a48baa161f841df4255408abb7186f78647422313fbe3a0a35699a487dd71482b76b8adc20622f44bb32e04a78b98e4f2cd42f16a6d35ec2463a484906dbb655969b900a15cc8a47694b1961bd4b2e9f074afd79e4c04344d31dd8fcd56d5147a9a47712")
|
||||
("scalars", "2be3984dc7a5c9e6172df42c905be929ce5bb29d9aa31a03f3ed8816e7d1265a0669a674fef9254f0efffd3e89c30f1f05587472251d362e1acea03a76918d137b322778b8188c1bf68c36ef8e0ce933290c67f981611c13a286e42235f89855e49966a4e9ad8c64122f4f5e720986193e59771fa91aef113d8739642bdd6613")
|
||||
("num", 4)
|
||||
("res", "25038aea2d2d1c15dad2fa4c6e31162d1b79ca1b1bca608190a05dea451701e9fc95a8c441a25083df7fa56d54eae51241a8c9489719b9cc35852ce3d7e04b5ada5c65f45d1818f80ea161264b70ab6fa86e694691281b8110000d209aea5c17"));
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( g2_weighted_sum_test, bls_primitives_tester ) try {
|
||||
push_action("eosio"_n, "testg2wsum"_n, "test"_n, mvo()
|
||||
("points", "556524e3e80fcf448c0befd659ad744c409cdd1111291a81949324a02688999ab88e6ccb3e9dcecf57ccfe9aa7ada21540ba5407c0700ce81578bcee892ed385dd1ed476c465fe48cea2dd7e37784d8ae795fba842ce0f88baa76857ec1c7c137163beed84ff2c6a159d486d10c7128b2cbb6f10c547d202d0f6e68fb43a9a6a18a01823c4e70b5dc25d38b9c33d4916510de467f10922f3b284855c4accc816f542fe74fd0b331b1884dac6918d3c38860b0725809a19b6101e5d3942b9f40eee6901e17a0c50187e6385767b7d1e54eaacbb3c1939e2e995ec79569dd0200583a937891035475e1e5a733a0446f7063e77f9d564c60dfc6dc25572369bf7fe51b2607f73fd0fa9eee9d27b127a81c63bbd7f08dd64237d082e9735018d96024c56d32b55e991e84f39c6ffc0d56ef17307e82fc200df9259f83b7bdae719124f7151d855b8f51f703e087ea1540900c4eba1592de051db895689aeb5233dec52ccb74f93acc8fc14bcde4413a14dceb0ec386623021ddf9ad1fce429e1780c5a6877b00b17af384fd49b7077434387672218967f4a7647174162c07e99d9007380be10a7bef367181ba886a0e40c160a4b36548826c30710ea8238b0c37ec06e331fe1d3aaf1b5a73ae0880794d0c0a9623b8498d9bbd4754e1a8c1e2346091fec42aaeddc40f2ae06456e8ad9059c61db437089a855af3d1bc2a6d68e9c01474bdbaabfa185a58dba9808f8e0b20a3c51c51c5bca629aa061dfa5ff238a43e1e90242df403635869743c723276c0eca711c6c91b94a65310b6b869ee556179ed113a2b406a52de2fe54f61f4589f510924b2e3f8b14ead1541af2e1cc9dd35a91f6cd4bbc02c58a844d9e4906a106197b8ab39a539561aeecd265762bcf5106344ae2fe0a62c7af1bbc846e9b39ebe38a046461d7c0c4901caddb0fd7c70b86246d53bf3124af629596f6367e86f3456cc954e3581bfea600b6d2818259332fedeb88ece673626ffd4d5935d0310e5cf2462055d5fa4b6cc4531f11cf0722c8647dbfc7364c9b2e24e0066ef5b0e3497ce38537a7230e02f7edc2f53e980f")
|
||||
("scalars", "e5a6afde5d144ed43bd1742b7ec7f5385a7d392f65465927e37afe7b9f0a9e368449cf52e36ca432b096f8562c98f318216d21a426b2d51f0a4db8fcafcd687326b548cd973f30d4fc47d79d853ec94239c620229ea0632b2570a1f8df08fe1ce323ef2cad610917a13d1157e25fac05ef6bafaa68e8ce265594d207a5d13c1e")
|
||||
("num", 4)
|
||||
("res", "889d8b750987cbce4aa4b872b29f22011752354e672b24ad4b229ca575ce14a8c081366db5cfd0f7a85ff68559bd4216b3cecfb6a2618a29c6c95b17147d083f28cc1fae5959fd7de74d986e7fd543ce1060cbdd8d4ae136910d8a15a1b3ee16d955657630d5f50aae107d13aa0c46040616e2d3018e5d07f9551e2a4c34565c9b59b8fd7751e025f473772120b4a511946e09fc93dcf9732399244c1fbb864fa09c2dd5d29543e794e64b6e1a2df39289245ff4b65dff0357a6621d151e4514"));
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( pairing_test, bls_primitives_tester ) try {
|
||||
push_action("eosio"_n, "testpairing"_n, "test"_n, mvo()
|
||||
("g1_points", "af7d28fa69e9ff7cf98da7614f02faf91f8ae2888d522db1a225724394bedd8547ae93cb07b41f5f21092846c6c2950e43328c2e6aaa18cf735a703f4ee43a60658167b9c1bf895ddbc898dae5269a335699c595aa9dc4137103d5480320270f756a4c35700b847a02d4933be43e508139affb438b7bcf547debcf9904f1056d197ec8484283e2f194430e16443d250f0b4734d5380cac631d6287e2b45a6a12fb5fea3eed96a7b2cd3bac9a532e4bb6176b1e792964444798e5bf151e14c314277fa052e05911619c457335e708633aca11239a33686e56dd949e6f50e5fe79f1d069bbb01822566f992299184ddc06d08c662a5d2b37668c7821bef5177ff4df977799dc81ae15d0444be9a54db2195d41e316f7ebdb7d879f8f7b355cb416137401a36684f0ccbce51fd4d8b32f45d81f2c33bc95687ed777e7fcb181367e163d94356c96d239f193dabf01616d13936ba746ed9a64578a5a4b191238fe8472e4135525afcac4ed818c13e518864ce82de26a6bb1066b9c0771c021716603")
|
||||
("g2_points", "5528fc322669dcf2757583835b5ba5cc84f629db47e1d5e3ec78523fff567ec26100b7977ba038586c9e465abbaeb603554afef9cfe21ac33847b1d11796088cc6b18c7544355da3f996ddb0c0a15c8b1eeba2ec3a5cc8c7b4a8ecc7131e4609582cc42caa57f68017f95af50757bfc0d3c4d4327d1d40012af8f664da428f1984bf17c26d43b6fd65a8ce6c3d039d03f1247385a3f565108de722d4e08b0e9d23bba036646668167bdd41709ebe8bf5aadbd88ccc2af0c6d5940531c9fd50053e786ffe9011554db15fc7e130ea07cd254f21a86911fe758517274f96b89cb67e30c104186c4a6cb0d92cb82e39260245b68e74bdb828992697a1957be0564a9863f56eaf36bb5fc4d0869468b6ad4e36a1e7c550303c80c4ca0cbae773b309a61c6d4d6a4d2f17a4424c1987d294f195275581c8b8f88b7ce7fec5bc67e7bfd58bb747f39aa4dbc77d79cd18dd09142b10a45d49abc8fd544281f02a0e045062b72b25ead1a376e4f705ac83ad2385c84a8fd914d2f6a71d7eeb7126d677001013a0df759ff906a09fe4a3da307dd6cc17ee1fd72af8f7d953662be427cda2985cb1073563bbea492d9e6a96ca8a05ca5d45d349cb3e2f09cff6022a9916324eaa4fe5c543d46cafe5f82e81c5baddc2cc58100b03a20c2feaeed58cbd63019b8e3586d14193470d4ee9c1a0fc5e0a736e1ba94d7ad20ead3a3dacc4b2f3530ad751daffa944be4cb1969b3d2595058007d28d49e2fdebab68607c119b77d766785ed9e209582c737fce93b6ad0d4d795f86415238e0d3b70b9d8954d6a20ce85e7128588a849c505d5d2c81ff63bf12ea3ad52a316316ce49b2014dfbc486c9934dccb98db06089c03dc8f76ad70323ada12fe7e5b9f552c5b6cc073f72409a6e44f6634ca58bed30649b9840f177ea0039932f81574ea22b6da18b702f0e367f633e41d2b585d5166669f4c48d389f003eeecf06b5aa119d0df46de26adcb938d362e4410fdaa990a6fc4c2eca0f7bffee724789a0a47ba1b531bb4a3c95c129585ba5c9a6fe978a6915f4afedeb710ef6a55f153a5b21f943de6531680d")
|
||||
("res", "01cc207c7c76c65afc059d073106d545705af7c4e4ed78e6169c599bae1c9bf6358d5a2cdfeeae389cc64436dfe7b7192c733fe9e2d105c0eaec21589d8bb5ecd5c71a5fee083af47a1cbc3af2df8a13603a78956c39f55fd0663ed482846a047280f87426ecde4c535c0d30bdf4b95ff5aff45782129ee6c7a0fa20a632bc98e95bfb663685eb2443e4b1f518c40f00502303b3db49be61f36ef6af46b9097c83835a864ae6337ef07e40df617af1aacea98c0d75e96a104d41a3617e7a4f05fc1cdcec57ea40a0237ff387a5d9130b34c92cb57a3450080bbaa2f6f9e895851b05c05eec03abd2d5083c81c402a500d2bec4895cf0f58a9953e43ee9039a38ae73cc3ec325fa636777e1f597b69a2b6a62bd49fba5b163bc03ce73f277f818fad1c6681fa59be891c2baf85b6a5e908d96b6a6c4cf3d53b3de23fdade91b3dde7199648aca0fce1d2307253bf57b054a4c4dc276034f8d57017cddc0a84975c643f9ea808652f2cefea32f767fe8e6df58a837c47c3136ced7107e7dbd9711399605212e6a1b8da806a12636076f7da0629ca8173f0411ba2a1050d1bca61994e28f69f274ec94e016a3ba6f9a6b06cd17f570928b5e4b8c75a5d62a0a67bd54249702923b440355db775599ea7be7cd3c6d88ab8da7694e43352837b0080814880a1460bc61fae141d36f961db8393313f74a65c3eabcc38793b84062999364bb0c36a415445ec4318b59c16e850260a53e7aaaf72bcaa568b57b69b552bf827c3e1c116565122322d6c26e14354fd96dc4bb1161ede0ee36efeeae1a5503"));
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( g1_map_test, bls_primitives_tester ) try {
|
||||
push_action("eosio"_n, "testg1map"_n, "test"_n, mvo()
|
||||
("e", "6de1c03023f2b4e454559b97266ebc1f96cd5510c4f48e2acafbe73a536a1477f2c8d1c9b5f6615d01968ea59ef4fd07")
|
||||
("res", "2c7390d4bfbe0ccbaae9699aab5458d62f6d1aa91938b0ab0717249ad89209cb14ee8ed764a8952415382dbbfdef2312d5b2988b1ed7e6907d73ef2335cba7f9263b63003effa44ab8d6805d6ed0f08d87919230f0cb45d9ec35b2e0615d920f"));
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( g2_map_test, bls_primitives_tester ) try {
|
||||
push_action("eosio"_n, "testg2map"_n, "test"_n, mvo()
|
||||
("e", "b4108d552274d175fd4e52dd766ff396a4f365c102e0ef7b4d266f220ec67eefab48ac15d1db0d98ba31cda435616e0bdeb51952b044ce0f64b5d42199d9560ed0175f3d2c58af07909d29db4480c1b417dfbf7f1af274648adb54b029e38f08")
|
||||
("res", "f74a6a357dc6a1fb33344f60898ab9eb29c68170727136b26d943249fbbd9393bd893846ea0d43250d4fd37737e49f1463d11827561e80cda0f6ead2cd3c84d4be6d99d61fa4cbc41cce534af2cf3d1b3fc31ccecc1259cfc7530a93c58e801951454f38f693d2d763e0f993c202151d873eefec3e90507cea6232cb3c0061f254a2f4b5872098b23362763a79d6c004333e0e02ad077c8a3683d63827becf20c88a9b7a63bbac739bc3a4f659d119df2f5853e371a25c803fc8301c393e7804"));
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( fp_mul_test, bls_primitives_tester ) try {
|
||||
push_action("eosio"_n, "testfpmul"_n, "test"_n, mvo()
|
||||
("op1", "AAAAFFFFFFFFFEB9FFFF53B1FEFFAB1E24F6B0F6A0D23067BF1285F3844B7764D7AC4B43B6A71B4B9AE67F39EA11011A")
|
||||
("op2", "AAAAFFFFFFFFFEB9FFFF53B1FEFFAB1E24F6B0F6A0D23067BF1285F3844B7764D7AC4B43B6A71B4B9AE67F39EA11011A")
|
||||
("res", "010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( fp_exp_test, bls_primitives_tester ) try {
|
||||
push_action("eosio"_n, "testfpexp"_n, "test"_n, mvo()
|
||||
("base", "AAAAFFFFFFFFFEB9FFFF53B1FEFFAB1E24F6B0F6A0D23067BF1285F3844B7764D7AC4B43B6A71B4B9AE67F39EA11011A")
|
||||
("exp", "AAAAFFFFFFFFFEB9FFFF53B1FEFFAB1E24F6B0F6A0D23067BF1285F3844B7764D7AC4B43B6A71B4B9AE67F39EA11011A00000000000000000000000000000000")
|
||||
("res", "010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( base64_test, bls_primitives_tester ) try {
|
||||
push_action("eosio"_n, "g1baseb4enc"_n, "test"_n, mvo()
|
||||
("g1", "4783d417e555ba2fe4a6a9068e3c212bc43d5c895a83dc15bfdcbb65357c4caafbf6a6884c36a41c68587a77caba3f1105feb50023b4806b003c913c3ecca1ede21ff4cf322576520571977958ec1f6b8d483ae505a1eb93675ecf856ae0dc0e")
|
||||
("base64", "PUB_BLS_R4PUF-VVui_kpqkGjjwhK8Q9XIlag9wVv9y7ZTV8TKr79qaITDakHGhYenfKuj8RBf61ACO0gGsAPJE8Psyh7eIf9M8yJXZSBXGXeVjsH2uNSDrlBaHrk2dez4Vq4NwOf9VEMA"));
|
||||
push_action("eosio"_n, "sigbaseb4enc"_n, "test"_n, mvo()
|
||||
("g2", "ddb6db1f52a1eb191dfa57656645689fbd08e76170f08c9674c20c243c71bda00054d06862623083abe2a738da032000f1d2784eefacb8696a48f185ecc225f2b0cc26d3e59d84cb6bafba976785002446cd2921cb954daa124058a368ba270ef6e7a57e41f3c651f2ca6e70982330b5ab3acc65887f24e9f5c63d3550d2c6fa643fd6ea061c7e24ecdc41a8c55850089ab3cf40b0d986d283d065f1e7b66047008596d721db450b0e8b8eada95a09ca258a651d0d19b4651e2b38cbae308218")
|
||||
("base64", "SIG_BLS_3bbbH1Kh6xkd-ldlZkVon70I52Fw8IyWdMIMJDxxvaAAVNBoYmIwg6vipzjaAyAA8dJ4Tu-suGlqSPGF7MIl8rDMJtPlnYTLa6-6l2eFACRGzSkhy5VNqhJAWKNouicO9uelfkHzxlHyym5wmCMwtas6zGWIfyTp9cY9NVDSxvpkP9bqBhx-JOzcQajFWFAImrPPQLDZhtKD0GXx57ZgRwCFltch20ULDouOralaCcolimUdDRm0ZR4rOMuuMIIYOJG0NA"));
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( sig_verify_test, bls_primitives_tester ) try {
|
||||
// assumes signed message of std::vector<uint8_t> msg = {51, 23, 56, 93, 212, 129, 128, 27, 251, 12, 42, 129, 210, 9, 34, 98};
|
||||
// vector<uint8_t> seed(32, 0x30); array<uint64_t, 4> sk = secret_key(seed); g1 pk = g1::one().scale(sk).affine(); string pk_hex = to_hex(pk.toAffineBytesLE());
|
||||
// g2 sig = sign(sk, msg); string sig_hex = to_hex(sig.toAffineBytesLE());
|
||||
push_action("eosio"_n, "verifyraw"_n, "test"_n, mvo()
|
||||
("pk", "c27efc440ed89d739ff80f1c7178d4672d5f71e8c8926a85785d0f84074e79c1662c522fdbd6fcaebd640d816dea6c0dc36c5d7e7a297afc960369e306d845fcad0e5fe2a88c0d3bbe854d4f9e3e6365c9c1003662f0e81b35fd9c6a11d0a10c")
|
||||
("sig", "e13a38c18dfad440a9af8d720bfb9ce0f388a25a5789a8cdc34b87204fe29db5cc16658a5d9f4fa4a7cc16b8ef8d2d0d1a5984e6b69ca228692f1920e9340f149024b4d856711656f11bb1e0c7d081e5bb80692638a9bace2d8f4d796b4887129c59fbb7901997cbbb681f709291a45315979f55b719dfc8757d3a878cf01e4a48a0e6647b837d0ea8aea5d41e121b0dd37fa20007aef4f51740d846cc8d6ab151dbd88964e7d19890a500d5537be81b881451b75f928a66f546441d45028603"));
|
||||
|
||||
// bls_private_key sk = bls_private_key(seed_1);
|
||||
// bls_public_key pk = sk.get_public_key();
|
||||
// std::string msg = "this is a message string";
|
||||
// std::vector<uint8_t> msg_v(msg.begin(), msg.end());
|
||||
// bls_signature signature = sk.sign(msg_v);
|
||||
// pk.to_string();
|
||||
// signature.to_string();
|
||||
push_action("eosio"_n, "verify"_n, "test"_n, mvo()
|
||||
("pk", "PUB_BLS_sS66EwY8bNx7vkDn3mKhwPhhqa1V6STN1QSb6bWOIFBTloF5zt5b55r9y7uQMiQGrvt6XOZO3CpEgthlba7R7qz7Qob2YcD5EX3Ng_rUUdMBsjEJRuXNWICPe0QbKAoCQOw9vw")
|
||||
("sig", "SIG_BLS_07NCCTekrxhDFurhRhl3b8m4T-xmTixSl63TYcee_xJONi2_qy9-8o5vyetMefsL4hhDMfy1yIeHERqxUvGguRBBncpabp84b3P2bNpY18A-PVs7qKFqlld1gEUqt-cDOcwkyUe6HqqFXR5wtXoSHE4lHauV3CzR0lD91gnr2c49aUQPAC7SD-ZcnZyahwURje-Db26zhTXIO1WWIx6vwKnZUuvZEbzYrijjBQKeZsqp0eoAzjrByx9gOmN2d_AR9PhRvg")
|
||||
("msg", "this is a message string"));
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( sig_pop_verify_test, bls_primitives_tester ) try {
|
||||
push_action("eosio"_n, "popverifyraw"_n, "test"_n, mvo()
|
||||
("pk", "3b08e73bbda9c3eff597fc60fbb1bd8c81af3659024f62829082438ef52a02a71f99658087ea58108e12543c08980a0f1950c7f3085ab4b49e3137e8d35adfcbed616dd37cd011435e940a74f53f99ab1d1fd220a089d4e8517df0267ecb0802")
|
||||
("sig", "3a1e5689abddbd0ed54c48c88dcef7ac9bba70abdd7a8e965fb807a188cfc8a7e21ca5c9ecc58df7681d158cc6aced13d50bbe35a5aa7848c32a290b096e1f7a61b2817660bd6e6d5686180a1c00716d47ee996ced081fdb6c4417d6cc8dbd06f26f037331c1b4703e94454374ba04e71fb7571159299b9020c124e9ecee777c2b5c16a51ca883b716082fdf2e6c150551a82eaca5efaf761053d6998a439cc696366fe82eb93f19aac34893610698b37d11f0d608fdc1befc50a7e565ea4813"));
|
||||
|
||||
push_action("eosio"_n, "popverify"_n, "test"_n, mvo()
|
||||
("pk", "PUB_BLS_82P3oM1u0IEv64u9i4vSzvg1-QDl4Fb2n50Mp8Sk7Fr1Tz0MJypzL39nSd5VPFgFC9WqrjopRbBm1Pf0RkP018fo1k2rXaJY7Wtzd9RKlE8PoQ6XhDm4PyZlIupQg_gOuiMhcg")
|
||||
("sig", "SIG_BLS_RrwvP79LxfahskX-ceZpbgrJ1aUkSSIzE2sMFj0twuhK8QwjcGMvT2tZ_-QMHvAV83tWZYOs7SEvoyteCKGD_Tk6YySkw1HONgvVeNWM8ZwuNgonOHkegNNPIXSIvWMTczfkg2lEtEh-ngBa5t9-4CvZ6aOjg29XPVvu6dimzHix-9E0M53YkWZ-gW5GDkkOLoN2FMxjXaELmhuI64xSeSlcWLFfZa6TMVTctBFWsHDXm1ZMkURoB83dokKHEi4OQTbJtg"));
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -0,0 +1,275 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <eosio/testing/tester.hpp>
|
||||
#include <eosio/chain/abi_serializer.hpp>
|
||||
#include <fc/variant_object.hpp>
|
||||
|
||||
#include <contracts.hpp>
|
||||
|
||||
using namespace eosio;
|
||||
using namespace eosio::testing;
|
||||
using namespace fc;
|
||||
|
||||
using mvo = fc::mutable_variant_object;
|
||||
|
||||
struct acct_and_code {
|
||||
account_name acct;
|
||||
std::vector<uint8_t> wasm;
|
||||
char* abi = nullptr;
|
||||
};
|
||||
|
||||
// The first account in the accounts vector is the action initiating the
|
||||
// first sync call
|
||||
struct call_tester: tester {
|
||||
call_tester(const std::vector<acct_and_code>& accounts) {
|
||||
for (auto i = 0u; i < accounts.size(); ++i) {
|
||||
create_account(accounts[i].acct);
|
||||
set_code(accounts[i].acct, accounts[i].wasm);
|
||||
set_abi(accounts[i].acct, accounts[i].abi);
|
||||
}
|
||||
|
||||
produce_block();
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(sync_call_tests)
|
||||
|
||||
// Verify a sync call returns value correctly
|
||||
BOOST_AUTO_TEST_CASE(return_value_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::callee_wasm(), contracts::callee_abi().data()}
|
||||
});
|
||||
|
||||
// Using host function directly
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "hstretvaltst"_n, "caller"_n, {}));
|
||||
|
||||
// Using call_wrapper
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "wrpretvaltst"_n, "caller"_n, {}));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify one parameter passing works correctly
|
||||
BOOST_AUTO_TEST_CASE(param_basic_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::callee_wasm(), contracts::callee_abi().data()}
|
||||
});
|
||||
|
||||
// Using host function directly
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "hstoneprmtst"_n, "caller"_n, {}));
|
||||
|
||||
// Using call_wrapper
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "wrponeprmtst"_n, "caller"_n, {}));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify multiple parameters passing works correctly
|
||||
BOOST_AUTO_TEST_CASE(multiple_params_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::callee_wasm(), contracts::callee_abi().data()}
|
||||
});
|
||||
|
||||
// Using host function directly
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "hstmulprmtst"_n, "caller"_n, {}));
|
||||
|
||||
// Using call_wrapper
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "wrpmulprmtst"_n, "caller"_n, {}));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify passing a struct parameter works correctly
|
||||
BOOST_AUTO_TEST_CASE(struct_param_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::callee_wasm(), contracts::callee_abi().data()}
|
||||
});
|
||||
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "structtest"_n, "caller"_n, {}));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify passing a mix of structs and integer works correctly
|
||||
BOOST_AUTO_TEST_CASE(mix_struct_int_params_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::callee_wasm(), contracts::callee_abi().data()}
|
||||
});
|
||||
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "structinttst"_n, "caller"_n, {}));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify a sync call to a void function works properly.
|
||||
BOOST_AUTO_TEST_CASE(void_func_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::callee_wasm(), contracts::callee_abi().data()}
|
||||
});
|
||||
|
||||
auto check = [] (const transaction_trace_ptr& trx_trace) {
|
||||
auto& atrace = trx_trace->action_traces;
|
||||
|
||||
auto& call_traces = atrace[0].call_traces;
|
||||
BOOST_REQUIRE_EQUAL(call_traces.size(), 1u);
|
||||
|
||||
// Verify the print from the void function is correct.
|
||||
// The test contract checks the return value size is 0.
|
||||
auto& call_trace = call_traces[0];
|
||||
BOOST_REQUIRE_EQUAL(call_trace.call_ordinal, 1u);
|
||||
BOOST_REQUIRE_EQUAL(call_trace.sender_ordinal, 0u);
|
||||
BOOST_REQUIRE_EQUAL(call_trace.console, "I am a void function");
|
||||
};
|
||||
|
||||
// Using host function directly
|
||||
auto trx_trace = t.push_action("caller"_n, "hstvodfuntst"_n, "caller"_n, {});
|
||||
check(trx_trace);
|
||||
|
||||
// Using call_wrapper
|
||||
trx_trace = t.push_action("caller"_n, "wrpvodfuntst"_n, "caller"_n, {});
|
||||
check(trx_trace);
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify a function tagged as both `action` and `call` works
|
||||
BOOST_AUTO_TEST_CASE(mixed_action_call_tags_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::callee_wasm(), contracts::callee_abi().data()}
|
||||
});
|
||||
|
||||
// `sum` in `callee` contract is tagged as `action` and `call`
|
||||
|
||||
// Make sure we can make a sync call to `sum` (`mulparamtest` in `caller` does
|
||||
// a sync call to `sum`)
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "hstmulprmtst"_n, "caller"_n, {}));
|
||||
|
||||
// Make sure we can push an action using `sum`.
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("callee"_n, "sum"_n, "callee"_n,
|
||||
mvo()
|
||||
("a", 1)
|
||||
("b", 2)
|
||||
("c", 3)));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify the receiver contract with only one sync call function works
|
||||
// (for testing the sync_call entry point dispatcher)
|
||||
BOOST_AUTO_TEST_CASE(single_function_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::single_func_wasm(), contracts::single_func_abi().data()}
|
||||
});
|
||||
|
||||
// The single_func_wasm contains only one function and the caller contract
|
||||
// hooks up with it
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "hstretvaltst"_n, "caller"_n, {}));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify support_mode for void and non-void sync calls if calls are a failure
|
||||
BOOST_AUTO_TEST_CASE(sync_call_support_mode_failure_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::not_supported_wasm(), contracts::not_supported_abi().data()}
|
||||
});
|
||||
|
||||
// voidfncnoop uses support_mode::no_op
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "voidfncnoop"_n, "caller"_n, {}));
|
||||
|
||||
// voidfncabort uses default support_mode::abort
|
||||
BOOST_CHECK_EXCEPTION(t.push_action("caller"_n, "voidfncabort"_n, "caller"_n, {}),
|
||||
eosio_assert_message_exception,
|
||||
fc_exception_message_contains("receiver does not support sync call but support_mode is set to abort"));
|
||||
|
||||
// intfuncnoop uses support_mode::no_op
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "intfuncnoop"_n, "caller"_n, {}));
|
||||
|
||||
// intfuncabort uses default support_mode::abort
|
||||
BOOST_CHECK_EXCEPTION(t.push_action("caller"_n, "intfuncabort"_n, "caller"_n, {}),
|
||||
eosio_assert_message_exception,
|
||||
fc_exception_message_contains("receiver does not support sync call but support_mode is set to abort"));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify support_mode for void and non-void sync calls if call is successful
|
||||
BOOST_AUTO_TEST_CASE(sync_call_support_mode_success_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::callee_wasm(), contracts::callee_abi().data()}
|
||||
});
|
||||
|
||||
// voidnoopsucc uses support_mode::no_op
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "voidnoopsucc"_n, "caller"_n, {}));
|
||||
|
||||
// sumnoopsucc uses support_mode::no_op
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "sumnoopsucc"_n, "caller"_n, {}));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify header validation
|
||||
BOOST_AUTO_TEST_CASE(unknown_function_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::callee_wasm(), contracts::callee_abi().data()}
|
||||
});
|
||||
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "hdrvaltest"_n, "caller"_n, {}));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify adding/reading entries to/from a table, and read-only enforcement work
|
||||
BOOST_AUTO_TEST_CASE(addr_book_tests) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::addr_book_caller_wasm(), contracts::addr_book_caller_abi().data()},
|
||||
{"callee"_n, contracts::addr_book_callee_wasm(), contracts::addr_book_callee_abi().data()}
|
||||
});
|
||||
|
||||
// Try to add an entry using a read-only sync call
|
||||
BOOST_CHECK_EXCEPTION(t.push_action("caller"_n, "upsertrdonly"_n, "caller"_n, mvo()
|
||||
("user", "alice")
|
||||
("first_name", "alice")
|
||||
("street", "123 Main St.")),
|
||||
unaccessible_api,
|
||||
fc_exception_message_contains("this API is not allowed in read only action/call"));
|
||||
|
||||
// Add an entry using a read-write sync call
|
||||
t.push_action("caller"_n, "upsert"_n, "caller"_n, mvo()
|
||||
("user", "alice")
|
||||
("first_name", "alice")
|
||||
("street", "123 Main St."));
|
||||
|
||||
// Read the inserted entry. "get"_n action will check the return value from the sync call
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "get"_n, "caller"_n, mvo() ("user", "alice")));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// For a function tagged as both `action` and `call`, verify is_sync_call()
|
||||
// returns true if tagged as `call` and false if tagged as `action`.
|
||||
BOOST_AUTO_TEST_CASE(is_sync_call_test) { try {
|
||||
call_tester t({
|
||||
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
|
||||
{"callee"_n, contracts::callee_wasm(), contracts::callee_abi().data()}
|
||||
});
|
||||
|
||||
// issynccall() is tagged as both `action` and `call`, and returns
|
||||
// is_sync_call(). makesynccall() calls issynccall() as a sync call
|
||||
// and returns its result. So the current action return value must be
|
||||
// true.
|
||||
auto trx_trace = t.push_action("caller"_n, "makesynccall"_n, "caller"_n, {});
|
||||
auto& action_trace = trx_trace->action_traces[0];
|
||||
bool return_value = fc::raw::unpack<bool>(action_trace.return_value);
|
||||
BOOST_REQUIRE(return_value == true);
|
||||
|
||||
// Call issynccall() directly as an action. Since issynccall()
|
||||
// returns is_sync_call(), the current action return value must be false.
|
||||
trx_trace = t.push_action("callee"_n, "issynccall"_n, "callee"_n, {});
|
||||
auto& action_trace1 = trx_trace->action_traces[0];
|
||||
return_value = fc::raw::unpack<bool>(action_trace1.return_value);
|
||||
BOOST_REQUIRE(return_value == false);
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify customized sync call entry function, without sync call tag
|
||||
BOOST_AUTO_TEST_CASE(customized_call_entry_func_test1) { try {
|
||||
call_tester t({{"receiver"_n, contracts::cust_entry_wasm(), contracts::cust_entry_abi().data()}});
|
||||
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("receiver"_n, "cusentrytst1"_n, "receiver"_n, {}));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// Verify customized sync call entry function, with sync call tag
|
||||
BOOST_AUTO_TEST_CASE(customized_call_entry_func_test2) { try {
|
||||
call_tester t({{"receiver"_n, contracts::cust_entry_wasm(), contracts::cust_entry_abi().data()}});
|
||||
|
||||
BOOST_REQUIRE_NO_THROW(t.push_action("receiver"_n, "cusentrytst2"_n, "receiver"_n, {}));
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
namespace eosio::testing {
|
||||
struct contracts {
|
||||
static std::vector<uint8_t> array_tests_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/array_tests.wasm"); }
|
||||
static std::vector<char> array_tests_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/array_tests.abi"); }
|
||||
static std::vector<uint8_t> malloc_tests_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/malloc_tests.wasm"); }
|
||||
static std::vector<char> malloc_tests_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/malloc_tests.abi"); }
|
||||
static std::vector<uint8_t> old_malloc_tests_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/old_malloc_tests.wasm"); }
|
||||
@@ -23,6 +25,12 @@ namespace eosio::testing {
|
||||
static std::vector<uint8_t> crypto_primitives_test_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/crypto_primitives_tests.wasm"); }
|
||||
static std::vector<char> crypto_primitives_test_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/crypto_primitives_tests.abi"); }
|
||||
|
||||
static std::vector<uint8_t> bls_primitives_test_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/bls_primitives_tests.wasm"); }
|
||||
static std::vector<char> bls_primitives_test_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/bls_primitives_tests.abi"); }
|
||||
|
||||
static std::vector<uint8_t> instant_finality_test_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/instant_finality_tests.wasm"); }
|
||||
static std::vector<char> instant_finality_test_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/instant_finality_tests.abi"); }
|
||||
|
||||
static std::vector<uint8_t> get_code_hash_write_test_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/get_code_hash_write.wasm"); }
|
||||
static std::vector<char> get_code_hash_write_test_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/get_code_hash_write.abi"); }
|
||||
static std::vector<uint8_t> get_code_hash_read_test_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/get_code_hash_read.wasm"); }
|
||||
@@ -33,5 +41,20 @@ namespace eosio::testing {
|
||||
|
||||
static std::vector<uint8_t> test_multi_index_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/test_multi_index.wasm"); }
|
||||
static std::vector<char> test_multi_index_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/test_multi_index.abi"); }
|
||||
|
||||
static std::vector<uint8_t> caller_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_caller.wasm"); }
|
||||
static std::vector<char> caller_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_caller.abi"); }
|
||||
static std::vector<uint8_t> callee_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_callee.wasm"); }
|
||||
static std::vector<char> callee_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_callee.abi"); }
|
||||
static std::vector<uint8_t> not_supported_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_not_supported.wasm"); }
|
||||
static std::vector<char> not_supported_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_not_supported.abi"); }
|
||||
static std::vector<uint8_t> single_func_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_single_func.wasm"); }
|
||||
static std::vector<char> single_func_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_single_func.abi"); }
|
||||
static std::vector<uint8_t> addr_book_callee_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_addr_book_callee.wasm"); }
|
||||
static std::vector<char> addr_book_callee_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_addr_book_callee.abi"); }
|
||||
static std::vector<uint8_t> addr_book_caller_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_addr_book_caller.wasm"); }
|
||||
static std::vector<char> addr_book_caller_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_addr_book_caller.abi"); }
|
||||
static std::vector<uint8_t> cust_entry_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_cust_entry.wasm"); }
|
||||
static std::vector<char> cust_entry_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_cust_entry.abi"); }
|
||||
};
|
||||
} //ns eosio::testing
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <eosio/testing/tester.hpp>
|
||||
#include <eosio/chain/abi_serializer.hpp>
|
||||
#include <fc/variant_object.hpp>
|
||||
|
||||
#include <contracts.hpp>
|
||||
|
||||
using namespace eosio;
|
||||
using namespace eosio::testing;
|
||||
using namespace fc;
|
||||
|
||||
using mvo = fc::mutable_variant_object;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(instant_finality_tests)
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(instant_finality_test, tester) try {
|
||||
create_accounts( { "test"_n } );
|
||||
produce_block();
|
||||
|
||||
set_code( config::system_account_name, contracts::instant_finality_test_wasm() );
|
||||
set_abi( config::system_account_name, contracts::instant_finality_test_abi().data() );
|
||||
|
||||
produce_block();
|
||||
|
||||
push_action(config::system_account_name, "setfinalizer"_n, "test"_n, mvo()
|
||||
("finalizer_policy", mvo()("threshold", 1)
|
||||
("finalizers", std::vector<mvo>{mvo()
|
||||
("description", "test_desc")
|
||||
("weight", 1)
|
||||
("public_key", "744beeb74c9d1debc318fe847f73b822ae905dff6351c3144f59c22515fe251625158acefea2adff1e37f6f509d83919df639de8074967e4bd756444f52cbeed0e9b363a6820e3f4716ce4282d43aa685f137a5a5be293840de7a0b915f12b08")})));
|
||||
signed_block_ptr cur_block = produce_block();
|
||||
fc::variant pretty_output;
|
||||
abi_serializer::to_variant( *cur_block, pretty_output, get_resolver(), fc::microseconds::maximum() );
|
||||
std::cout << fc::json::to_string(pretty_output, fc::time_point::now() + abi_serializer_max_time) << std::endl;
|
||||
|
||||
std::string output_json = fc::json::to_pretty_string(pretty_output);
|
||||
BOOST_TEST(output_json.find("finality_extension") != std::string::npos);
|
||||
BOOST_TEST(output_json.find("\"generation\": 2") != std::string::npos);
|
||||
BOOST_TEST(output_json.find("\"threshold\": 1") != std::string::npos);
|
||||
BOOST_TEST(output_json.find("\"description\": \"test_desc\"") != std::string::npos);
|
||||
BOOST_TEST(output_json.find("\"weight\": 1") != std::string::npos);
|
||||
BOOST_TEST(output_json.find("PUB_BLS_dEvut0ydHevDGP6Ef3O4Iq6QXf9jUcMUT1nCJRX-JRYlFYrO_qKt_x439vUJ2DkZ32Od6AdJZ-S9dWRE9Sy-7Q6bNjpoIOP0cWzkKC1DqmhfE3paW-KThA3noLkV8SsILcfxpQ") != std::string::npos);
|
||||
|
||||
// testing wrong public key size
|
||||
BOOST_CHECK_THROW(push_action(config::system_account_name, "setfinalizer"_n, "test"_n, mvo()
|
||||
("finalizer_policy", mvo()("threshold", 1)
|
||||
("finalizers", std::vector<mvo>{mvo()
|
||||
("description", "test_desc")
|
||||
("weight", 1)
|
||||
("public_key", std::vector<char>{'a', 'b', 'c'})}))), fc::exception);
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -18,7 +18,7 @@ using namespace eosio::testing;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(multi_index_tests)
|
||||
|
||||
// this test is copy from leap test_api_multi_index
|
||||
// this test is copied from Spring test_api_multi_index
|
||||
BOOST_FIXTURE_TEST_CASE(main_multi_index_tests, TESTER) { try {
|
||||
produce_blocks(1);
|
||||
create_account( "testapi"_n );
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <charconv>
|
||||
|
||||
inline eosio::chain::version_t extract_version_from_json_abi(std::vector<char> abi) {
|
||||
std::string_view sv(abi.data(), abi.size());
|
||||
|
||||
constexpr const char* pattern = R"("version": "eosio::abi/)";
|
||||
if (auto pos = sv.find(pattern); pos != std::string_view::npos) {
|
||||
return eosio::chain::version_t{sv.substr(pos + strlen(pattern))};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": [],
|
||||
"expected" : {
|
||||
"abi-file" : "action_results_test.abi"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tests": [
|
||||
{
|
||||
"compile_flags": [],
|
||||
"expected": {
|
||||
"abi-file": "aliased_type_variant_template_arg.abi"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": [],
|
||||
"expected" : {
|
||||
"abi-file" : "nested_container.abi"
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": [],
|
||||
"expected" : {
|
||||
"abi-file" : "singleton_contract.abi"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tests": [
|
||||
{
|
||||
"compile_flags": [],
|
||||
"expected": {
|
||||
"abi-file": "struct_base_typedefd.abi"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
{
|
||||
"____comment": "This file was generated with eosio-abigen. DO NOT EDIT ",
|
||||
"version": "eosio::abi/1.3",
|
||||
"types": [],
|
||||
"structs": [
|
||||
{
|
||||
"name": "noparam",
|
||||
"base": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "sum",
|
||||
"base": "",
|
||||
"fields": [
|
||||
{
|
||||
"name": "a",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "b",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "c",
|
||||
"type": "uint32"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "voidfunc",
|
||||
"base": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "withparam",
|
||||
"base": "",
|
||||
"fields": [
|
||||
{
|
||||
"name": "in",
|
||||
"type": "uint32"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"actions": [],
|
||||
"tables": [],
|
||||
"ricardian_clauses": [],
|
||||
"variants": [],
|
||||
"action_results": [],
|
||||
"calls": [
|
||||
{
|
||||
"name": "noparam",
|
||||
"type": "noparam",
|
||||
"id": 229476383600947,
|
||||
"result_type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "sum",
|
||||
"type": "sum",
|
||||
"id": 193506202,
|
||||
"result_type": "uint32"
|
||||
},
|
||||
{
|
||||
"name": "voidfunc",
|
||||
"type": "voidfunc",
|
||||
"id": 7573061335575747,
|
||||
"result_type": ""
|
||||
},
|
||||
{
|
||||
"name": "withparam",
|
||||
"type": "withparam",
|
||||
"id": 249912189145794130,
|
||||
"result_type": "uint32"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include <eosio/call.hpp>
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
class [[eosio::contract]] sync_call_test : public eosio::contract {
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t noparam() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t withparam(uint32_t in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
[[eosio::call]]
|
||||
void voidfunc() {
|
||||
int i = 10;
|
||||
}
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t sum(uint32_t a, uint32_t b, uint32_t c) {
|
||||
return a + b + c;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"expected" : {
|
||||
"abi-file" : "sync_call_test.abi"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": [],
|
||||
"expected" : {
|
||||
"abi-file" : "tagged_number_test.abi"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": [],
|
||||
"expected" : {
|
||||
"abi-file" : "using_std_array.abi"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
class [[eosio::contract]] separate_cpp_hpp : eosio::contract {
|
||||
class [[eosio::contract]] separate_cpp_hpp : public eosio::contract {
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ set_blockchain_parameters_packed : yes
|
||||
set_parameters_packed : yes
|
||||
set_privileged : yes
|
||||
send_deferred : yes
|
||||
set_finalizers : yes
|
||||
*/
|
||||
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <eosio/call.hpp>
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
// Test the validation of the number of arguments passed in call_wrapper.
|
||||
// Expected error:
|
||||
// .../build/bin/../include/eosiolib/contracts/eosio/detail.hpp:72:7: error: static_assert failed due to requirement 'sizeof...(Ts) == std::tuple_size<std::__1::tuple<unsigned int, unsigned int, unsigned int>>::value'
|
||||
// static_assert(sizeof...(Ts) == std::tuple_size<deduced<Function>>::value);
|
||||
|
||||
class [[eosio::contract]] sync_call_invalid_arg_nums : public eosio::contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t sum(uint32_t a, uint32_t b, uint32_t c) {
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
using sum_func = eosio::call_wrapper<"sum"_i, &sync_call_invalid_arg_nums::sum>;
|
||||
|
||||
// Fewer number of arguments
|
||||
[[eosio::action]]
|
||||
void fewerargs() {
|
||||
sum_func{"callee"_n}(1, 2);
|
||||
}
|
||||
|
||||
// More number of arguments
|
||||
[[eosio::action]]
|
||||
void moreargs() {
|
||||
sum_func{"callee"_n}(1, 2, 3, 4);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": [],
|
||||
"expected" : {
|
||||
"exit-code": 255,
|
||||
"stderr": "error: static_assert failed due to requirement 'sizeof"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <eosio/call.hpp>
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
// Test the validation of the types of arguments passed in call_wrapper.
|
||||
// Expected error:
|
||||
// build/bin/../include/eosiolib/contracts/eosio/detail.hpp:60:7: error: static_assert failed due to requirement 'detail::is_same<sync_call_invalid_arg_nums::empty &, unsigned int>::value'
|
||||
// static_assert(detail::is_same<typename convert<T>::type, typename convert<typename std::tuple_element<I, deduced<Function>>::type>::type>::value);
|
||||
class [[eosio::contract]] sync_call_invalid_arg_nums : public eosio::contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t sum(uint32_t a, uint32_t b, uint32_t c) {
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
using sum_func = eosio::call_wrapper<"sum"_i, &sync_call_invalid_arg_nums::sum>;
|
||||
|
||||
struct empty {
|
||||
};
|
||||
|
||||
// Invalid first argument
|
||||
[[eosio::action]]
|
||||
void wrongrettype() {
|
||||
empty bad;
|
||||
sum_func{"callee"_n}(bad, 2, 3);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"tests" : [
|
||||
{
|
||||
"compile_flags": [],
|
||||
"expected" : {
|
||||
"exit-code": 255,
|
||||
"stderr": "error: static_assert failed due to requirement 'detail::is_same"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5,7 +5,6 @@ include( CDTMacros )
|
||||
|
||||
macro(add_cdt_unit_test TEST_NAME)
|
||||
add_native_executable(${TEST_NAME} ${TEST_NAME}.cpp)
|
||||
target_compile_options(${TEST_NAME} PRIVATE -fno-cfl-aa)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
target_compile_options(${TEST_NAME} PRIVATE -O2)
|
||||
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
@@ -14,6 +13,7 @@ macro(add_cdt_unit_test TEST_NAME)
|
||||
endmacro()
|
||||
|
||||
add_cdt_unit_test(asset_tests)
|
||||
add_cdt_unit_test(base64_tests)
|
||||
add_cdt_unit_test(binary_extension_tests)
|
||||
add_cdt_unit_test(crt_tests)
|
||||
add_cdt_unit_test(crypto_tests)
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright defined in eosio.cdt/LICENSE.txt
|
||||
*/
|
||||
|
||||
#include <eosio/tester.hpp>
|
||||
#include <eosio/base64.hpp>
|
||||
|
||||
using namespace eosio;
|
||||
using namespace std::literals;
|
||||
|
||||
EOSIO_TEST_BEGIN(base64enc)
|
||||
auto input = "abc123$&()'?\xb4\xf5\x01\xfa~a"s;
|
||||
auto expected_output = "YWJjMTIzJCYoKSc/tPUB+n5h"s;
|
||||
|
||||
CHECK_EQUAL(expected_output, base64_encode(input));
|
||||
EOSIO_TEST_END
|
||||
|
||||
// No trailing sequence of = added
|
||||
EOSIO_TEST_BEGIN(base64urlenc)
|
||||
auto input = "abc123$&()'?\xb4\xf5\x01\xfa~a"s;
|
||||
auto expected_output = "YWJjMTIzJCYoKSc_tPUB-n5h"s;
|
||||
|
||||
CHECK_EQUAL(expected_output, base64url_encode(input));
|
||||
EOSIO_TEST_END
|
||||
|
||||
EOSIO_TEST_BEGIN(base64dec)
|
||||
auto input = "YWJjMTIzJCYoKSc/tPUB+n5h"s;
|
||||
auto expected_output = "abc123$&()'?\xb4\xf5\x01\xfa~a"s;
|
||||
|
||||
CHECK_EQUAL(expected_output, base64_decode(input));
|
||||
EOSIO_TEST_END
|
||||
|
||||
EOSIO_TEST_BEGIN(base64urldec)
|
||||
auto input = "YWJjMTIzJCYoKSc_tPUB-n5h"s;
|
||||
auto expected_output = "abc123$&()'?\xb4\xf5\x01\xfa~a"s;
|
||||
|
||||
CHECK_EQUAL(expected_output, base64url_decode(input));
|
||||
EOSIO_TEST_END
|
||||
|
||||
EOSIO_TEST_BEGIN(base64dec_extraequals)
|
||||
CHECK_ASSERT( "encountered non-base64 character",
|
||||
([](){
|
||||
base64_decode("YWJjMTIzJCYoKSc/tPUB+n5h========="s);
|
||||
}));
|
||||
EOSIO_TEST_END
|
||||
|
||||
EOSIO_TEST_BEGIN(base64dec_bad_stuff)
|
||||
CHECK_ASSERT( "encountered non-base64 character",
|
||||
([](){
|
||||
base64_decode("YWJjMTIzJCYoKSc/tPU$B+n5h="s);
|
||||
}));
|
||||
EOSIO_TEST_END
|
||||
|
||||
// `+` not valid in base64 url
|
||||
EOSIO_TEST_BEGIN(base64urldec_plus_not_allowed)
|
||||
CHECK_ASSERT( "encountered non-base64 character",
|
||||
([](){
|
||||
base64_decode("YWJjMTIzJCYoKSc+tPUB-n5h"s);
|
||||
}));
|
||||
EOSIO_TEST_END
|
||||
|
||||
// `/` not valid in base64 url
|
||||
EOSIO_TEST_BEGIN(base64urldec_slash_not_allowed)
|
||||
CHECK_ASSERT( "encountered non-base64 character",
|
||||
([](){
|
||||
base64_decode("YWJjMTIzJCYoKSc/tPUB-n5h"s);
|
||||
}));
|
||||
EOSIO_TEST_END
|
||||
|
||||
// trailing not allowed in base64 url
|
||||
EOSIO_TEST_BEGIN(base64urldec_trailing_not_allowed)
|
||||
CHECK_ASSERT( "encountered non-base64 character",
|
||||
([](){
|
||||
base64_decode("YWJjMTIzJCYoKSc_tPUB-n5h=="s);
|
||||
}));
|
||||
EOSIO_TEST_END
|
||||
|
||||
// tests from https://github.com/ReneNyffenegger/cpp-base64/blob/master/test.cpp
|
||||
EOSIO_TEST_BEGIN(base64_cpp_base64_tests)
|
||||
//
|
||||
// Note: this file must be encoded in UTF-8
|
||||
// for the following test, otherwise, the test item
|
||||
// fails.
|
||||
//
|
||||
const std::string orig =
|
||||
"René Nyffenegger\n"
|
||||
"http://www.renenyffenegger.ch\n"
|
||||
"passion for data\n";
|
||||
|
||||
std::string encoded = base64_encode({orig.c_str(), orig.length()});
|
||||
std::string decoded = base64_decode(encoded);
|
||||
|
||||
CHECK_EQUAL(encoded, "UmVuw6kgTnlmZmVuZWdnZXIKaHR0cDovL3d3dy5yZW5lbnlmZmVuZWdnZXIuY2gKcGFzc2lvbiBmb3IgZGF0YQo=");
|
||||
CHECK_EQUAL(decoded, orig);
|
||||
|
||||
// Test all possibilites of fill bytes (none, one =, two ==)
|
||||
// References calculated with: https://www.base64encode.org/
|
||||
|
||||
std::string rest0_original = "abc";
|
||||
std::string rest0_reference = "YWJj";
|
||||
|
||||
std::string rest0_encoded = base64_encode({rest0_original.c_str(),rest0_original.length()});
|
||||
std::string rest0_decoded = base64_decode(rest0_encoded);
|
||||
|
||||
CHECK_EQUAL(rest0_decoded, rest0_original);
|
||||
CHECK_EQUAL(rest0_reference, rest0_encoded);
|
||||
|
||||
std::string rest1_original = "abcd";
|
||||
std::string rest1_reference = "YWJjZA==";
|
||||
|
||||
std::string rest1_encoded = base64_encode({rest1_original.c_str(), rest1_original.length()});
|
||||
std::string rest1_decoded = base64_decode(rest1_encoded);
|
||||
|
||||
CHECK_EQUAL(rest1_decoded, rest1_original);
|
||||
CHECK_EQUAL(rest1_reference, rest1_encoded);
|
||||
|
||||
std::string rest2_original = "abcde";
|
||||
std::string rest2_reference = "YWJjZGU=";
|
||||
|
||||
std::string rest2_encoded = base64_encode({rest2_original.c_str(),rest2_original.length()});
|
||||
std::string rest2_decoded = base64_decode(rest2_encoded);
|
||||
|
||||
CHECK_EQUAL(rest2_decoded, rest2_original);
|
||||
CHECK_EQUAL(rest2_reference, rest2_encoded);
|
||||
|
||||
// --------------------------------------------------------------
|
||||
//
|
||||
// Data that is 17 bytes long requires one padding byte when
|
||||
// base-64 encoded. Such an encoded string could not correctly
|
||||
// be decoded when encoded with «url semantics». This bug
|
||||
// was discovered by https://github.com/kosniaz. The following
|
||||
// test checks if this bug was fixed:
|
||||
//
|
||||
std::string a17_orig = "aaaaaaaaaaaaaaaaa";
|
||||
std::string a17_encoded = base64_encode(a17_orig);
|
||||
std::string a17_encoded_url = base64url_encode(a17_orig);
|
||||
|
||||
CHECK_EQUAL(a17_encoded, "YWFhYWFhYWFhYWFhYWFhYWE=");
|
||||
CHECK_EQUAL(a17_encoded_url, "YWFhYWFhYWFhYWFhYWFhYWE");
|
||||
CHECK_EQUAL(base64_decode(a17_encoded_url), a17_orig);
|
||||
CHECK_EQUAL(base64_decode(a17_encoded), a17_orig);
|
||||
|
||||
// --------------------------------------------------------------
|
||||
|
||||
// characters 63 and 64 / URL encoding
|
||||
|
||||
std::string s_6364 = "\x03" "\xef" "\xff" "\xf9";
|
||||
|
||||
std::string s_6364_encoded = base64_encode(s_6364);
|
||||
std::string s_6364_encoded_url = base64url_encode(s_6364);
|
||||
|
||||
CHECK_EQUAL(s_6364_encoded, "A+//+Q==");
|
||||
CHECK_EQUAL(s_6364_encoded_url, "A-__-Q");
|
||||
CHECK_EQUAL(base64_decode(s_6364_encoded), s_6364);
|
||||
CHECK_EQUAL(base64url_decode(s_6364_encoded_url), s_6364);
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
std::string unpadded_input = "YWJjZGVmZw"; // Note the 'missing' "=="
|
||||
std::string unpadded_decoded = base64_decode(unpadded_input);
|
||||
CHECK_EQUAL(unpadded_decoded, "abcdefg");
|
||||
|
||||
unpadded_input = "YWJjZGU"; // Note the 'missing' "="
|
||||
unpadded_decoded = base64_decode(unpadded_input);
|
||||
CHECK_EQUAL(unpadded_decoded, "abcde");
|
||||
|
||||
unpadded_input = "";
|
||||
unpadded_decoded = base64_decode(unpadded_input);
|
||||
CHECK_EQUAL(unpadded_decoded, "");
|
||||
|
||||
unpadded_input = "YQ";
|
||||
unpadded_decoded = base64_decode(unpadded_input);
|
||||
CHECK_EQUAL(unpadded_decoded, "a");
|
||||
|
||||
unpadded_input = "YWI";
|
||||
unpadded_decoded = base64_decode(unpadded_input);
|
||||
CHECK_EQUAL(unpadded_decoded, "ab");
|
||||
|
||||
CHECK_ASSERT( "wrong encoded string size",
|
||||
([](){
|
||||
std::string not_null_terminated = std::string(1, 'a');
|
||||
base64_decode(not_null_terminated);
|
||||
}));
|
||||
// --------------------------------------------------------------
|
||||
//
|
||||
// Test the string_view interface (which required C++17)
|
||||
//
|
||||
std::string_view sv_orig = "foobarbaz";
|
||||
std::string sv_encoded = base64_encode(sv_orig);
|
||||
|
||||
CHECK_EQUAL(sv_encoded, "Zm9vYmFyYmF6");
|
||||
|
||||
std::string sv_decoded = base64_decode(sv_encoded);
|
||||
|
||||
CHECK_EQUAL(sv_decoded, sv_orig);
|
||||
|
||||
EOSIO_TEST_END
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
bool verbose = false;
|
||||
if( argc >= 2 && std::strcmp( argv[1], "-v" ) == 0 ) {
|
||||
verbose = true;
|
||||
}
|
||||
silence_output(!verbose);
|
||||
|
||||
EOSIO_TEST(base64enc);
|
||||
EOSIO_TEST(base64urlenc);
|
||||
EOSIO_TEST(base64dec);
|
||||
EOSIO_TEST(base64urldec);
|
||||
EOSIO_TEST(base64dec_extraequals);
|
||||
EOSIO_TEST(base64dec_bad_stuff);
|
||||
EOSIO_TEST(base64_cpp_base64_tests);
|
||||
return has_failed();
|
||||
}
|
||||
@@ -351,6 +351,13 @@ EOSIO_TEST_BEGIN(datastream_stream_test)
|
||||
ds.seekp(0);
|
||||
ds >> o;
|
||||
CHECK_EQUAL( co, o )
|
||||
// test upacking an empty std::optional to a non-empty works
|
||||
static const optional<char> co1{}; // empty
|
||||
ds.seekp(0);
|
||||
ds << co1;
|
||||
ds.seekp(0);
|
||||
ds >> o; // o had value
|
||||
CHECK_EQUAL( co1, o )
|
||||
|
||||
// ---------
|
||||
// std::pair
|
||||
|
||||
@@ -7,12 +7,21 @@ add_contract(explicit_nested_tests explicit_nested_tests explicit_nested_tests.c
|
||||
add_contract(transfer_contract transfer_contract transfer.cpp)
|
||||
add_contract(minimal_tests minimal_tests minimal_tests.cpp)
|
||||
add_contract(crypto_primitives_tests crypto_primitives_tests crypto_primitives_tests.cpp)
|
||||
add_contract(bls_primitives_tests bls_primitives_tests bls_primitives_tests.cpp)
|
||||
add_contract(instant_finality_tests instant_finality_tests instant_finality_tests.cpp)
|
||||
add_contract(get_code_hash_tests get_code_hash_write get_code_hash_write.cpp)
|
||||
add_contract(get_code_hash_tests get_code_hash_read get_code_hash_read.cpp)
|
||||
add_contract(name_pk_tests name_pk_tests name_pk_tests.cpp)
|
||||
add_contract(test_multi_index test_multi_index multi_index_tests.cpp)
|
||||
add_contract(sync_call_caller sync_call_caller sync_call_caller.cpp)
|
||||
add_contract(sync_call_callee sync_call_callee sync_call_callee.cpp)
|
||||
add_contract(sync_call_not_supported sync_call_not_supported sync_call_not_supported.cpp)
|
||||
add_contract(sync_call_single_func sync_call_single_func sync_call_single_func.cpp)
|
||||
add_contract(sync_call_addr_book_callee sync_call_addr_book_callee sync_call_addr_book_callee.cpp)
|
||||
add_contract(sync_call_addr_book_caller sync_call_addr_book_caller sync_call_addr_book_caller.cpp)
|
||||
add_contract(sync_call_cust_entry sync_call_cust_entry sync_call_cust_entry.cpp)
|
||||
add_contract(capi_tests capi_tests capi/capi.c capi/action.c capi/chain.c capi/crypto.c capi/db.c capi/permission.c
|
||||
capi/print.c capi/privileged.c capi/system.c capi/transaction.c)
|
||||
capi/print.c capi/privileged.c capi/system.c capi/transaction.c capi/call.c)
|
||||
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/simple_wrong.abi ${CMAKE_CURRENT_BINARY_DIR}/simple_wrong.abi COPYONLY )
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/capi/capi_tests.abi ${CMAKE_CURRENT_BINARY_DIR}/capi_tests.abi COPYONLY )
|
||||
|
||||
@@ -65,8 +65,7 @@ class [[eosio::contract]] array_tests : public contract {
|
||||
}
|
||||
}
|
||||
|
||||
// test parameter using std::array
|
||||
// not supported so far
|
||||
// test parameter using std::array
|
||||
[[eosio::action]]
|
||||
void testpa(std::array<int,4> input){
|
||||
std::array<int,4> arr = input;
|
||||
@@ -76,7 +75,7 @@ class [[eosio::contract]] array_tests : public contract {
|
||||
eosio::cout << "\n";
|
||||
}
|
||||
|
||||
// test return using std::array, not supported so far
|
||||
// test parameter and return value using std::array
|
||||
[[eosio::action]]
|
||||
// cleos -v push action eosio testre '[[1,2,3,4]]' -p eosio@active
|
||||
std::array<int,4> testre(std::array<int,4> input){
|
||||
@@ -85,6 +84,15 @@ class [[eosio::contract]] array_tests : public contract {
|
||||
return arr;
|
||||
}
|
||||
|
||||
// test return value using std::array
|
||||
[[eosio::action]]
|
||||
// cleos -v push action eosio testre2 '[[1,2,3,4]]' -p eosio@active
|
||||
std::array<int,4> testre2(std::vector<int> input){
|
||||
std::array<int,4> arr;
|
||||
for(size_t i=0; i<4; ++i) arr[i] = input[i+1];
|
||||
return arr;
|
||||
}
|
||||
|
||||
// test return using std::vector
|
||||
[[eosio::action]]
|
||||
// cleos -v push action eosio testrev '[[1,2,3,4]]' -p eosio@active
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
#include <eosio/eosio.hpp>
|
||||
#include <eosio/crypto.hpp>
|
||||
#include <eosio/crypto_ext.hpp>
|
||||
#include <eosio/crypto_bls_ext.hpp>
|
||||
|
||||
using namespace eosio;
|
||||
|
||||
class [[eosio::contract]] bls_primitives_tests : public contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::action]]
|
||||
void testg1add(const std::vector<char>& op1, const std::vector<char>& op2, const std::vector<char>& res) {
|
||||
check(op1.size() == std::tuple_size<bls_g1>::value, "wrong op1 size passed");
|
||||
check(op2.size() == std::tuple_size<bls_g1>::value, "wrong op2 size passed");
|
||||
bls_g1 r;
|
||||
bls_g1_add(*reinterpret_cast<const bls_g1*>(op1.data()), *reinterpret_cast<const bls_g1*>(op2.data()), r);
|
||||
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g1_add test failed");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void testg2add(const std::vector<char>& op1, const std::vector<char>& op2, const std::vector<char>& res) {
|
||||
bls_g2 r;
|
||||
bls_g2_add(*reinterpret_cast<const bls_g2*>(op1.data()), *reinterpret_cast<const bls_g2*>(op2.data()), r);
|
||||
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g2_add test failed");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void testg1wsum(const std::vector<char>& points, const std::vector<char>& scalars, const uint32_t num, const std::vector<char>& res)
|
||||
{
|
||||
check(points.size() == std::tuple_size<bls_g1>::value * num, "wrong points size passed");
|
||||
check(scalars.size() == std::tuple_size<bls_scalar>::value * num, "wrong scalars size passed");
|
||||
check(res.size() == std::tuple_size<bls_g1>::value, "wrong res size passed");
|
||||
bls_g1 r;
|
||||
int32_t error = bls_g1_weighted_sum(
|
||||
reinterpret_cast<const bls_g1*>(points.data()),
|
||||
reinterpret_cast<const bls_scalar*>(scalars.data()),
|
||||
num,
|
||||
r
|
||||
);
|
||||
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g1_weighted_sum: Result does not match");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void testg2wsum(const std::vector<char>& points, const std::vector<char>& scalars, const uint32_t num, const std::vector<char>& res)
|
||||
{
|
||||
check(points.size() == std::tuple_size<bls_g2>::value * num, "wrong points size passed");
|
||||
check(scalars.size() == std::tuple_size<bls_scalar>::value * num, "wrong scalars size passed");
|
||||
check(res.size() == std::tuple_size<bls_g2>::value, "wrong res size passed");
|
||||
bls_g2 r;
|
||||
int32_t error = bls_g2_weighted_sum(
|
||||
reinterpret_cast<const bls_g2*>(points.data()),
|
||||
reinterpret_cast<const bls_scalar*>(scalars.data()),
|
||||
num,
|
||||
r
|
||||
);
|
||||
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g2_weighted_sum: Result does not match");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void testpairing(const std::vector<char>& g1_points, const std::vector<char>& g2_points, const std::vector<char>& res) {
|
||||
auto num = g2_points.size()/sizeof(bls_g2);
|
||||
check(g1_points.size()/sizeof(bls_g1) == num, "number of elements in g1_points and g2_points must be equal");
|
||||
bls_gt r;
|
||||
bls_pairing(reinterpret_cast<const bls_g1*>(g1_points.data()), reinterpret_cast<const bls_g2*>(g2_points.data()), num, r);
|
||||
check(std::equal(res.begin(), res.end(), r.begin()), "bls_pairing test failed");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void testg1map(const std::vector<char>& e, const std::vector<char>& res) {
|
||||
bls_g1 r;
|
||||
bls_g1_map(*reinterpret_cast<const bls_fp*>(e.data()), r);
|
||||
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g1_map test failed");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void testg2map(const std::vector<char>& e, const std::vector<char>& res) {
|
||||
bls_g2 r;
|
||||
bls_g2_map(*reinterpret_cast<const bls_fp2*>(e.data()), r);
|
||||
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g2_map test failed");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void testfpmul(const std::vector<char>& op1, const std::vector<char>& op2, const std::vector<char>& res)
|
||||
{
|
||||
bls_fp r;
|
||||
int32_t error = bls_fp_mul(
|
||||
*reinterpret_cast<const bls_fp*>(op1.data()),
|
||||
*reinterpret_cast<const bls_fp*>(op2.data()),
|
||||
r
|
||||
);
|
||||
check(std::equal(res.begin(), res.end(), r.begin()), "bls_fp_mul: Result does not match");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void testfpexp(const std::vector<char>& base, const std::vector<char>& exp, const std::vector<char>& res)
|
||||
{
|
||||
bls_fp r;
|
||||
int32_t error = bls_fp_exp(
|
||||
*reinterpret_cast<const bls_fp*>(base.data()),
|
||||
*reinterpret_cast<const bls_s*>(exp.data()),
|
||||
r
|
||||
);
|
||||
check(std::equal(res.begin(), res.end(), r.begin()), "bls_fp_exp: Result does not match");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void popverifyraw(const std::vector<char>& pk, const std::vector<char>& sig) {
|
||||
check(pk.size() == std::tuple_size<bls_g1>::value, "wrong public key size passed");
|
||||
check(sig.size() == std::tuple_size<bls_g2>::value, "wrong signature size passed");
|
||||
check(bls_pop_verify(*reinterpret_cast<const bls_g1*>(pk.data()), *reinterpret_cast<const bls_g2*>(sig.data())), "raw pop verify failed");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void popverify(const std::string& pk, const std::string& sig) {
|
||||
check(bls_pop_verify(decode_bls_public_key_to_g1(pk), decode_bls_signature_to_g2(sig)), "pop verify failed");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void g1baseb4enc(const std::vector<char>& g1, const std::string& base64 ) {
|
||||
check(g1.size() == std::tuple_size<bls_g1>::value, "wrong g1 size passed");
|
||||
|
||||
check(encode_g1_to_bls_public_key(*reinterpret_cast<const bls_g1*>(g1.data())) == base64, "g1 to base64 encoding doesn't match" );
|
||||
check(decode_bls_public_key_to_g1(base64) == *reinterpret_cast<const bls_g1*>(g1.data()), "base64 to g1 decoding doesn't match" );
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void sigbaseb4enc(const std::vector<char>& g2, const std::string& base64) {
|
||||
check(g2.size() == std::tuple_size<bls_g2>::value, "wrong g2 size passed");
|
||||
check(encode_g2_to_bls_signature(*reinterpret_cast<const bls_g2*>(g2.data())) == base64, "g2 to base64 encoding doesn't match" );
|
||||
check(decode_bls_signature_to_g2(base64) == *reinterpret_cast<const bls_g2*>(g2.data()), "base64 to g2 decoding doesn't match" );
|
||||
}
|
||||
|
||||
// caller of verify() must use this msg
|
||||
std::vector<uint8_t> msg = {51, 23, 56, 93, 212, 129, 128, 27, 251, 12, 42, 129, 210, 9, 34, 98};
|
||||
|
||||
[[eosio::action]]
|
||||
void verifyraw(const std::vector<char>& pk, const std::vector<char>& sig) {
|
||||
check(pk.size() == std::tuple_size<bls_g1>::value, "wrong pk size passed");
|
||||
check(sig.size() == std::tuple_size<bls_g2>::value, "wrong sig size passed");
|
||||
|
||||
std::string msg_str(msg.begin(), msg.end());
|
||||
check(bls_signature_verify(*reinterpret_cast<const bls_g1*>(pk.data()), *reinterpret_cast<const bls_g2*>(sig.data()), msg_str), "signature verify failed");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void verify(const std::string& pk, const std::string& sig, const std::string& msg) {
|
||||
check(bls_signature_verify(decode_bls_public_key_to_g1(pk), decode_bls_signature_to_g2(sig), msg), "signature verify failed");
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <eosio/call.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void test_call( void ) {
|
||||
call(0, 0, NULL, 0);
|
||||
get_call_return_value(NULL, 0);
|
||||
get_call_data(NULL, 0);
|
||||
set_call_return_value(NULL, 0);
|
||||
}
|
||||
@@ -9,6 +9,7 @@ void test_print( void );
|
||||
void test_privileged( void );
|
||||
void test_system( void );
|
||||
void test_transaction( void );
|
||||
void test_call( void );
|
||||
|
||||
void apply( uint64_t a, uint64_t b, uint64_t c ) {
|
||||
if(a != 0xed234054a367196eull) return; // random value that should not be used
|
||||
@@ -21,4 +22,5 @@ void apply( uint64_t a, uint64_t b, uint64_t c ) {
|
||||
test_privileged();
|
||||
test_system();
|
||||
test_transaction();
|
||||
test_call();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <eosio/privileged.h>
|
||||
#include <eosio/instant_finality.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void test_privileged( void ) {
|
||||
@@ -11,4 +12,5 @@ void test_privileged( void ) {
|
||||
set_blockchain_parameters_packed(NULL, 0);
|
||||
get_blockchain_parameters_packed(NULL, 0);
|
||||
preactivate_feature(NULL);
|
||||
set_finalizers(0, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <eosio/eosio.hpp>
|
||||
#include <eosio/instant_finality.hpp>
|
||||
|
||||
class [[eosio::contract]] instant_finality_tests : public eosio::contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::action]]
|
||||
void setfinalizer(const eosio::finalizer_policy& finalizer_policy) {
|
||||
eosio::set_finalizers(finalizer_policy);
|
||||
}
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <eosio/eosio.hpp>
|
||||
#include <eosio/transaction.hpp>
|
||||
#include <eosio/deferred_transaction.hpp>
|
||||
#include <eosio/bitset.hpp>
|
||||
|
||||
#include "transfer.hpp"
|
||||
|
||||
@@ -51,7 +52,7 @@ class [[eosio::contract]] simple_tests : public contract {
|
||||
|
||||
[[eosio::action]]
|
||||
void testd(name nm) {
|
||||
transaction t;
|
||||
deferred_transaction t;
|
||||
action act;
|
||||
act.account = "other"_n;
|
||||
act.name = "testc"_n;
|
||||
@@ -61,6 +62,17 @@ class [[eosio::contract]] simple_tests : public contract {
|
||||
t.send(nm.value, get_self());
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
eosio::bitset testbs(eosio::bitset b) {
|
||||
for (size_t i=0; i<b.size(); ++i) {
|
||||
if (b[i])
|
||||
b.clear(i);
|
||||
else
|
||||
b.set(i);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
[[eosio::on_notify("eosio.token::transfer")]]
|
||||
void on_transfer(name from, name to, asset quant, std::string memo) {
|
||||
check(get_first_receiver() == "eosio.token"_n, "should be eosio.token");
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#include "sync_call_addr_book_callee.hpp"
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
using namespace eosio;
|
||||
|
||||
void sync_call_addr_book_callee::upsert(name user, std::string first_name, std::string street) {
|
||||
// Intentionally leave out require_auth(user) to test upsert cannot be called as a read_only
|
||||
// sync call
|
||||
|
||||
address_index addresses(get_first_receiver(), get_first_receiver().value);
|
||||
auto iterator = addresses.find(user.value);
|
||||
if( iterator == addresses.end() )
|
||||
{
|
||||
addresses.emplace(user, [&]( auto& row ) {
|
||||
row.key = user;
|
||||
row.first_name = first_name;
|
||||
row.street = street;
|
||||
});
|
||||
}
|
||||
else {
|
||||
addresses.modify(iterator, user, [&]( auto& row ) {
|
||||
row.key = user;
|
||||
row.first_name = first_name;
|
||||
row.street = street;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
person_info sync_call_addr_book_callee::get(name user) {
|
||||
address_index addresses(get_first_receiver(), get_first_receiver().value);
|
||||
|
||||
auto iterator = addresses.find(user.value);
|
||||
check(iterator != addresses.end(), "Record does not exist");
|
||||
|
||||
return person_info{ .first_name = iterator->first_name,
|
||||
.street = iterator->street };
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <eosio/call.hpp>
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
struct person_info {
|
||||
std::string first_name;
|
||||
std::string street;
|
||||
};
|
||||
|
||||
class [[eosio::contract]] sync_call_addr_book_callee : public eosio::contract {
|
||||
public:
|
||||
sync_call_addr_book_callee(eosio::name receiver, eosio::name code, eosio::datastream<const char*> ds): contract(receiver, code, ds) {}
|
||||
|
||||
[[eosio::call]]
|
||||
void upsert(eosio::name user, std::string first_name, std::string street);
|
||||
|
||||
[[eosio::call]]
|
||||
person_info get(eosio::name user);
|
||||
|
||||
using upsert_read_only_func = eosio::call_wrapper<"upsert"_i, &sync_call_addr_book_callee::upsert, eosio::access_mode::read_only>;
|
||||
using upsert_func = eosio::call_wrapper<"upsert"_i, &sync_call_addr_book_callee::upsert>;
|
||||
using get_func = eosio::call_wrapper<"get"_i, &sync_call_addr_book_callee::get>;
|
||||
|
||||
private:
|
||||
struct [[eosio::table]] person {
|
||||
eosio::name key;
|
||||
std::string first_name;
|
||||
std::string street;
|
||||
|
||||
uint64_t primary_key() const { return key.value; }
|
||||
};
|
||||
|
||||
using address_index = eosio::multi_index<"people"_n, person>;
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "sync_call_addr_book_callee.hpp"
|
||||
|
||||
#include <eosio/eosio.hpp>
|
||||
#include <eosio/call.hpp>
|
||||
|
||||
class [[eosio::contract]] sync_call_addr_book_caller : public eosio::contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
// Insert an entry using read_only, which will fail
|
||||
[[eosio::action]]
|
||||
void upsertrdonly(eosio::name user, std::string first_name, std::string street) {
|
||||
sync_call_addr_book_callee::upsert_read_only_func{"callee"_n}(user, first_name, street);
|
||||
}
|
||||
|
||||
// Insert an entry
|
||||
[[eosio::action]]
|
||||
void upsert(eosio::name user, std::string first_name, std::string street) {
|
||||
sync_call_addr_book_callee::upsert_func{"callee"_n}(user, first_name, street);
|
||||
}
|
||||
|
||||
// Read an entry
|
||||
[[eosio::action]]
|
||||
person_info get(eosio::name user) {
|
||||
auto user_info = sync_call_addr_book_callee::get_func{"callee"_n}(user);
|
||||
eosio::check(user_info.first_name == "alice", "first name not alice");
|
||||
eosio::check(user_info.street == "123 Main St.", "street not 123 Main St.");
|
||||
return user_info;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "sync_call_callee.hpp"
|
||||
#include <eosio/print.hpp>
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t sync_call_callee::return_ten() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t sync_call_callee::echo_input(uint32_t in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
[[eosio::call]]
|
||||
void sync_call_callee::void_func() {
|
||||
eosio::print("I am a void function");
|
||||
}
|
||||
|
||||
[[eosio::action, eosio::call]]
|
||||
uint32_t sync_call_callee::sum(uint32_t a, uint32_t b, uint32_t c) {
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
[[eosio::call]]
|
||||
struct1_t sync_call_callee::pass_single_struct(struct1_t s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
[[eosio::call]]
|
||||
struct1_t sync_call_callee::pass_multi_structs(struct1_t s1, int32_t m, struct2_t s2) {
|
||||
return { .a = s1.a * m + s2.c, .b = s1.b * m + s2.d };
|
||||
}
|
||||
|
||||
bool sync_call_callee::issynccall() {
|
||||
return is_sync_call();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#include <eosio/call.hpp>
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
struct struct1_t {
|
||||
int64_t a;
|
||||
uint64_t b;
|
||||
};
|
||||
|
||||
struct struct2_t {
|
||||
char a;
|
||||
bool b;
|
||||
int64_t c;
|
||||
uint64_t d;
|
||||
};
|
||||
|
||||
class [[eosio::contract]] sync_call_callee : public eosio::contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t return_ten();
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t echo_input(uint32_t in);
|
||||
|
||||
[[eosio::call]]
|
||||
void void_func();
|
||||
|
||||
[[eosio::action, eosio::call]]
|
||||
uint32_t sum(uint32_t a, uint32_t b, uint32_t c);
|
||||
|
||||
// pass in a struct and return it
|
||||
[[eosio::call]]
|
||||
struct1_t pass_single_struct(struct1_t s);
|
||||
|
||||
// pass in two structs and an integer, multiply each field in the struct by
|
||||
// the integer, add last two fields of the second struct, and return the result
|
||||
[[eosio::call]]
|
||||
struct1_t pass_multi_structs(struct1_t s1, int32_t m, struct2_t s2);
|
||||
|
||||
// return is_sync_call()
|
||||
[[eosio::action, eosio::call]]
|
||||
bool issynccall();
|
||||
using issynccall_func = eosio::call_wrapper<"issynccall"_i, &sync_call_callee::issynccall>;
|
||||
|
||||
using return_ten_func = eosio::call_wrapper<"return_ten"_i, &sync_call_callee::return_ten>;
|
||||
using echo_input_func = eosio::call_wrapper<"echo_input"_i, &sync_call_callee::echo_input>;
|
||||
using void_func_func = eosio::call_wrapper<"void_func"_i, &sync_call_callee::void_func>;
|
||||
using sum_func = eosio::call_wrapper<"sum"_i, &sync_call_callee::sum>;
|
||||
using pass_single_struct_func = eosio::call_wrapper<"pass_single_struct"_i, &sync_call_callee::pass_single_struct>;
|
||||
using pass_multi_structs_func = eosio::call_wrapper<"pass_multi_structs"_i, &sync_call_callee::pass_multi_structs>;
|
||||
|
||||
using void_no_op_success_func = eosio::call_wrapper<"void_func"_i, &sync_call_callee::void_func, eosio::access_mode::read_write, eosio::support_mode::no_op>;
|
||||
using sum_no_op_success_func = eosio::call_wrapper<"sum"_i, &sync_call_callee::sum, eosio::access_mode::read_write, eosio::support_mode::no_op>;
|
||||
};
|
||||
@@ -0,0 +1,182 @@
|
||||
#include "sync_call_callee.hpp"
|
||||
#include "sync_call_not_supported.hpp"
|
||||
|
||||
#include <eosio/eosio.hpp>
|
||||
#include <eosio/call.hpp>
|
||||
|
||||
using namespace eosio;
|
||||
|
||||
class [[eosio::contract]] sync_call_caller : public eosio::contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
// Using host function directly
|
||||
[[eosio::action]]
|
||||
void hstretvaltst() {
|
||||
call_data_header header{ .version = 0, .func_name = "return_ten"_i.id };
|
||||
const std::vector<char> data{ eosio::pack(header) };
|
||||
auto expected_size = eosio::call("callee"_n, 0, data.data(), data.size());
|
||||
eosio::check(expected_size >= 0, "call did not return a positive value");
|
||||
|
||||
std::vector<char> return_value;
|
||||
return_value.resize(expected_size);
|
||||
auto actual_size = eosio::get_call_return_value(return_value.data(), return_value.size());
|
||||
eosio::check(actual_size == expected_size, "actual_size not equal to expected_size");
|
||||
eosio::check(eosio::unpack<uint32_t>(return_value) == 10u, "return value not 10"); // return_ten always returns 10
|
||||
}
|
||||
|
||||
// Using call_wrapper
|
||||
[[eosio::action]]
|
||||
void wrpretvaltst() {
|
||||
sync_call_callee::return_ten_func return_ten{ "callee"_n };
|
||||
eosio::check(return_ten() == 10u, "return value not 10");
|
||||
}
|
||||
|
||||
// Using host function directly, testing one parameter passing
|
||||
[[eosio::action]]
|
||||
void hstoneprmtst() {
|
||||
// `echo_input(uint32_t p)` returns p
|
||||
call_data_header header{ .version = 0, .func_name = "echo_input"_i.id };
|
||||
const std::vector<char> data{ eosio::pack(std::make_tuple(header, 5)) };
|
||||
auto expected_size = eosio::call("callee"_n, 0, data.data(), data.size());
|
||||
eosio::check(expected_size >= 0, "call did not return a positive value");
|
||||
|
||||
std::vector<char> return_value;
|
||||
return_value.resize(expected_size);
|
||||
auto actual_size = eosio::get_call_return_value(return_value.data(), return_value.size());
|
||||
eosio::check(actual_size == expected_size, "actual_size not equal to expected_size");
|
||||
eosio::check(eosio::unpack<uint32_t>(return_value) == 5u, "return value not 5"); // echo_input returns back the same value of parameter
|
||||
}
|
||||
|
||||
// Using call_wrapper, testing one parameter passing
|
||||
[[eosio::action]]
|
||||
void wrponeprmtst() {
|
||||
sync_call_callee::echo_input_func echo_input{ "callee"_n };
|
||||
eosio::check(echo_input(5) == 5u, "return value not 5");
|
||||
}
|
||||
|
||||
// Using host function directly, testing multiple parameters passing
|
||||
[[eosio::action]]
|
||||
void hstmulprmtst() {
|
||||
call_data_header header{ .version = 0, .func_name = "sum"_i.id };
|
||||
const std::vector<char> data{ eosio::pack(std::make_tuple(header, 10, 20, 30)) };
|
||||
auto expected_size = eosio::call("callee"_n, 0, data.data(), data.size());
|
||||
eosio::check(expected_size >= 0, "call did not return a positive value");
|
||||
|
||||
std::vector<char> return_value;
|
||||
return_value.resize(expected_size);
|
||||
auto actual_size = eosio::get_call_return_value(return_value.data(), return_value.size());
|
||||
eosio::check(actual_size == expected_size, "actual_size not equal to expected_size");
|
||||
eosio::check(eosio::unpack<uint32_t>(return_value) == 60u, "sum of 10, 20, and 30 not 60"); // sum returns the sum of the 3 arguments
|
||||
}
|
||||
|
||||
// Using call_wrapper, testing multiple parameters passing
|
||||
[[eosio::action]]
|
||||
void wrpmulprmtst() {
|
||||
sync_call_callee::sum_func sum{ "callee"_n };
|
||||
eosio::check(sum(10, 20, 30) == 60u, "sum of 10, 20, and 30 not 60");
|
||||
}
|
||||
|
||||
// Verify single struct parameter passing
|
||||
[[eosio::action]]
|
||||
void structtest() {
|
||||
sync_call_callee::pass_single_struct_func func{ "callee"_n };
|
||||
struct1_t input = { 10, 20 };
|
||||
auto output = func(input); // pass_single_struct_func returns the input as is
|
||||
eosio::check(output.a == input.a, "field a in output is not equal to a in input");
|
||||
eosio::check(output.b == input.b, "field b in output is not equal to b in input");
|
||||
}
|
||||
|
||||
// Verify mix of struct and integer parameters passing
|
||||
[[eosio::action]]
|
||||
void structinttst() {
|
||||
sync_call_callee::pass_multi_structs_func func{ "callee"_n };
|
||||
struct1_t input1 = { 10, 20 };
|
||||
struct2_t input2 = { 'a', true, 50, 100 };
|
||||
int32_t m = 2;
|
||||
|
||||
// pass_multi_structs_func multiply each field of input1 by m,
|
||||
// add last two fields of input2, and return a struct1_t
|
||||
auto output = func(input1, m, input2);
|
||||
eosio::check(output.a == m * input1.a + input2.c, "field a of output is not correct");
|
||||
eosio::check(output.b == m * input1.b + input2.d, "field b of output is not correct");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void hstvodfuntst() {
|
||||
call_data_header header{ .version = 0, .func_name = "void_func"_i.id };
|
||||
const std::vector<char> data{ eosio::pack(header) };
|
||||
auto expected_size = eosio::call("callee"_n, 0, data.data(), data.size());
|
||||
eosio::check(expected_size == 0, "call did not return 0"); // void function. return value size should be 0
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void wrpvodfuntst() {
|
||||
sync_call_callee::void_func_func void_func{ "callee"_n };
|
||||
void_func();
|
||||
}
|
||||
|
||||
// Verify void call. void_func uses default support_mode::abort
|
||||
[[eosio::action]]
|
||||
void voidfncabort() {
|
||||
sync_call_not_supported::void_func void_func_abort{ "callee"_n };
|
||||
void_func_abort(); // Will throw. Tester will verify that.
|
||||
}
|
||||
|
||||
// void_func uses support_mode::no_op
|
||||
[[eosio::action]]
|
||||
void voidfncnoop() {
|
||||
sync_call_not_supported::void_no_op_func void_func_no_op{ "callee"_n };
|
||||
check(void_func_no_op() == std::nullopt, "void_func_io_op did not return std::nullopt");
|
||||
}
|
||||
|
||||
// verify non-void call. int_func uses default support_mode::abort
|
||||
[[eosio::action]]
|
||||
void intfuncabort() {
|
||||
sync_call_not_supported::int_func int_func_abort{ "callee"_n };
|
||||
int_func_abort(); // Will throw. Tester will verify that.
|
||||
}
|
||||
|
||||
// int_func uses support_mode::no_opabort
|
||||
[[eosio::action]]
|
||||
void intfuncnoop() {
|
||||
sync_call_not_supported::int_no_op_func int_func_no_op{ "callee"_n };
|
||||
check(int_func_no_op() == std::nullopt, "void_func_io_op did not return std::nullopt");
|
||||
}
|
||||
|
||||
// void_io_op_success_func uses support_mode::no_op
|
||||
[[eosio::action]]
|
||||
void voidnoopsucc() {
|
||||
sync_call_callee::void_no_op_success_func f{ "callee"_n };
|
||||
check(f().has_value(), "void_io_op_success_func did not return a value");
|
||||
}
|
||||
|
||||
// void_io_op_success_func uses support_mode::no_op
|
||||
[[eosio::action]]
|
||||
void sumnoopsucc() {
|
||||
sync_call_callee::sum_no_op_success_func f{ "callee"_n };
|
||||
check(*f(7, 8, 9) == 24, "sum_io_op_success_func did not return a value");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void hdrvaltest() {
|
||||
// Verify function name validation works
|
||||
call_data_header unkwn_func_header{ .version = 0, .func_name = "unknwnfunc"_i.id };
|
||||
const std::vector<char> unkwn_func_data{ eosio::pack(unkwn_func_header) }; // unknwnfunc is not in "callee"_i contract
|
||||
auto status = eosio::call("callee"_n, 0, unkwn_func_data.data(), unkwn_func_data.size());
|
||||
eosio::check(status == -10001, "call did not return -10001 for unknown function");
|
||||
|
||||
// Verify version validation works
|
||||
call_data_header bad_version_header{ .version = 1, .func_name = "sum"_i.id }; // version 1 is not supported
|
||||
const std::vector<char> bad_version_data{ eosio::pack(bad_version_header) };
|
||||
status = eosio::call("callee"_n, 0, bad_version_data.data(), bad_version_data.size());
|
||||
eosio::check(status == -10000, "call did not return -10000 for invalid version");
|
||||
}
|
||||
|
||||
// Call issynccall as a sync call and return its return value
|
||||
[[eosio::action]]
|
||||
bool makesynccall() {
|
||||
sync_call_callee::issynccall_func is_sync_call_func{ "callee"_n };
|
||||
return is_sync_call_func();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This contract is used to verify customized sync_call entry function works.
|
||||
* It verifies customized sync_call entry is exported, and `call()` host function
|
||||
* can reach it.
|
||||
*/
|
||||
|
||||
#include <eosio/eosio.hpp>
|
||||
#include <eosio/call.hpp>
|
||||
|
||||
namespace eosio {
|
||||
|
||||
class [[eosio::contract]] sync_call_cust_entry : public contract {
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::action]]
|
||||
void cusentrytst1() {
|
||||
// Make a sync call to "receiver"_n account, pass function ID in `data`,
|
||||
// go to `sync_call()` entry function, and dispatch the call to `get_10()`
|
||||
// based on the function ID.
|
||||
const std::vector<char> data{ eosio::pack(1) }; // function ID 1
|
||||
eosio::call("receiver"_n, 0, data.data(), data.size());
|
||||
|
||||
// Retrieve return value and unpack it
|
||||
std::vector<char> return_value(sizeof(uint32_t));
|
||||
eosio::get_call_return_value(return_value.data(), return_value.size());
|
||||
|
||||
// Verify it
|
||||
eosio::check(eosio::unpack<uint32_t>(return_value) == 10, "return value is not 10");
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
void cusentrytst2() {
|
||||
// Make a sync call to "receiver"_n account, pass function ID in `data`,
|
||||
// go to `sync_call()` entry function, and dispatch the call to `get_20()`
|
||||
// based on the function ID.
|
||||
const std::vector<char> data{ eosio::pack(2) }; // function ID 2
|
||||
eosio::call("receiver"_n, 0, data.data(), data.size());
|
||||
|
||||
// Retrieve return value and unpack it
|
||||
std::vector<char> return_value(sizeof(uint32_t));
|
||||
eosio::get_call_return_value(return_value.data(), return_value.size());
|
||||
|
||||
// Verify it
|
||||
eosio::check(eosio::unpack<uint32_t>(return_value) == 20, "return value is not 20");
|
||||
}
|
||||
|
||||
// `eosio::call` tag is optional
|
||||
uint32_t get_10() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t get_20() {
|
||||
return 20;
|
||||
}
|
||||
};
|
||||
} /// namespace eosio
|
||||
|
||||
extern "C" {
|
||||
[[eosio::wasm_entry]]
|
||||
int64_t sync_call(uint64_t sender, uint64_t receiver, uint32_t data_size) {
|
||||
eosio::datastream<const char*> ds(nullptr, 0); // for testing, not used
|
||||
eosio::sync_call_cust_entry obj(eosio::name{receiver}, eosio::name{receiver}, ds);
|
||||
|
||||
std::vector<char> data(sizeof(uint32_t));
|
||||
eosio::get_call_data(data.data(), data.size());
|
||||
auto func_id = eosio::unpack<uint32_t>(data);
|
||||
|
||||
// Dispatch sync calls
|
||||
uint32_t rv = 0;
|
||||
switch (func_id) {
|
||||
case 1: rv = obj.get_10(); break;
|
||||
case 2: rv = obj.get_20(); break;
|
||||
default: eosio::check(false, "wrong function ID");
|
||||
}
|
||||
|
||||
// set return value
|
||||
eosio::set_call_return_value(&rv, sizeof(uint32_t));
|
||||
|
||||
return 0; // return 0 to indicate success
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "sync_call_not_supported.hpp"
|
||||
|
||||
[[eosio::action]]
|
||||
void sync_call_not_supported::voidfunc() {
|
||||
}
|
||||
|
||||
[[eosio::action]]
|
||||
int sync_call_not_supported::intfunc() {
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include <eosio/eosio.hpp>
|
||||
#include <eosio/call.hpp>
|
||||
|
||||
// Because this contract does not tag any functions by `call` attribute,
|
||||
// `sync_call` entry point is not generated.
|
||||
// Any sync calls to this contract will return a status indicating
|
||||
// sync calls are not supported by the receiver.
|
||||
class [[eosio::contract]] sync_call_not_supported : public eosio::contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::action]]
|
||||
void voidfunc();
|
||||
|
||||
[[eosio::action]]
|
||||
int intfunc();
|
||||
|
||||
using void_func = eosio::call_wrapper<"voidfunc"_i, &sync_call_not_supported::voidfunc>; // default behavior: abort when called
|
||||
using void_no_op_func = eosio::call_wrapper<"voidfunc"_i, &sync_call_not_supported::voidfunc, eosio::access_mode::read_write, eosio::support_mode::no_op>; // no op when called
|
||||
|
||||
using int_func = eosio::call_wrapper<"intfunc"_i, &sync_call_not_supported::intfunc>; // default behavior: abort when called
|
||||
using int_no_op_func = eosio::call_wrapper<"intfunc"_i, &sync_call_not_supported::intfunc, eosio::access_mode::read_write, eosio::support_mode::no_op>; // no op when called
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <eosio/call.hpp>
|
||||
#include <eosio/print.hpp>
|
||||
#include <eosio/eosio.hpp>
|
||||
|
||||
class [[eosio::contract]] sync_call_single_func : public eosio::contract{
|
||||
public:
|
||||
using contract::contract;
|
||||
|
||||
[[eosio::call]]
|
||||
uint32_t return_ten() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
// Do NOT add any more functions tagged as `eosio::call` in this contract.
|
||||
// It is used to test a contract having only one function tagged as `eosio::call`.
|
||||
};
|
||||
@@ -64,7 +64,15 @@ void generate(const std::vector<std::string>& base_options, std::string input, s
|
||||
|
||||
abigen::get().set_contract_name(contract_name);
|
||||
abigen::get().set_resource_dirs(resource_paths);
|
||||
abigen::get().set_abi_version(std::get<0>(abi_version), std::get<1>(abi_version));
|
||||
|
||||
// We used to accept a command line option `--abi-version` which allowed a user to force an abi version
|
||||
// to be generated.
|
||||
// Since https://github.com/AntelopeIO/cdt/pull/360, this command line flag is ignored, and the abi
|
||||
// version is generated according to the features used in the contract being compiled, starting from a
|
||||
// base `1.2` version and up.
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
// abigen::get().set_abi_version(std::get<0>(abi_version), std::get<1>(abi_version));
|
||||
|
||||
abigen::get().set_suppress_ricardian_warning(suppress_ricardian_warning);
|
||||
codegen::get().set_contract_name(contract_name);
|
||||
codegen::get().set_warn_action_read_only(warn_action_read_only);
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
add_subdirectory(wabt)
|
||||
add_subdirectory(wabt)
|
||||
|
||||
@@ -80,9 +80,9 @@ static cl::opt<bool> fno_lto_opt(
|
||||
"fno-lto",
|
||||
cl::desc("Disable LTO"),
|
||||
cl::cat(LD_CAT));
|
||||
static cl::opt<bool> fno_cfl_aa_opt(
|
||||
"fno-cfl-aa",
|
||||
cl::desc("Disable CFL Alias Analysis"),
|
||||
static cl::opt<bool> fcfl_aa_opt(
|
||||
"fcfl-aa",
|
||||
cl::desc("Enable CFL Alias Analysis"),
|
||||
cl::cat(LD_CAT));
|
||||
static cl::opt<bool> fno_stack_first_opt(
|
||||
"fno-stack-first",
|
||||
@@ -508,6 +508,8 @@ static void GetLdDefaults(std::vector<std::string>& ldopts) {
|
||||
else
|
||||
ldopts.insert(ldopts.end(), { "-e", "apply" });
|
||||
ldopts.insert(ldopts.end(), { "--only-export", "apply:function" });
|
||||
ldopts.insert(ldopts.end(), { "--only-export", "*:memory" });
|
||||
ldopts.insert(ldopts.end(), { "--only-export", "sync_call:function" });
|
||||
}
|
||||
ldopts.emplace_back("-lc++");
|
||||
ldopts.emplace_back("-lc");
|
||||
@@ -616,7 +618,7 @@ static Options CreateOptions(bool add_defaults=true) {
|
||||
else
|
||||
pp_dir = eosio::cdt::whereami::where();
|
||||
|
||||
if (!fno_cfl_aa_opt) {
|
||||
if (fcfl_aa_opt) {
|
||||
copts.emplace_back("-mllvm");
|
||||
copts.emplace_back("-use-cfl-aa-in-codegen=both");
|
||||
agopts.emplace_back("-mllvm");
|
||||
@@ -946,9 +948,13 @@ static Options CreateOptions(bool add_defaults=true) {
|
||||
|
||||
#endif
|
||||
|
||||
// 1.2 -- action results
|
||||
// 1.3 -- sync calls, bitset type, action and sync call names in C++
|
||||
// identifier format
|
||||
|
||||
/* TODO add some way of defaulting these to the current highest version */
|
||||
int abi_version_major = 1;
|
||||
int abi_version_minor = 2;
|
||||
int abi_version_minor = 3;
|
||||
|
||||
if (!abi_version_opt.empty()) {
|
||||
abi_version_major = std::stoi(abi_version_opt);
|
||||
|
||||
@@ -30,6 +30,14 @@ struct abi_action {
|
||||
bool operator<(const abi_action& s) const { return name < s.name; }
|
||||
};
|
||||
|
||||
struct abi_call {
|
||||
std::string name;
|
||||
std::string type;
|
||||
uint64_t id = 0; // internal short ID of `name`
|
||||
std::string result_type;
|
||||
bool operator<(const abi_call& s) const { return name < s.name; }
|
||||
};
|
||||
|
||||
struct abi_table {
|
||||
std::string name;
|
||||
std::string type;
|
||||
@@ -61,19 +69,43 @@ struct abi_action_result {
|
||||
bool operator<(const abi_action_result& ar) const { return name < ar.name; }
|
||||
};
|
||||
|
||||
struct version_t {
|
||||
uint8_t major = 0;
|
||||
uint8_t minor = 0;
|
||||
|
||||
version_t(uint8_t major, uint8_t minor)
|
||||
: major(major)
|
||||
, minor(minor) {}
|
||||
|
||||
friend bool operator<(const version_t& a, const version_t& b) {
|
||||
return std::tie(a.major, a.minor) < std::tie(b.major, b.minor);
|
||||
}
|
||||
friend bool operator==(const version_t& a, const version_t& b) {
|
||||
return std::tie(a.major, a.minor) == std::tie(b.major, b.minor);
|
||||
}
|
||||
|
||||
void set_min(version_t o) {
|
||||
if (*this < o)
|
||||
*this = o;
|
||||
}
|
||||
|
||||
std::string str() const { return std::to_string(major) + "." + std::to_string(minor); }
|
||||
};
|
||||
|
||||
/// From eosio libraries/chain/include/eosio/chain/abi_def.hpp
|
||||
struct abi {
|
||||
int version_major = 1;
|
||||
int version_minor = 1;
|
||||
std::string version_string()const { return std::string("eosio::abi/")+std::to_string(version_major)+"."+std::to_string(version_minor); }
|
||||
version_t version{1,2}; // base version is 1.2, add features (bitset, sync calls) push to 1.3
|
||||
std::set<abi_struct> structs;
|
||||
std::set<abi_typedef> typedefs;
|
||||
std::set<abi_action> actions;
|
||||
std::set<abi_call> calls;
|
||||
std::set<abi_table> tables;
|
||||
std::set<abi_variant> variants;
|
||||
std::vector<abi_ricardian_clause_pair> ricardian_clauses;
|
||||
std::vector<abi_error_message> error_messages;
|
||||
std::set<abi_action_result> action_results;
|
||||
|
||||
std::string version_string() const { return std::string("eosio::abi/")+version.str(); }
|
||||
};
|
||||
|
||||
inline void dump( const abi& abi ) {
|
||||
|
||||
+104
-13
@@ -26,6 +26,7 @@
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <map>
|
||||
#include <array>
|
||||
#include <jsoncons/json.hpp>
|
||||
@@ -36,7 +37,11 @@ using namespace eosio::cdt;
|
||||
using jsoncons::json;
|
||||
using jsoncons::ojson;
|
||||
|
||||
namespace eosio { namespace cdt {
|
||||
namespace eosio::cdt {
|
||||
|
||||
const version_t bitset_min_version{1,3};
|
||||
const version_t sync_calls_min_version{1,3};
|
||||
|
||||
class abigen : public generation_utils {
|
||||
std::set<std::string> checked_actions;
|
||||
public:
|
||||
@@ -48,8 +53,7 @@ namespace eosio { namespace cdt {
|
||||
}
|
||||
|
||||
void set_abi_version(int major, int minor) {
|
||||
_abi.version_major = major;
|
||||
_abi.version_minor = minor;
|
||||
_abi.version = version_t{static_cast<uint8_t>(major), static_cast<uint8_t>(minor)};
|
||||
}
|
||||
|
||||
void add_typedef( const clang::QualType& t ) {
|
||||
@@ -131,6 +135,50 @@ namespace eosio { namespace cdt {
|
||||
}
|
||||
}
|
||||
|
||||
void add_call( const clang::CXXRecordDecl* decl ) {
|
||||
abi_call ret;
|
||||
auto call_name = decl->getEosioCallAttr()->getName();
|
||||
|
||||
if (call_name.empty()) {
|
||||
validate_name(decl->getName().str(), [&](auto s) { CDT_ERROR("abigen_error", decl->getLocation(), s); });
|
||||
ret.name = decl->getName().str();
|
||||
}
|
||||
else {
|
||||
validate_name( call_name.str(), [&](auto s) { CDT_ERROR("abigen_error", decl->getLocation(), s); });
|
||||
ret.name = call_name.str();
|
||||
}
|
||||
ret.type = decl->getName().str();
|
||||
ret.id = to_hash_id(ret.name);
|
||||
_abi.calls.insert(ret);
|
||||
|
||||
_abi.version.set_min(sync_calls_min_version);
|
||||
}
|
||||
|
||||
void add_call( const clang::CXXMethodDecl* decl ) {
|
||||
abi_call ret;
|
||||
|
||||
auto call_name = decl->getEosioCallAttr()->getName();
|
||||
|
||||
if (call_name.empty()) {
|
||||
validate_hash_id( decl->getNameAsString(), [&](auto s) { CDT_ERROR("abigen_error", decl->getLocation(), s); } );
|
||||
ret.name = decl->getNameAsString();
|
||||
}
|
||||
else {
|
||||
validate_hash_id( call_name.str(), [&](auto s) { CDT_ERROR("abigen_error", decl->getLocation(), s); } );
|
||||
ret.name = call_name.str();
|
||||
}
|
||||
ret.type = decl->getNameAsString();
|
||||
ret.id = to_hash_id(ret.name);
|
||||
auto result_type = translate_type(decl->getReturnType());
|
||||
if (result_type != "void") {
|
||||
add_type(decl->getReturnType());
|
||||
ret.result_type = result_type;
|
||||
}
|
||||
_abi.calls.insert(ret);
|
||||
|
||||
_abi.version.set_min(sync_calls_min_version);
|
||||
}
|
||||
|
||||
void add_tuple(const clang::QualType& type) {
|
||||
auto pt = llvm::dyn_cast<clang::ElaboratedType>(type.getTypePtr());
|
||||
auto tst = llvm::dyn_cast<clang::TemplateSpecializationType>((pt) ? pt->desugar().getTypePtr() : type.getTypePtr());
|
||||
@@ -151,7 +199,6 @@ namespace eosio { namespace cdt {
|
||||
void add_pair(const clang::QualType& type) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
clang::QualType ftype = std::get<clang::QualType>(get_template_argument(type, i));
|
||||
std::string ty = translate_type(ftype);
|
||||
add_type(ftype);
|
||||
}
|
||||
abi_struct pair;
|
||||
@@ -216,6 +263,7 @@ namespace eosio { namespace cdt {
|
||||
void add_struct( const clang::CXXMethodDecl* decl ) {
|
||||
abi_struct new_struct;
|
||||
new_struct.name = decl->getNameAsString();
|
||||
|
||||
for (auto param : decl->parameters() ) {
|
||||
auto param_type = param->getType().getNonReferenceType().getUnqualifiedType();
|
||||
new_struct.fields.push_back({param->getNameAsString(), get_type(param_type)});
|
||||
@@ -480,7 +528,8 @@ namespace eosio { namespace cdt {
|
||||
add_explicit_nested_type(t.getNonReferenceType());
|
||||
return;
|
||||
}
|
||||
if (!is_builtin_type(translate_type(type))) {
|
||||
auto type_str = translate_type(type);
|
||||
if (!is_builtin_type(type_str)) {
|
||||
if (is_aliasing(type)) {
|
||||
add_typedef(type);
|
||||
}
|
||||
@@ -502,6 +551,13 @@ namespace eosio { namespace cdt {
|
||||
}
|
||||
else if (type.getTypePtr()->isRecordType())
|
||||
add_struct(type.getTypePtr()->getAsCXXRecordDecl());
|
||||
} else {
|
||||
static std::unordered_map<std::string, version_t> versioned_types {
|
||||
{ "bitset", bitset_min_version }
|
||||
};
|
||||
|
||||
if (auto it = versioned_types.find(type_str); it != versioned_types.end())
|
||||
_abi.version.set_min(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,6 +607,15 @@ namespace eosio { namespace cdt {
|
||||
return o;
|
||||
}
|
||||
|
||||
ojson call_to_json( const abi_call& c ) {
|
||||
ojson o;
|
||||
o["name"] = c.name;
|
||||
o["type"] = c.type;
|
||||
o["id"] = c.id;
|
||||
o["result_type"] = c.result_type;
|
||||
return o;
|
||||
}
|
||||
|
||||
ojson clause_to_json( const abi_ricardian_clause_pair& clause ) {
|
||||
ojson o;
|
||||
o["id"] = clause.id;
|
||||
@@ -593,13 +658,15 @@ namespace eosio { namespace cdt {
|
||||
set_of_tables.insert(t);
|
||||
}
|
||||
|
||||
return _abi.structs.empty() && _abi.typedefs.empty() && _abi.actions.empty() && set_of_tables.empty() && _abi.ricardian_clauses.empty() && _abi.variants.empty();
|
||||
return _abi.structs.empty() && _abi.typedefs.empty() && _abi.actions.empty() && _abi.calls.empty() && set_of_tables.empty() && _abi.ricardian_clauses.empty() && _abi.variants.empty();
|
||||
}
|
||||
|
||||
ojson to_json() {
|
||||
ojson o;
|
||||
o["____comment"] = generate_json_comment();
|
||||
|
||||
o["version"] = _abi.version_string();
|
||||
|
||||
o["structs"] = ojson::array();
|
||||
auto remove_suffix = [&]( std::string name ) {
|
||||
int i = name.length()-1;
|
||||
@@ -658,6 +725,10 @@ namespace eosio { namespace cdt {
|
||||
if (as.name == _translate_type(a.type))
|
||||
return true;
|
||||
}
|
||||
for ( auto a : _abi.calls ) {
|
||||
if (as.name == _translate_type(a.type))
|
||||
return true;
|
||||
}
|
||||
for( auto t : set_of_tables ) {
|
||||
if (as.name == _translate_type(t.type))
|
||||
return true;
|
||||
@@ -695,6 +766,9 @@ namespace eosio { namespace cdt {
|
||||
for ( auto a : _abi.actions )
|
||||
if ( a.type == td.new_type_name )
|
||||
return true;
|
||||
for ( auto a : _abi.calls )
|
||||
if ( a.type == td.new_type_name )
|
||||
return true;
|
||||
for ( auto _td : _abi.typedefs )
|
||||
if ( remove_suffix(_td.type) == td.new_type_name )
|
||||
return true;
|
||||
@@ -719,6 +793,12 @@ namespace eosio { namespace cdt {
|
||||
for ( auto a : _abi.actions ) {
|
||||
o["actions"].push_back(action_to_json( a ));
|
||||
}
|
||||
if (!_abi.calls.empty()) { // add calls section only when sync calls are used
|
||||
o["calls"] = ojson::array();
|
||||
for ( auto a : _abi.calls ) {
|
||||
o["calls"].push_back(call_to_json( a ));
|
||||
}
|
||||
}
|
||||
o["tables"] = ojson::array();
|
||||
for ( auto t : set_of_tables ) {
|
||||
o["tables"].push_back(table_to_json( t ));
|
||||
@@ -727,16 +807,17 @@ namespace eosio { namespace cdt {
|
||||
for ( auto rc : _abi.ricardian_clauses ) {
|
||||
o["ricardian_clauses"].push_back(clause_to_json( rc ));
|
||||
}
|
||||
|
||||
o["variants"] = ojson::array();
|
||||
for ( auto v : _abi.variants ) {
|
||||
o["variants"].push_back(variant_to_json( v ));
|
||||
}
|
||||
|
||||
o["abi_extensions"] = ojson::array();
|
||||
if (_abi.version_major == 1 && _abi.version_minor >= 2) {
|
||||
o["action_results"] = ojson::array();
|
||||
for ( auto ar : _abi.action_results ) {
|
||||
o["action_results"].push_back(action_result_to_json( ar ));
|
||||
}
|
||||
|
||||
o["action_results"] = ojson::array();
|
||||
for ( auto ar : _abi.action_results ) {
|
||||
o["action_results"].push_back(action_result_to_json( ar ));
|
||||
}
|
||||
return o;
|
||||
}
|
||||
@@ -778,6 +859,14 @@ namespace eosio { namespace cdt {
|
||||
ag.add_type( param->getType() );
|
||||
}
|
||||
}
|
||||
|
||||
if (decl->isEosioCall() && ag.is_eosio_contract(decl, ag.get_contract_name())) {
|
||||
ag.add_struct(decl);
|
||||
ag.add_call(decl);
|
||||
for (auto param : decl->parameters()) {
|
||||
ag.add_type( param->getType() );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool VisitCXXRecordDecl(clang::CXXRecordDecl* decl) {
|
||||
@@ -786,10 +875,12 @@ namespace eosio { namespace cdt {
|
||||
ag.add_contracts(ag.parse_contracts());
|
||||
has_added_clauses = true;
|
||||
}
|
||||
if ((decl->isEosioAction() || decl->isEosioTable()) && ag.is_eosio_contract(decl, ag.get_contract_name())) {
|
||||
if ((decl->isEosioAction() || decl->isEosioCall() || decl->isEosioTable()) && ag.is_eosio_contract(decl, ag.get_contract_name())) {
|
||||
ag.add_struct(decl);
|
||||
if (decl->isEosioAction())
|
||||
ag.add_action(decl);
|
||||
if (decl->isEosioCall())
|
||||
ag.add_call(decl);
|
||||
if (decl->isEosioTable())
|
||||
ag.add_table(decl);
|
||||
for (auto field : decl->fields()) {
|
||||
@@ -922,4 +1013,4 @@ namespace eosio { namespace cdt {
|
||||
return std::make_unique<eosio_abigen_consumer>(&CI, file);
|
||||
}
|
||||
};
|
||||
}} // ns eosio::cdt
|
||||
} // ns eosio::cdt
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user