Compare commits

..

102 Commits

Author SHA1 Message Date
Lin Huang 95077ed429 Bump Leap to release/3.1.5 2023-07-12 09:25:47 -04:00
Lin Huang 05e6cc8c18 Update eos-vm to release/3.x 2023-07-12 09:25:10 -04:00
Lin Huang 5caf5833ad A companion Leap changes for fixing WASM memory exhaustion 2023-07-12 09:18:25 -04:00
Peter Oschwald ed854f2bbd Merge pull request #1291 from AntelopeIO/pinned-builds-workflow-in-ci
[3.1] Pinned Builds manual dispatch workflow in CI
2023-06-22 11:38:59 -05:00
Peter Oschwald e3976b8dc1 Merge pull request #1310 from AntelopeIO/pinned_build_install_prefix_knob
[3.1] `CMAKE_INSTALL_PREFIX=/usr` for pinned builds in CI
2023-06-22 10:59:43 -05:00
Peter Oschwald 02c43ca656 Use enf-x86-beefy-long runner 2023-06-22 09:30:09 -05:00
Peter Oschwald 1ec98976b1 Try newly added self hosted runner for pinned builds. 2023-06-16 14:42:43 -05:00
Peter Oschwald 93833b8e03 Simplify naming and path matching for artifact. 2023-06-16 14:14:55 -05:00
Matt Witherspoon d6cd2c9a7d LEAP_PINNED_INSTALL_PREFIX knob to set pinned_build.sh CMAKE_INSTALL_PREFIX 2023-06-15 22:37:09 -04:00
Peter Oschwald ae2679e164 Cleanup. 2023-06-15 16:13:03 -05:00
Peter Oschwald 0f25eaa33a Remove quotes from path for upload. 2023-06-15 14:13:06 -05:00
Peter Oschwald b7b4554a18 Fix spelling causing issue with GITHUB_ENV. And trying again to get artifact name correctly. 2023-06-15 12:35:43 -05:00
Peter Oschwald 20e59a92bc Not finding deb packages. check dir structure some more. 2023-06-15 10:49:04 -05:00
Peter Oschwald 31fd1361aa Something is not matching up with expected dir or file structure. 2023-06-15 08:00:00 -05:00
Peter Oschwald 449f37133b Skip wildcards in upload-artifact and capture artifact name with regex grep and store in env variable. 2023-06-14 16:44:42 -05:00
Peter Oschwald feeee5eb8f Say yes. 2023-06-14 15:37:38 -05:00
Peter Oschwald 32de87b185 Update package lists first. 2023-06-14 15:35:28 -05:00
Peter Oschwald 78dd785035 Need software-properties-common and a apt-get update to get add-apt-repository to work. 2023-06-14 15:34:06 -05:00
Peter Oschwald f4b39ea29e Use single quotes. 2023-06-14 15:30:35 -05:00
Peter Oschwald 20f45e5923 Add conditional step to add updated apt repository for git.
Ubuntu 18.04 installs  git 2.17.1, but need 2.18+ for git submodules to work.
2023-06-14 15:27:18 -05:00
Peter Oschwald fc2166a46d Merge branch 'init-pinned-builds-workflow-in-ci' into pinned-builds-workflow-in-ci 2023-06-14 13:58:18 -05:00
Peter Oschwald 39a5ba846a Have to have a job for github. Add temp job. 2023-06-14 13:57:00 -05:00
Peter Oschwald e4b28a7854 Remove empty jobs section. 2023-06-14 13:54:13 -05:00
Peter Oschwald e4819c35e1 Merge branch 'init-pinned-builds-workflow-in-ci' into pinned-builds-workflow-in-ci 2023-06-14 13:51:11 -05:00
Peter Oschwald 7b7027cbee Not using cached build environments so removing this job. 2023-06-14 13:49:33 -05:00
Peter Oschwald 74fb1615d8 Add pinned to artifact name and don't upload dev artifact by filtering out in regex. 2023-06-14 13:02:32 -05:00
Peter Oschwald 5523010cfd Fix syntax and forgotten run command. 2023-06-14 13:00:00 -05:00
Peter Oschwald 7c106605cc Not using cached build environments so removing this job. 2023-06-14 12:16:11 -05:00
Peter Oschwald 9047d1175b For now run on github runner. 2023-06-14 12:05:12 -05:00
Peter Oschwald da6a068639 Script already runs cpack, remove. Break artifact check into own step for easier removal in future. 2023-06-14 12:03:27 -05:00
Peter Oschwald a886743005 Initial work to run pinned_build script on base images.
Build package and upload artifacts.
2023-06-14 11:44:53 -05:00
Peter Oschwald 0dbfb1a6ed Creating a shell of the initial pinned_build.yaml workflow to be merged quickly allowing development of actual workflow in follow on branch.
Need to have workflow file merged before github will allow triggering it in a development branch.
2023-06-14 11:26:08 -05:00
Huang-Ming Huang 9d1ea27ed7 Merge pull request #777 from AntelopeIO/huangminghuang/strike-rule
[3.1] subjective-account-max-failures-window-size
2023-03-07 08:19:34 -06:00
Huang-Ming Huang 71548a6425 Merge branch 'release/3.1' into huangminghuang/strike-rule 2023-03-06 09:37:22 -06:00
Huang-Ming Huang 72c5d299fe add reset time until back 2023-03-06 09:12:30 -06:00
Huang-Ming Huang 5cf31c9929 address PR comment 2023-03-06 08:21:26 -06:00
Kevin Heifner 941b525093 Merge pull request #773 from AntelopeIO/GH-768-logging-3.1
[3.1] Move subjective bill log to `all` level of `producer_plugin` logger.
2023-03-04 13:42:53 -06:00
Kevin Heifner e377339f04 GH-768 Move subjective bill log to all level of producer_plugin logger. 2023-03-03 07:10:23 -06:00
Huang-Ming Huang fcbdb0ae98 subjective-account-max-failures-window-size 2023-03-01 06:13:02 -06:00
Gregory Popovitch ecc5c4ec11 Merge pull request #754 from AntelopeIO/gh-513_rel3.1
[3.1] keosd - Exit program if keosd fails to aquire wallet lock (GH #513)
2023-02-27 10:39:15 -05:00
greg7mdp caa01ca443 main() should return if appbase initialization fails. 2023-02-25 14:39:25 -05:00
Alexander Molchevsky 3e585d0f8a Merge pull request #747 from AntelopeIO/update_bios_boot_tutorial3.1
Backport to 3.1 of bootstrap new protocol features activation
2023-02-24 12:38:21 +02:00
Alexander Molchevsky 967ab869e0 Backport to 3.1 of bootstrap new protocol features activation 2023-02-24 00:42:48 +02:00
Kevin Heifner 0d977585ce Merge pull request #700 from AntelopeIO/GH-695-dirty-db-3.1
[3.1] Fix reporting of dirty db
2023-02-10 08:15:54 -06:00
Kevin Heifner a357765c73 GH-695 Report dirty-db correctly 2023-02-08 08:07:14 -06:00
766C6164 280d799958 Added comment on why non-propagating system_error 2023-02-08 08:03:43 -06:00
766C6164 f694588f9f Propagate all exceptions minus system_error 2023-02-08 08:03:38 -06:00
Kevin Heifner 26025d7382 Merge pull request #684 from AntelopeIO/GH-662-terminate-at-block-3.1
[3.1] Fix --terminate-at-block to stop at correct block
2023-02-04 15:17:10 -06:00
Kevin Heifner 517ef20396 GH-662 Fixes for terminate-scenarios-test 2023-02-03 16:01:08 -06:00
Kevin Heifner 6f16383453 GH-662 Fix terminate-at-block test 2023-02-03 14:10:57 -06:00
Kevin Heifner debba62dd8 GH-662 Fix terminate-at-block to terminate at correct block 2023-02-03 14:10:38 -06:00
Kevin Heifner 343596a0c1 Merge pull request #676 from AntelopeIO/GH-588-handshake-3.1
[3.1] net_plugin improve block latency calculation
2023-02-02 14:47:12 -06:00
Kevin Heifner ec27d3d1f3 GH-588 Round using lround instead of the original hardcoded +1 2023-02-01 15:10:23 -06:00
Kevin Heifner f347ab534e GH-588 Add additional logging that would be helpful for debugging 2023-02-01 13:42:13 -06:00
Kevin Heifner 3db765e0f1 GH-588 Remove +1 to number of blocks latency calculation. With it 0 latency indicates 1 block latency. 2023-01-31 07:44:20 -06:00
Kevin Heifner 0dbd5cf68c Merge pull request #667 from AntelopeIO/GH-631-fork-test-3.1
[3.1] Test fix: nodeos_forked_chain_lr_test
2023-01-27 13:30:03 -06:00
Kevin Heifner da2a1dc996 GH-631 Update preKill info since waiting for producer to change before continuing. 2023-01-26 13:29:19 -06:00
Lin Huang 78973e4088 Merge pull request #651 from AntelopeIO/bump_to_3_1_4
bump Leap release to 3.1.4
2023-01-19 10:11:38 -05:00
Lin Huang d627a18e8e bump Leap release to 3.1.4 2023-01-19 09:27:35 -05:00
Kevin Heifner be7fc5714e Merge pull request #543 from AntelopeIO/GH-525-block-propagation-3.1
[3.1] Interrupt speculative start_block when a block is received
2023-01-18 12:13:35 -06:00
Kevin Heifner 2d6307b37e GH-525 rename start_block_interrupted to should_interrupt_start_block 2023-01-10 13:09:57 -06:00
Kevin Heifner 3d77eb001b GH-525 Add check for existing to be consistent 2023-01-10 13:09:04 -06:00
Kevin Heifner ef9b3ea1b6 Merge branch 'release/3.1' into GH-525-block-propagation-3.1 2023-01-10 07:00:41 -06:00
Kevin Heifner 943d113480 Merge pull request #606 from AntelopeIO/GH-605-dup-sync-stop-3.1
[3.1] Attempt connection retry for duplicate connections
2023-01-05 08:23:05 -06:00
Kevin Heifner 34b185d49b Merge branch 'release/3.1' into GH-605-dup-sync-stop-3.1 2022-12-30 10:42:56 -06:00
Kevin Heifner 79e99ad605 GH-605 Remove no_retry code from connect that was already in resolve_and_connect. connect is only called by resolve_and_connect. The no_retry code in connect didn't have the newly added re-connect for duplicate. 2022-12-30 10:37:31 -06:00
Luis Paris 6c9012874b Merge pull request #583 from AntelopeIO/fix-devrel#60b
[3.1] Update nodeos options help usage [docs]
2022-12-23 15:29:53 -05:00
Eric Passmore 278b94baf7 Merge pull request #569 from AntelopeIO/ehp/GH-547-producer-api-doc-cleanup-3.1
[3.1] Fixes Producer Plugin Schema Fixes and Better Alignment with OpenAPI spec
2022-12-19 17:06:02 -08:00
Eric Passmore 20b1da2b47 removed datatypes from descriptions 2022-12-19 13:45:24 -08:00
Luis 82ef97bf4e rename eos.io to example.org in net plugin help :doc 2022-12-19 16:23:27 -05:00
Luis cca0dc306e remove unsupported history plugin docs :doc 2022-12-19 14:57:45 -05:00
Luis 897edb9d9f update state history plugin options :doc 2022-12-19 14:56:06 -05:00
Luis f7c6b63cf7 update resource monitor plugin options and minor edits :doc 2022-12-19 14:54:09 -05:00
Luis 32d7d9f9fd update producer plugin options and minor edits :doc 2022-12-19 14:50:46 -05:00
Luis 97737fdd86 update net plugin options :doc 2022-12-19 14:47:12 -05:00
Luis 7a5930bb66 update http plugin options :doc 2022-12-19 14:45:17 -05:00
Luis 51d9cc22d7 update chain plugin options :doc 2022-12-19 14:33:22 -05:00
Luis ee1b184428 fix another small type that slipped :doc 2022-12-16 16:52:05 -05:00
Luis d34c40bd68 fix minor sentence contructions :doc 2022-12-16 16:36:47 -05:00
Luis a3bf1f54a1 minor edits and spelling corrections :doc 2022-12-16 16:33:15 -05:00
Kevin Heifner 9b5ec62e19 GH-525 Remove unused incoming::channels::transaction 2022-12-16 08:39:38 -06:00
Kevin Heifner 453e5d0975 GH-525 Add open_impl/close_impl so all methods of fork_database follow the same pattern. 2022-12-15 18:39:28 -06:00
Kevin Heifner 8f12805b4c GH-525 Minor cleanup from PR comments. 2022-12-15 15:12:10 -06:00
Kevin Heifner 9b1401aa4a GH-525 Only interrupt start_block for validated block_header. 2022-12-15 09:23:10 -06:00
Kevin Heifner b3391af3bf GH-525 Use shared_mutex to allow multiple readers 2022-12-15 08:15:44 -06:00
Kevin Heifner d0d7fa798b GH-525 Move scope_exit of schedule_production_loop since any call should restart block because speculative block may have been interrupted. 2022-12-15 08:15:32 -06:00
Kevin Heifner 7468dede46 GH-525 Remove unused block channel. 2022-12-15 08:15:17 -06:00
Kevin Heifner 43d45edb01 GH-525 Make forkdb thread-safe 2022-12-15 08:14:57 -06:00
Eric Passmore 76a341e52c updated version tag 2022-12-14 03:23:46 -08:00
Eric Passmore b0ea27b449 paused returns boolean, pause does not 2022-12-14 02:20:53 -08:00
Eric Passmore 16c8021e93 added 4xx return codes as required by redocly linter 2022-12-13 12:50:22 -08:00
Eric Passmore 266175a940 fixed component paths on openapi docs 2022-12-13 11:25:32 -08:00
Eric Passmore 1bd84d8447 fixes producer plugin docs 2022-12-13 03:22:36 -08:00
Kevin Heifner 40a7e34d14 GH-525 Honor deadline if we can produce 2022-12-12 08:58:59 -06:00
Kevin Heifner 82829648ba Merge pull request #541 from AntelopeIO/GH-535-trace-api-3.1
[3.1] Do not run maintenance task on shutdown
2022-12-09 06:19:17 -06:00
Kevin Heifner e63482a75e GH-525 Minor cleanup 2022-12-08 19:05:57 -06:00
Kevin Heifner 8027ecb367 GH-525 Fixed spelling of yield 2022-12-08 17:25:46 -06:00
Kevin Heifner 1f44c07cd8 GH-525 Use received block as interrupt for start_block when in speculative mode. Use deadline when in production mode. 2022-12-08 16:54:23 -06:00
Kevin Heifner 0103412fe7 GH-525 Interrupt speculative start_block when a block is received 2022-12-06 14:09:15 -06:00
Kevin Heifner 051f8fd186 Merge branch 'release/3.1' into GH-535-trace-api-3.1 2022-12-06 11:30:52 -06:00
Kevin Heifner 57b0acb59c GH-535 Add log of shutdown complete. 2022-12-06 09:54:01 -06:00
Kevin Heifner 2c4d19902c GH-535 Do not run maintenance task on shutdown 2022-12-06 09:41:55 -06:00
1312 changed files with 6423 additions and 71919 deletions
@@ -1,14 +0,0 @@
name: 'Parallel ctest'
description: 'Runs a set of labeled ctests in parallel via multiple docker containers'
inputs:
container:
required: true
error-log-paths:
required: true
log-tarball-prefix:
required: true
tests-label:
required: true
runs:
using: 'node16'
main: 'dist/index.mjs'
File diff suppressed because one or more lines are too long
@@ -1,69 +0,0 @@
import child_process from 'node:child_process';
import process from 'node:process';
import stream from 'node:stream';
import fs from 'node:fs';
import zlib from 'node:zlib';
import tar from 'tar-stream';
import core from '@actions/core'
const container = core.getInput('container', {required: true});
const error_log_paths = JSON.parse(core.getInput('error-log-paths', {required: true}));
const log_tarball_prefix = core.getInput('log-tarball-prefix', {required: true});
const tests_label = core.getInput('tests-label', {required: true});
try {
if(child_process.spawnSync("docker", ["run", "--name", "base", "-v", `${process.cwd()}/build.tar.zst:/build.tar.zst`, "--workdir", "/__w/leap/leap", container, "sh", "-c", "zstdcat /build.tar.zst | tar x"], {stdio:"inherit"}).status)
throw new Error("Failed to create base container");
if(child_process.spawnSync("docker", ["commit", "base", "baseimage"], {stdio:"inherit"}).status)
throw new Error("Failed to create base image");
if(child_process.spawnSync("docker", ["rm", "base"], {stdio:"inherit"}).status)
throw new Error("Failed to remove base container");
// the correct approach is by far "--show-only=json-v1" and then pluck out .tests[].name; but that doesn't work on U18's cmake 3.10 since it lacks json-v1 output
const test_query_result = child_process.spawnSync("docker", ["run", "--rm", "baseimage", "bash", "-e", "-o", "pipefail", "-c", `cd build; ctest -L '${tests_label}' --show-only | head -n -1 | cut -d ':' -f 2 -s | jq -cnR '[inputs | select(length>0)[1:]]'`]);
if(test_query_result.status)
throw new Error("Failed to discover tests with label")
const tests = JSON.parse(test_query_result.stdout);
let subprocesses = [];
tests.forEach(t => {
subprocesses.push(new Promise(resolve => {
child_process.spawn("docker", ["run", "--name", t, "--init", "baseimage", "bash", "-c", `cd build; ctest --output-on-failure -R '^${t}$'`], {stdio:"inherit"}).on('close', code => resolve(code));
}));
});
const results = await Promise.all(subprocesses);
for(let i = 0; i < results.length; ++i) {
if(results[i] === 0)
continue;
//failing test
core.setFailed("Some tests failed");
let extractor = tar.extract();
let packer = tar.pack();
extractor.on('entry', (header, stream, next) => {
if(!header.name.startsWith(`__w/leap/leap/build`)) {
stream.on('end', () => next());
stream.resume();
return;
}
header.name = header.name.substring(`__w/leap/leap/`.length);
if(header.name !== "build/" && error_log_paths.filter(p => header.name.startsWith(p)).length === 0) {
stream.on('end', () => next());
stream.resume();
return;
}
stream.pipe(packer.entry(header, next));
}).on('finish', () => {packer.finalize()});
child_process.spawn("docker", ["export", tests[i]]).stdout.pipe(extractor);
stream.promises.pipeline(packer, zlib.createGzip(), fs.createWriteStream(`${log_tarball_prefix}-${tests[i]}-logs.tar.gz`));
}
} catch(e) {
core.setFailed(`Uncaught exception ${e.message}`);
}
@@ -1,351 +0,0 @@
{
"name": "parallel-ctest-containers",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"dependencies": {
"@actions/core": "^1.9.1",
"@vercel/ncc": "^0.34.0",
"tar-stream": "^2.2.0"
}
},
"node_modules/@actions/core": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
"dependencies": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
},
"node_modules/@actions/http-client": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
"dependencies": {
"tunnel": "^0.0.6"
}
},
"node_modules/@vercel/ncc": {
"version": "0.34.0",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.34.0.tgz",
"integrity": "sha512-G9h5ZLBJ/V57Ou9vz5hI8pda/YQX5HQszCs3AmIus3XzsmRn/0Ptic5otD3xVST8QLKk7AMk7AqpsyQGN7MZ9A==",
"bin": {
"ncc": "dist/ncc/cli.js"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"dependencies": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/tar-stream": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
"dependencies": {
"bl": "^4.0.3",
"end-of-stream": "^1.4.1",
"fs-constants": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.1.1"
},
"engines": {
"node": ">=6"
}
},
"node_modules/tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
"engines": {
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}
},
"dependencies": {
"@actions/core": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
"requires": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
},
"@actions/http-client": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
"requires": {
"tunnel": "^0.0.6"
}
},
"@vercel/ncc": {
"version": "0.34.0",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.34.0.tgz",
"integrity": "sha512-G9h5ZLBJ/V57Ou9vz5hI8pda/YQX5HQszCs3AmIus3XzsmRn/0Ptic5otD3xVST8QLKk7AMk7AqpsyQGN7MZ9A=="
},
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"requires": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
}
},
"buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"requires": {
"once": "^1.4.0"
}
},
"fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"requires": {
"wrappy": "1"
}
},
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"requires": {
"safe-buffer": "~5.2.0"
}
},
"tar-stream": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
"requires": {
"bl": "^4.0.3",
"end-of-stream": "^1.4.1",
"fs-constants": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.1.1"
}
},
"tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}
}
}
@@ -1,7 +0,0 @@
{
"dependencies": {
"@actions/core": "^1.9.1",
"@vercel/ncc": "^0.34.0",
"tar-stream": "^2.2.0"
}
}
+63 -68
View File
@@ -7,9 +7,13 @@ on:
- "release/*"
pull_request:
workflow_dispatch:
inputs:
run-lr-tests:
description: 'Run long running tests'
type: boolean
permissions:
packages: read
packages: write
contents: read
defaults:
@@ -40,9 +44,6 @@ jobs:
matrix:
platform: ${{fromJSON(needs.d.outputs.missing-platforms)}}
runs-on: ["self-hosted", "enf-x86-beefy"]
permissions:
packages: write
contents: read
steps:
- name: Login to Container Registry
uses: docker/login-action@v2
@@ -56,7 +57,6 @@ jobs:
push: true
tags: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}}
file: ${{fromJSON(needs.d.outputs.p)[matrix.platform].dockerfile}}
Build:
needs: [d, build-platforms]
if: always() && needs.d.result == 'success' && (needs.build-platforms.result == 'success' || needs.build-platforms.result == 'skipped')
@@ -64,6 +64,8 @@ jobs:
fail-fast: false
matrix:
platform: [ubuntu18, ubuntu20, ubuntu22]
outputs:
lr-tests: ${{steps.build.outputs.lr-tests}}
runs-on: ["self-hosted", "enf-x86-beefy"]
container: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}}
steps:
@@ -79,38 +81,25 @@ jobs:
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -GNinja ..
ninja
tar -pc -C .. --exclude "*.o" build | zstd --long -T0 -9 > ../build.tar.zst
# the correct approach is by far "--show-only=json-v1 | jq '.tests[].name' | jq -sc" but that doesn't work on U18's cmake 3.10 since it lacks json-v1
echo ::set-output name=lr-tests::$(ctest -L "long_running_tests" --show-only | head -n -1 | cut -d ':' -f 2 -s | jq -cnR '[inputs | select(length>0)[1:]]')
tar -pc -C .. --exclude "*.a" --exclude "*.o" build | zstd --long -T0 -9 > ../build.tar.gz
- name: Upload builddir
uses: AntelopeIO/upload-artifact-large-chunks-action@v1
uses: actions/upload-artifact@v3
with:
name: ${{matrix.platform}}-build
path: build.tar.zst
dev-package:
name: Build leap-dev package
needs: [d, Build]
if: always() && needs.Build.result == 'success'
runs-on: ubuntu-latest
container: ${{fromJSON(needs.d.outputs.p)['ubuntu20'].image}}
steps:
- uses: actions/checkout@v3
with:
submodules: true
- name: Download builddir
uses: actions/download-artifact@v3
with:
name: ubuntu20-build
- name: Build dev package
run: |
zstdcat build.tar.zst | tar x
cd build
cpack
- name: Upload dev package
uses: actions/upload-artifact@v3
with:
name: leap-dev-ubuntu20-amd64
path: build/leap-dev*.deb
path: build.tar.gz
- name: Build dev package (Ubuntu 20 only)
if: matrix.platform == 'ubuntu20'
run: |
cd build
ninja package
- name: Upload dev package (Ubuntu 20 only)
if: matrix.platform == 'ubuntu20'
uses: actions/upload-artifact@v3
with:
name: leap-dev-ubuntu20-amd64
path: build/leap-dev*.deb
tests:
name: Tests
needs: [d, Build]
@@ -118,11 +107,13 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [ubuntu20, ubuntu22]
runs-on: ["self-hosted", "enf-x86-hightier"]
platform: [ubuntu20]
runs-on: ["self-hosted", "enf-x86-beefy"]
container: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}}
steps:
- uses: actions/checkout@v3
with:
submodules: true
- name: Download builddir
uses: actions/download-artifact@v3
with:
@@ -131,13 +122,9 @@ jobs:
run: |
# https://github.com/actions/runner/issues/2033 -- need this because of full version label test looking at git revs
chown -R $(id -u):$(id -g) $PWD
# jammy's boost 1.74 can stumble on an EXDEV via copy_file_range() it doesn't have a fallback for; re-eval once moving to std::filesystem
export TMPDIR="$PWD/tmp"
mkdir -p $TMPDIR
zstdcat build.tar.zst | tar x
zstdcat build.tar.gz | tar x
cd build
ctest --output-on-failure -j $(nproc) -LE "(nonparallelizable_tests|long_running_tests)"
np-tests:
name: NP Tests
needs: [d, Build]
@@ -145,62 +132,70 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [ubuntu18, ubuntu20, ubuntu22]
runs-on: ["self-hosted", "enf-x86-midtier"]
platform: [ubuntu20]
runs-on: ubuntu-latest
container:
image: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}}
options: --init
steps:
- uses: actions/checkout@v3
- name: Download builddir
uses: actions/download-artifact@v3
with:
name: ${{matrix.platform}}-build
- name: Run tests in parallel containers
uses: ./.github/actions/parallel-ctest-containers
with:
container: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}}
error-log-paths: '["build/etc", "build/var", "build/leap-ignition-wd"]'
log-tarball-prefix: ${{matrix.platform}}
tests-label: nonparallelizable_tests
- name: Run NP Tests
run: |
zstdcat build.tar.gz | tar x
cd build
ctest --output-on-failure -L "nonparallelizable_tests"
- name: Bundle logs from failed tests
if: failure()
run: tar --ignore-failed-read -czf ${{matrix.platform}}-serial-logs.tar.gz build/var build/etc build/leap-ignition-wd
- name: Upload logs from failed tests
uses: actions/upload-artifact@v3
if: failure()
with:
name: ${{matrix.platform}}-np-logs
path: '*-logs.tar.gz'
name: ${{matrix.platform}}-serial-logs
path: ${{matrix.platform}}-serial-logs.tar.gz
lr-tests:
name: LR Tests
needs: [d, Build]
if: always() && needs.Build.result == 'success'
if: always() && needs.Build.result == 'success' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || inputs.run-lr-tests)
strategy:
fail-fast: false
matrix:
platform: [ubuntu18, ubuntu20, ubuntu22]
runs-on: ["self-hosted", "enf-x86-lowtier"]
platform: [ubuntu20]
test-name: ${{fromJSON(needs.Build.outputs.lr-tests)}}
runs-on: ubuntu-latest
container:
image: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}}
options: --init
steps:
- uses: actions/checkout@v3
- name: Download builddir
uses: actions/download-artifact@v3
with:
name: ${{matrix.platform}}-build
- name: Run tests in parallel containers
uses: ./.github/actions/parallel-ctest-containers
with:
container: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}}
error-log-paths: '["build/etc", "build/var", "build/leap-ignition-wd"]'
log-tarball-prefix: ${{matrix.platform}}
tests-label: long_running_tests
- name: Upload logs from failed tests
- name: Run ${{matrix.test-name}} Test
run: |
zstdcat build.tar.gz | tar x
cd build
ctest --output-on-failure -R ${{matrix.test-name}}
- name: Bundle logs from failed tests
if: failure()
run: tar --ignore-failed-read -czf ${{matrix.platform}}-${{matrix.test-name}}-logs.tar.gz build/var build/etc build/leap-ignition-wd
- name: Upload logs from failed tests
uses: actions/upload-artifact@v3
if: failure()
with:
name: ${{matrix.platform}}-lr-logs
path: '*-logs.tar.gz'
name: ${{matrix.platform}}-${{matrix.test-name}}-logs
path: ${{matrix.platform}}-${{matrix.test-name}}-logs.tar.gz
all-passing:
name: All Required Tests Passed
needs: [dev-package, tests, np-tests]
needs: [tests, np-tests]
if: always()
runs-on: ubuntu-latest
steps:
- if: needs.dev-package.result != 'success' || needs.tests.result != 'success' || needs.np-tests.result != 'success'
- if: needs.tests.result != 'success' || needs.np-tests.result != 'success'
run: false
-42
View File
@@ -1,42 +0,0 @@
name: Jira Issue Creator
on:
issues:
types:
- labeled
jobs:
create-jira-issue:
runs-on: ubuntu-latest
if: github.event.label.name == 'OCI'
steps:
- name: Create json issue file
run: |
cat << EOF > issue.json
{
"fields": {
"project":
{
"key": "$JIRA_PROJECT_KEY"
},
"summary": "$JIRA_ISSUE_SUMMARY",
"description": "$JIRA_ISSUE_DESCRIPTION",
"issuetype": {
"name": "$JIRA_ISSUE_TYPE_NAME"
}
}
}
EOF
env:
JIRA_PROJECT_KEY: ${{ secrets.JIRA_PROJECT_KEY }}
JIRA_ISSUE_SUMMARY: ${{ github.event.issue.title }}
JIRA_ISSUE_DESCRIPTION: "${{ github.event.issue.url }}\\n\\n${{ github.event.issue.html_url }}"
JIRA_ISSUE_TYPE_NAME: "Story"
- name: Check issue json
run: |
cat issue.json
- name: Trigger jira issue creation
run: |
curl -u $JIRA_AUTH -X POST --data @issue.json -H "Content-Type: application/json" --url $JIRA_PROJECT_URL
env:
JIRA_AUTH: ${{ secrets.JIRA_USN_AND_TOKEN }}
JIRA_PROJECT_URL: ${{ secrets.JIRA_PROJECT_URL }}
-17
View File
@@ -1,17 +0,0 @@
name: Label New Issue
on:
issues:
types: opened
jobs:
label_new_issue:
uses: AntelopeIO/issue-project-labeler-workflow/.github/workflows/issue-project-labeler.yaml@v1
with:
issue-id: ${{github.event.issue.node_id}}
label: triage
org-project: 'Team Backlog'
project-field: Status=Todo
secrets:
token: ${{secrets.ENFCIBOT_REPO_AND_PROJECTS}}
+58
View File
@@ -0,0 +1,58 @@
name: "Pinned Build"
on:
workflow_dispatch:
permissions:
packages: read
contents: read
defaults:
run:
shell: bash
jobs:
Build:
name: Build
strategy:
fail-fast: false
matrix:
platform: [ubuntu18, ubuntu20, ubuntu22]
runs-on: ["self-hosted", "enf-x86-beefy-long"]
container: ${{ matrix.platform == 'ubuntu18' && 'ubuntu:bionic' || matrix.platform == 'ubuntu20' && 'ubuntu:focal' || 'ubuntu:jammy' }}
steps:
- name: Conditionally update git repo
if: ${{ matrix.platform == 'ubuntu18' }}
run: |
apt-get update
apt-get install -y software-properties-common
apt-get update
add-apt-repository ppa:git-core/ppa
- name: Update and Install git
run: |
apt-get update
apt-get install -y git
git --version
- name: Clone leap
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install dependencies
run: |
# https://github.com/actions/runner/issues/2033
chown -R $(id -u):$(id -g) $PWD
./scripts/install_deps.sh
- name: Build Pinned Build
env:
LEAP_PINNED_INSTALL_PREFIX: /usr
run: |
./scripts/pinned_build.sh deps build "$(nproc)"
- name: Upload package
uses: actions/upload-artifact@v3
with:
name: leap-${{matrix.platform}}-pinned-amd64
path: build/leap-3*.deb
- name: Run Parallel Tests
run: |
cd build
ctest --output-on-failure -j $(nproc) -LE "(nonparallelizable_tests|long_running_tests)" --timeout 420
-1
View File
@@ -10,7 +10,6 @@
*.abi.hpp
*.cmake
!.cicd
!package.cmake
!CMakeModules/*.cmake
*.ninja
\#*
+6 -12
View File
@@ -7,24 +7,18 @@
[submodule "libraries/eos-vm"]
path = libraries/eos-vm
url = https://github.com/AntelopeIO/eos-vm
[submodule "libraries/fc"]
path = libraries/fc
url = https://github.com/AntelopeIO/fc
[submodule "libraries/softfloat"]
path = libraries/softfloat
url = https://github.com/AntelopeIO/berkeley-softfloat-3
[submodule "libraries/rapidjson"]
path = libraries/rapidjson
url = https://github.com/Tencent/rapidjson/
[submodule "libraries/yubihsm"]
path = libraries/yubihsm
url = https://github.com/Yubico/yubihsm-shell
[submodule "tests/abieos"]
path = tests/abieos
url = https://github.com/AntelopeIO/abieos
[submodule "libraries/libfc/include/fc/crypto/webauthn_json"]
path = libraries/libfc/include/fc/crypto/webauthn_json
url = https://github.com/Tencent/rapidjson/
[submodule "libraries/libfc/secp256k1/secp256k1"]
path = libraries/libfc/secp256k1/secp256k1
url = https://github.com/bitcoin-core/secp256k1
[submodule "libraries/libfc/libraries/ff"]
path = libraries/libfc/libraries/ff
url = https://github.com/AntelopeIO/libff
[submodule "wasm-spec-tests"]
path = wasm-spec-tests
url = https://github.com/AntelopeIO/wasm-spec-tests
+36 -29
View File
@@ -14,9 +14,9 @@ set( CMAKE_CXX_EXTENSIONS ON )
set( CXX_STANDARD_REQUIRED ON)
set(VERSION_MAJOR 3)
set(VERSION_MINOR 2)
set(VERSION_PATCH 0)
#set(VERSION_SUFFIX rc2)
set(VERSION_MINOR 1)
set(VERSION_PATCH 5)
#set(VERSION_SUFFIX rc4)
if(VERSION_SUFFIX)
set(VERSION_FULL "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_SUFFIX}")
@@ -27,7 +27,6 @@ endif()
set( CLI_CLIENT_EXECUTABLE_NAME cleos )
set( NODE_EXECUTABLE_NAME nodeos )
set( KEY_STORE_EXECUTABLE_NAME keosd )
set( LEAP_UTIL_EXECUTABLE_NAME leap-util )
# http://stackoverflow.com/a/18369825
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
@@ -54,11 +53,7 @@ set(ENABLE_MULTIVERSION_PROTOCOL_TEST FALSE CACHE BOOL "Enable nodeos multiversi
# add defaults for openssl
if(APPLE AND UNIX AND "${OPENSSL_ROOT_DIR}" STREQUAL "")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
set(OPENSSL_ROOT_DIR "/opt/homebrew/opt/openssl@3;/opt/homebrew/opt/openssl@1.1")
else()
set(OPENSSL_ROOT_DIR "/usr/local/opt/openssl@3;/usr/local/opt/openssl@1.1")
endif()
set(OPENSSL_ROOT_DIR "/usr/local/opt/openssl@3;/usr/local/opt/openssl@1.1")
endif()
# fc also adds these definitions to its public interface. once fc becomes the sole importer of openssl, this should be removed
add_definitions(-DOPENSSL_API_COMPAT=0x10100000L -DOPENSSL_NO_DEPRECATED)
@@ -182,10 +177,13 @@ add_subdirectory( scripts )
add_subdirectory( unittests )
add_subdirectory( tests )
add_subdirectory( tools )
add_subdirectory( benchmark )
option(DISABLE_WASM_SPEC_TESTS "disable building of wasm spec unit tests" OFF)
if (NOT DISABLE_WASM_SPEC_TESTS)
add_subdirectory( wasm-spec-tests/generated-tests )
endif()
install(FILES testnet.template DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/eosio/launcher COMPONENT dev EXCLUDE_FROM_ALL)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testnet.template ${CMAKE_CURRENT_BINARY_DIR}/etc/eosio/launcher/testnet.template COPYONLY)
@@ -215,26 +213,35 @@ install(FILES ${CMAKE_BINARY_DIR}/modules/leap-config.cmake DESTINATION ${CMAKE_
install(FILES ${CMAKE_BINARY_DIR}/modules/EosioTester.cmake DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/leap COMPONENT dev EXCLUDE_FROM_ALL)
install(FILES ${CMAKE_SOURCE_DIR}/CMakeModules/EosioCheckVersion.cmake DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/leap COMPONENT dev EXCLUDE_FROM_ALL)
configure_file(LICENSE licenses/leap/LICENSE COPYONLY)
configure_file(libraries/softfloat/COPYING.txt licenses/leap/LICENSE.softfloat COPYONLY)
configure_file(libraries/wasm-jit/LICENSE licenses/leap/LICENSE.wavm COPYONLY)
configure_file(libraries/libfc/secp256k1/secp256k1/COPYING licenses/leap/LICENSE.secp256k1 COPYONLY)
configure_file(libraries/libfc/include/fc/crypto/webauthn_json/license.txt licenses/leap/LICENSE.rapidjson COPYONLY)
configure_file(libraries/libfc/src/network/LICENSE.go licenses/leap/LICENSE.go COPYONLY)
configure_file(libraries/eos-vm/LICENSE licenses/leap/LICENSE.eos-vm COPYONLY)
configure_file(libraries/libfc/libraries/ff/LICENSE licenses/leap/LICENSE.libff COPYONLY)
configure_file(programs/cleos/LICENSE.CLI11 licenses/leap/LICENSE.CLI11 COPYONLY)
configure_file(libraries/yubihsm/LICENSE licenses/leap/LICENSE.yubihsm COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/LICENSE
${CMAKE_BINARY_DIR}/licenses/leap/LICENSE COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/libraries/softfloat/COPYING.txt
${CMAKE_BINARY_DIR}/licenses/leap/LICENSE.softfloat COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/libraries/wasm-jit/LICENSE
${CMAKE_BINARY_DIR}/licenses/leap/LICENSE.wavm COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/libraries/fc/secp256k1/secp256k1/COPYING
${CMAKE_BINARY_DIR}/licenses/leap/LICENSE.secp256k1 COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/libraries/fc/include/fc/crypto/webauthn_json/license.txt
${CMAKE_BINARY_DIR}/licenses/leap/LICENSE.rapidjson COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/libraries/fc/src/network/LICENSE.go
${CMAKE_BINARY_DIR}/licenses/leap/LICENSE.go COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/libraries/yubihsm/LICENSE
${CMAKE_BINARY_DIR}/licenses/leap/LICENSE.yubihsm COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/libraries/eos-vm/LICENSE
${CMAKE_BINARY_DIR}/licenses/leap/LICENSE.eos-vm COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/programs/cleos/LICENSE.CLI11
${CMAKE_BINARY_DIR}/programs/cleos/LICENSE.CLI11 COPYONLY)
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/licenses/leap" DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/" COMPONENT base)
configure_file(${CMAKE_SOURCE_DIR}/libraries/cli11/bash-completion/completions/leap-util
${CMAKE_BINARY_DIR}/programs/leap-util/bash-completion/completions/leap-util COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/libraries/cli11/bash-completion/completions/cleos
${CMAKE_BINARY_DIR}/programs/cleos/bash-completion/completions/cleos COPYONLY)
install(FILES libraries/cli11/bash-completion/completions/leap-util DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/bash-completion/completions COMPONENT base)
install(FILES libraries/cli11/bash-completion/completions/cleos DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/bash-completion/completions COMPONENT base)
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/leap/ COMPONENT base)
install(FILES libraries/softfloat/COPYING.txt DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/leap/ RENAME LICENSE.softfloat COMPONENT base)
install(FILES libraries/wasm-jit/LICENSE DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/leap/ RENAME LICENSE.wavm COMPONENT base)
install(FILES libraries/fc/secp256k1/secp256k1/COPYING DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/leap/ RENAME LICENSE.secp256k1 COMPONENT base)
install(FILES libraries/fc/include/fc/crypto/webauthn_json/license.txt DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/leap/ RENAME LICENSE.rapidjson COMPONENT base)
install(FILES libraries/fc/src/network/LICENSE.go DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/leap/ COMPONENT base)
install(FILES libraries/yubihsm/LICENSE DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/leap/ RENAME LICENSE.yubihsm COMPONENT base)
install(FILES libraries/eos-vm/LICENSE DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/leap/ RENAME LICENSE.eos-vm COMPONENT base)
install(FILES libraries/fc/libraries/ff/LICENSE DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/leap/ RENAME LICENSE.libff COMPONENT base)
install(FILES programs/cleos/LICENSE.CLI11 DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/leap/ COMPONENT base)
add_custom_target(dev-install
COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}"
+7 -2
View File
@@ -54,8 +54,13 @@ find_package(Boost @Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@ EXACT REQUIRED CO
find_library(libtester eosio_testing @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
find_library(libchain eosio_chain @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
find_library(libfc fc @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
find_library(libsecp256k1 secp256k1 @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
if ( "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" )
find_library(libfc fc_debug @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
find_library(libsecp256k1 secp256k1_debug @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
else()
find_library(libfc fc @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
find_library(libsecp256k1 secp256k1 @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
endif()
find_library(libff ff @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
find_library(libwasm WASM @CMAKE_INSTALL_FULL_LIBDIR@ NO_DEFAULT_PATH)
+11 -5
View File
@@ -51,10 +51,16 @@ find_package(Boost @Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@ EXACT REQUIRED CO
find_library(libtester eosio_testing @CMAKE_BINARY_DIR@/libraries/testing NO_DEFAULT_PATH)
find_library(libchain eosio_chain @CMAKE_BINARY_DIR@/libraries/chain NO_DEFAULT_PATH)
find_library(libfc fc @CMAKE_BINARY_DIR@/libraries/libfc NO_DEFAULT_PATH)
find_library(libsecp256k1 secp256k1 @CMAKE_BINARY_DIR@/libraries/libfc/secp256k1 NO_DEFAULT_PATH)
if ( "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" )
find_library(libfc fc_debug @CMAKE_BINARY_DIR@/libraries/fc NO_DEFAULT_PATH)
find_library(libsecp256k1 secp256k1_debug @CMAKE_BINARY_DIR@/libraries/fc/secp256k1 NO_DEFAULT_PATH)
find_library(libff ff @CMAKE_BINARY_DIR@/libraries/libfc/libraries/ff/libff NO_DEFAULT_PATH)
else()
find_library(libfc fc @CMAKE_BINARY_DIR@/libraries/fc NO_DEFAULT_PATH)
find_library(libsecp256k1 secp256k1 @CMAKE_BINARY_DIR@/libraries/fc/secp256k1 NO_DEFAULT_PATH)
endif()
find_library(libff ff @CMAKE_BINARY_DIR@/libraries/fc/libraries/ff/libff NO_DEFAULT_PATH)
find_library(libwasm WASM @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/WASM NO_DEFAULT_PATH)
find_library(libwast WAST @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/WAST NO_DEFAULT_PATH)
find_library(libir IR @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/IR NO_DEFAULT_PATH)
@@ -123,7 +129,7 @@ macro(add_eosio_test_executable test_name)
@OPENSSL_INCLUDE_DIR@
@CMAKE_SOURCE_DIR@/libraries/chain/include
@CMAKE_BINARY_DIR@/libraries/chain/include
@CMAKE_SOURCE_DIR@/libraries/libfc/include
@CMAKE_SOURCE_DIR@/libraries/fc/include
@CMAKE_SOURCE_DIR@/libraries/softfloat/source/include
@CMAKE_SOURCE_DIR@/libraries/appbase/include
@CMAKE_SOURCE_DIR@/libraries/chainbase/include
@@ -170,7 +176,7 @@ if(ENABLE_COVERAGE_TESTING)
COMMAND ${LCOV_PATH} --directory . --capture --gcov-tool ${CMAKE_SOURCE_DIR}/tools/llvm-gcov.sh --output-file ${Coverage_NAME}.info
COMMAND ${LCOV_PATH} -remove ${Coverage_NAME}.info '*/boost/*' '/usr/lib/*' '/usr/include/*' '*/externals/*' '*/libfc/*' '*/wasm-jit/*' --output-file ${Coverage_NAME}_filtered.info
COMMAND ${LCOV_PATH} -remove ${Coverage_NAME}.info '*/boost/*' '/usr/lib/*' '/usr/include/*' '*/externals/*' '*/fc/*' '*/wasm-jit/*' --output-file ${Coverage_NAME}_filtered.info
COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}_filtered.info
-7
View File
@@ -1,7 +0,0 @@
file(GLOB BENCHMARK "*.cpp")
add_executable( benchmark ${BENCHMARK} )
target_link_libraries( benchmark fc Boost::program_options )
target_include_directories( benchmark PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}"
)
-123
View File
@@ -1,123 +0,0 @@
#include <iostream>
#include <fc/crypto/alt_bn128.hpp>
#include <benchmark.hpp>
namespace benchmark {
using bytes = std::vector<char>;
using g1g2_pair = std::vector<std::string>;
void add_benchmarking() {
std::vector<unsigned char> point1_raw = {
12,175,215,144,98,95,151,228,179,85,31,170,172,159,40,255,250,252,68,28,235,65,172,180,69,164,153,29,187,239,220,201, // x
18,102,219,76,79,148,120,28,39,149,42,172,41,248,120,249,255,69,42,51,160,239,13,219,239,183,77,174,217,158,130,10,}; // y
std::vector<unsigned char> point2_raw = {
12,144,10,32,104,85,103,36,222,232,48,152,108,217,40,145,230,48,8,54,0,7,134,164,7,10,139,110,95,205,124,121, // x
22,254,176,251,18,168,78,220,142,100,102,113,58,176,83,186,212,62,154,138,235,135,34,46,237,117,54,36,198,40,79,73,}; // y
bytes point1, point2;
point1.insert(point1.begin(), point1_raw.begin(), point1_raw.end());
point2.insert(point2.begin(), point2_raw.begin(), point2_raw.end());
auto f = [&]() {
auto res = fc::alt_bn128_add(point1, point2);
if (std::holds_alternative<fc::alt_bn128_error>(res)) {
std::cout << "alt_bn128_add failed: "
<< (int)std::get<fc::alt_bn128_error>(res) << std::endl;
}
};
benchmarking("alt_bn128_add", f);
}
void mul_benchmarking() {
std::vector<unsigned char> point_raw = {
12,175,215,144,98,95,151,228,179,85,31,170,172,159,40,255,250,252,68,28,235,65,172,180,69,164,153,29,187,239,220,201, // x
18,102,219,76,79,148,120,28,39,149,42,172,41,248,120,249,255,69,42,51,160,239,13,219,239,183,77,174,217,158,130,10,}; // y
std::vector<unsigned char> scaler_raw = {
25,62,182,170,104,140,135,90,37,150,0,77,2,77,146,71,54,101,113,69,177,216,157,4,229,213,33,215,169,99,150,91, }; // scaler size 256 bits
bytes point, scaler;
point.insert(point.begin(), point_raw.begin(), point_raw.end());
scaler.insert(scaler.begin(), scaler_raw.begin(), scaler_raw.end());
auto f = [&]() {
auto res = fc::alt_bn128_mul(point, scaler);
if (std::holds_alternative<fc::alt_bn128_error>(res)) {
std::cout << "alt_bn128_mul failed: "
<< (int)std::get<fc::alt_bn128_error>(res) << std::endl;
}
};
benchmarking("alt_bn128_mul", f);
}
void pair_benchmarking() {
std::vector<unsigned char> g1_g2_pairs_raw = {
/* pair 1 */
12,175,215,144,98,95,151,228,179,85,31,170,172,159,40,255,250,252,68,28,235,65,172,180,69,164,153,29,187,239,220,201,18,102,219,76,79,148,120,28,39,149,42,172,41,248,120,249,255,69,42,51,160,239,13,219,239,183,77,174,217,158,130,10,
46,24,234,176,148,82,198,136,44,30,157,18,217,25,49,241,63,197,2,151,14,150,136,210,114,4,74,124,145,225,131,139,13,60,0,50,236,103,39,15,150,226,246,189,209,113,0,46,151,39,41,6,87,119,228,213,45,225,29,234,161,110,43,87,3,237,74,227,93,23,171,129,49,118,228,173,154,111,168,220,161,46,140,103,155,56,168,207,254,90,228,76,188,232,25,34,44,102,159,35,193,216,177,31,131,247,226,19,170,222,26,227,86,37,81,149,202,144,188,126,120,168,9,195,32,169,147,161,
/* pair,2,*/
12,144,10,32,104,85,103,36,222,232,48,152,108,217,40,145,230,48,8,54,0,7,134,164,7,10,139,110,95,205,124,121,22,254,176,251,18,168,78,220,142,100,102,113,58,176,83,186,212,62,154,138,235,135,34,46,237,117,54,36,198,40,79,73,
0,186,148,242,227,252,208,242,165,128,1,160,59,2,6,195,30,54,69,118,8,28,223,92,254,98,110,219,90,92,7,113,26,8,119,98,122,61,119,91,216,107,29,179,122,218,203,6,84,109,119,140,44,12,57,157,203,90,14,108,218,54,94,44,42,77,118,169,232,192,189,60,129,213,156,157,215,160,91,214,138,130,119,145,167,89,237,149,225,85,151,33,89,181,224,235,2,91,213,225,37,226,214,14,255,84,254,117,142,211,28,164,78,254,64,11,126,217,25,124,203,220,52,181,39,32,78,132,
/* pair 3 */
48,58,116,183,56,3,62,111,104,127,0,7,202,204,146,2,236,192,214,213,231,100,12,17,104,47,76,49,149,39,35,179,2,162,218,104,52,130,61,134,223,111,123,225,186,122,171,2,144,236,110,29,26,142,113,183,238,44,130,30,76,212,52,15,
19,206,16,79,220,158,153,194,12,48,10,79,173,10,97,199,113,25,255,87,220,3,102,235,164,170,50,240,177,237,223,205,11,75,211,28,143,229,192,35,171,167,172,238,138,235,82,134,111,165,144,29,118,150,179,21,158,9,202,2,242,109,33,148,14,188,33,145,213,186,0,126,178,10,131,168,121,66,121,193,106,209,176,34,176,41,145,227,3,55,245,150,82,218,232,155,31,153,213,183,157,2,159,247,25,69,49,215,219,36,46,5,192,205,201,182,72,189,84,62,61,47,136,81,51,65,231,161,
/* pair 4 */
27,31,150,92,17,82,135,210,46,161,0,24,16,199,200,165,29,165,157,168,222,9,83,17,44,27,64,226,208,112,223,128,20,253,182,130,45,130,249,9,168,206,153,86,197,214,59,248,241,191,93,113,70,113,247,244,43,214,240,246,24,38,33,50,
23,76,241,195,191,99,69,237,123,173,212,42,74,85,138,108,39,80,105,135,226,11,84,237,39,73,180,224,42,230,246,76,26,61,86,57,253,213,223,2,93,42,38,186,38,38,206,38,209,138,153,181,57,89,16,187,234,2,110,23,12,14,252,240,32,231,237,147,16,62,220,6,160,64,154,167,57,238,243,112,255,35,80,36,100,173,21,58,96,244,77,245,75,202,24,63,35,178,46,215,219,69,120,221,70,119,111,195,145,45,109,84,206,76,254,205,98,167,30,72,117,5,128,129,156,128,196,192,
/* pair 5 */
33,230,106,254,43,77,114,126,9,205,25,63,9,170,62,237,149,102,198,184,60,31,185,213,103,120,71,249,28,106,238,107,1,133,60,180,58,152,18,177,142,248,46,186,90,34,94,200,235,158,242,255,209,32,143,133,102,195,19,107,153,42,207,228,
30,43,165,137,133,231,242,156,65,126,94,159,26,27,78,164,165,159,225,150,220,158,247,118,118,170,195,122,12,125,8,34,39,57,159,231,167,233,3,47,243,142,174,224,162,38,147,65,74,191,98,144,126,125,81,177,75,140,161,27,34,97,46,249,8,65,220,15,139,144,78,12,72,239,54,163,39,6,30,147,154,208,89,111,170,126,6,214,32,181,195,140,215,53,218,239,44,43,229,0,169,242,16,227,163,185,224,21,142,203,135,66,60,53,91,80,48,112,8,13,226,206,58,249,163,52,196,53,
/* pair 6 */
14,157,100,136,255,206,130,101,56,187,235,39,67,209,67,124,40,174,153,135,155,26,166,170,118,193,244,21,70,71,120,150,3,189,254,120,183,98,23,175,175,28,195,233,165,224,35,95,247,132,40,64,26,208,70,206,247,92,134,105,118,181,21,242,
16,159,200,208,93,99,234,139,8,222,239,67,3,187,15,125,5,144,190,196,146,171,15,218,92,36,37,130,2,201,241,182,36,31,104,164,95,29,73,231,87,50,174,142,209,72,31,75,48,13,70,237,118,193,39,85,97,88,228,50,77,163,209,112,7,202,214,212,235,15,224,247,229,179,101,15,72,130,125,8,62,227,46,20,109,53,26,168,10,237,222,85,169,133,181,196,25,36,112,182,41,208,39,132,100,181,199,189,44,99,238,140,6,187,19,197,99,93,243,63,159,132,211,0,230,118,153,54,
/* pair 7 */
31,60,154,8,188,169,224,107,69,183,223,15,60,32,61,51,81,226,85,38,72,88,241,202,216,204,253,98,0,250,116,167,21,255,0,81,80,3,108,196,240,102,114,33,33,122,116,155,188,19,232,217,42,217,54,195,91,187,88,188,249,218,240,146,
12,28,171,60,8,166,151,19,125,237,128,127,207,183,19,1,188,189,105,181,170,172,8,180,30,175,4,108,191,252,197,161,37,122,14,151,117,34,172,227,236,154,84,99,189,197,91,46,43,148,174,218,83,61,196,48,131,45,242,61,92,242,56,251,39,125,111,11,24,37,76,62,151,59,183,3,156,187,249,232,229,56,230,171,55,2,246,70,74,102,0,156,185,237,126,90,0,30,248,164,199,146,66,237,158,134,139,168,128,189,126,55,35,198,48,18,112,40,63,70,254,246,88,111,254,67,213,223,
/* pair 8 */
27,106,52,232,120,148,201,234,161,123,171,160,223,151,6,105,206,47,94,147,47,22,27,21,248,20,223,51,116,192,29,221,25,149,109,33,131,198,32,101,157,94,62,164,205,151,23,108,214,43,231,7,95,228,183,1,242,205,19,62,124,79,48,203,
37,186,150,204,63,241,145,219,169,250,247,76,247,18,135,175,140,58,209,133,113,144,185,191,101,197,252,253,50,126,188,177,45,103,105,194,21,229,145,210,89,135,244,248,238,64,102,155,129,232,252,32,208,82,51,131,113,100,25,174,253,19,211,18,6,77,66,232,173,42,146,120,106,72,92,144,51,233,117,184,113,60,33,118,209,83,119,93,170,253,126,41,58,13,85,111,30,233,117,238,183,18,219,38,216,163,244,98,219,254,156,189,57,246,220,178,17,190,88,84,13,41,8,236,181,155,85,198,
/* pair 9 */
25,62,182,170,104,140,135,90,37,150,0,77,2,77,146,71,54,101,113,69,177,216,157,4,229,213,33,215,169,99,150,91,5,185,157,10,152,12,220,171,39,188,1,48,87,129,192,101,36,179,99,212,123,207,13,76,89,78,8,154,75,239,117,189,
19,87,226,242,101,183,176,42,195,135,40,225,195,207,13,62,60,37,28,251,13,165,96,198,173,250,251,107,25,141,77,68,45,115,128,233,135,104,231,12,192,206,60,249,137,191,114,141,3,235,34,189,208,170,23,59,231,12,197,116,5,188,52,20,11,153,186,15,96,240,54,123,212,242,168,141,151,187,17,38,185,238,196,242,26,194,193,18,34,107,95,238,108,154,140,224,13,76,71,149,81,56,85,83,56,59,203,183,170,10,167,200,128,135,105,19,93,203,131,146,116,209,62,27,81,80,234,172,
/* pair 10 */
30,204,212,77,212,159,135,173,195,194,165,112,62,248,180,204,66,73,253,99,65,111,39,171,19,211,171,203,35,66,146,20,33,241,46,6,167,133,80,76,238,165,59,232,120,58,211,157,50,212,86,191,95,6,134,164,36,227,79,58,119,98,108,171,
48,49,12,141,166,151,158,56,136,255,197,138,114,195,39,59,71,236,82,57,149,249,170,55,187,95,193,171,14,124,45,87,7,157,47,178,153,237,194,157,142,194,100,14,40,51,61,201,244,93,61,196,154,59,14,135,209,72,102,186,14,228,228,152,40,246,109,82,93,249,92,105,191,121,77,108,20,87,3,87,167,173,171,255,189,34,155,239,218,95,181,153,222,20,120,195,27,28,47,82,113,3,218,129,54,210,185,165,206,99,126,61,217,19,237,5,12,90,148,246,128,231,63,53,37,223,204,195
};
// benchmarking 1 pair of points
bytes g1_g2_1_pair;
g1_g2_1_pair.insert(g1_g2_1_pair.begin(), g1_g2_pairs_raw.begin(), g1_g2_pairs_raw.begin() + 384);
auto f_1_pair = [&]() {
auto res = fc::alt_bn128_pair(g1_g2_1_pair, [](){});
if (std::holds_alternative<fc::alt_bn128_error>(res)) {
std::cout << "alt_bn128_pair 1 pair failed: "
<< (int)std::get<fc::alt_bn128_error>(res) << std::endl;
}
};
benchmarking("alt_bn128_pair (1 pair)", f_1_pair);
// benchmarking 10 pair of points
bytes g1_g2_10_pairs;
g1_g2_10_pairs.insert(g1_g2_10_pairs.begin(), g1_g2_pairs_raw.begin(), g1_g2_pairs_raw.end());
auto f_10_pairs = [&]() {
auto res = fc::alt_bn128_pair(g1_g2_10_pairs, [](){});
if (std::holds_alternative<fc::alt_bn128_error>(res)) {
std::cout << "alt_bn128_pair 10 pairs failed: "
<< (int)std::get<fc::alt_bn128_error>(res) << std::endl;
}
};
benchmarking("alt_bn128_pair (10 pairs)", f_10_pairs);
}
void alt_bn_128_benchmarking() {
add_benchmarking();
mul_benchmarking();
pair_benchmarking();
}
} // benchmark
-82
View File
@@ -1,82 +0,0 @@
#include <chrono>
#include <iostream>
#include <iomanip>
#include <locale>
#include <benchmark.hpp>
namespace benchmark {
// update this map when a new feature is supported
// key is the name and value is the function doing benchmarking
std::map<std::string, std::function<void()>> features {
{ "alt_bn_128", alt_bn_128_benchmarking },
{ "modexp", modexp_benchmarking },
{ "key", key_benchmarking },
{ "hash", hash_benchmarking },
{ "blake2", blake2_benchmarking },
};
// values to control cout format
constexpr auto name_width = 28;
constexpr auto runs_width = 5;
constexpr auto time_width = 12;
constexpr auto ns_width = 2;
uint32_t num_runs = 1;
std::map<std::string, std::function<void()>> get_features() {
return features;
}
void set_num_runs(uint32_t runs) {
num_runs = runs;
}
void print_header() {
std::cout << std::left << std::setw(name_width) << "function"
<< std::setw(runs_width) << "runs"
<< std::setw(time_width + ns_width) << std::right << "average"
<< std::setw(time_width + ns_width) << "minimum"
<< std::setw(time_width + ns_width) << "maximum"
<< std::endl << std::endl;
}
void print_results(std::string name, uint32_t runs, uint64_t total, uint64_t min, uint64_t max) {
std::cout.imbue(std::locale(""));
std::cout
<< std::setw(name_width) << std::left << name
<< std::setw(runs_width) << runs
// std::fixed for not printing 1234 in 1.234e3.
// setprecision(0) for not printing fractions
<< std::right << std::fixed << std::setprecision(0)
<< std::setw(time_width) << total/runs << std::setw(ns_width) << " ns"
<< std::setw(time_width) << min << std::setw(ns_width) << " ns"
<< std::setw(time_width) << max << std::setw(ns_width) << " ns"
<< std::endl;
}
bytes to_bytes(const std::string& source) {
bytes output(source.length()/2);
fc::from_hex(source, output.data(), output.size());
return output;
};
void benchmarking(std::string name, const std::function<void()>& func) {
uint64_t total {0}, min {std::numeric_limits<uint64_t>::max()}, max {0};
for (auto i = 0U; i < num_runs; ++i) {
auto start_time = std::chrono::high_resolution_clock::now();
func();
auto end_time = std::chrono::high_resolution_clock::now();
uint64_t duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count();
total += duration;
min = std::min(min, duration);
max = std::max(max, duration);
}
print_results(name, num_runs, total, min, max);
}
} // benchmark
-25
View File
@@ -1,25 +0,0 @@
#pragma once
#include <functional>
#include <map>
#include <vector>
#include <fc/crypto/hex.hpp>
namespace benchmark {
using bytes = std::vector<char>;
void set_num_runs(uint32_t runs);
std::map<std::string, std::function<void()>> get_features();
void print_header();
bytes to_bytes(const std::string& source);
void alt_bn_128_benchmarking();
void modexp_benchmarking();
void key_benchmarking();
void hash_benchmarking();
void blake2_benchmarking();
void benchmarking(std::string name, const std::function<void()>& func);
} // benchmark
-21
View File
@@ -1,21 +0,0 @@
#include <fc/crypto/blake2.hpp>
#include <benchmark.hpp>
namespace benchmark {
void blake2_benchmarking() {
uint32_t _rounds = 0x0C;
bytes _h = to_bytes( "48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b");
bytes _m = to_bytes("6162630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
bytes _t0_offset = to_bytes("0300000000000000");
bytes _t1_offset = to_bytes("0000000000000000");
bool _f = false;
auto blake2_f = [&]() {
fc::blake2b(_rounds, _h, _m, _t0_offset, _t1_offset, _f, [](){});;
};
benchmarking("blake2", blake2_f);
}
} // benchmark
-89
View File
@@ -1,89 +0,0 @@
#include <fc/crypto/hex.hpp>
#include <fc/crypto/sha1.hpp>
#include <fc/crypto/sha3.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/crypto/sha512.hpp>
#include <fc/crypto/ripemd160.hpp>
#include <fc/utility.hpp>
#include <benchmark.hpp>
using namespace fc;
namespace benchmark {
void hash_benchmarking() {
std::string small_message = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ01";
// build a large message
constexpr auto large_msg_size = 4096;
std::string large_message;
large_message.reserve(large_msg_size);
uint32_t num_concats = large_msg_size/small_message.length();
for (uint32_t i = 0; i < num_concats; ++i) {
large_message += small_message;
}
auto sha1_small_msg = [&]() {
fc::sha1::hash(small_message);
};
benchmarking("sha1 (" + std::to_string(small_message.length()) + " bytes)", sha1_small_msg);
auto sha1_large_msg = [&]() {
fc::sha1::hash(large_message);
};
benchmarking("sha1 (" + std::to_string(large_message.length()) + " bytes)", sha1_large_msg);
auto sha256_small_msg = [&]() {
fc::sha256::hash(small_message);
};
benchmarking("sha256 (" + std::to_string(small_message.length()) + " bytes)", sha256_small_msg);
auto sha256_large_msg = [&]() {
fc::sha256::hash(large_message);
};
benchmarking("sha256 (" + std::to_string(large_message.length()) + " bytes)", sha256_large_msg);
auto sha512_small_msg = [&]() {
fc::sha512::hash(small_message);
};
benchmarking("sha512 (" + std::to_string(small_message.length()) + " bytes)", sha512_small_msg);
auto sha512_large_msg = [&]() {
fc::sha512::hash(large_message);
};
benchmarking("sha512 (" + std::to_string(large_message.length()) + " bytes)", sha512_large_msg);
auto ripemd160_small_msg = [&]() {
fc::ripemd160::hash(small_message);
};
benchmarking("ripemd160 (" + std::to_string(small_message.length()) + " bytes)", ripemd160_small_msg);
auto ripemd160_large_msg = [&]() {
fc::ripemd160::hash(large_message);
};
benchmarking("ripemd160 (" + std::to_string(large_message.length()) + " bytes)", ripemd160_large_msg);
auto sha3_small_msg = [&]() {
fc::sha3::hash(small_message, true);
};
benchmarking("sha3-256 (" + std::to_string(small_message.length()) + " bytes)", sha3_small_msg);
auto sha3_large_msg = [&]() {
fc::sha3::hash(large_message, true);
};
benchmarking("sha3-256 (" + std::to_string(large_message.length()) + " bytes)", sha3_large_msg);
auto keccak_small_msg = [&]() {
fc::sha3::hash(small_message, false);
};
benchmarking("keccak256 (" + std::to_string(small_message.length()) + " bytes)", keccak_small_msg);
auto keccak_large_msg = [&]() {
fc::sha3::hash(large_message, false);
};
benchmarking("keccak256 (" + std::to_string(large_message.length()) + " bytes)", keccak_large_msg);
}
} // benchmark
-109
View File
@@ -1,109 +0,0 @@
#include <fc/crypto/public_key.hpp>
#include <fc/crypto/private_key.hpp>
#include <fc/crypto/signature.hpp>
#include <fc/crypto/k1_recover.hpp>
#include <benchmark.hpp>
using namespace fc::crypto;
using namespace fc;
using namespace std::literals;
namespace benchmark {
void k1_sign_benchmarking() {
auto payload = "Test Cases";
auto digest = sha256::hash(payload, const_strlen(payload));
auto private_key_string = std::string("5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3");
auto key = private_key(private_key_string);
auto sign_non_canonical_f = [&]() {
key.sign(digest, false);
};
benchmarking("k1_sign_non_canonical", sign_non_canonical_f);
}
void k1_recover_benchmarking() {
auto signature = to_bytes( "1b323dd47a1dd5592c296ee2ee12e0af38974087a475e99098a440284f19c1f7642fa0baa10a8a3ab800dfdbe987dee68a09b6fa3db45a5cc4f3a5835a1671d4dd");
auto digest = to_bytes( "92390316873c5a9d520b28aba61e7a8f00025ac069acd9c4d2a71d775a55fa5f");
auto recover_f = [&]() {
fc::k1_recover(signature, digest);
};
benchmarking("k1_recover", recover_f);
}
void k1_benchmarking() {
k1_sign_benchmarking();
k1_recover_benchmarking();
}
void r1_benchmarking() {
auto payload = "Test Cases";
auto digest = sha256::hash(payload, const_strlen(payload));
auto key = private_key::generate<r1::private_key_shim>();
auto sign_f = [&]() {
key.sign(digest);
};
benchmarking("r1_sign", sign_f);
auto sig = key.sign(digest);
auto recover_f = [&]() {
public_key(sig, digest);;
};
benchmarking("r1_recover", recover_f);
}
static fc::crypto::webauthn::signature make_webauthn_sig(const fc::crypto::r1::private_key& priv_key,
std::vector<uint8_t>& auth_data,
const std::string& json) {
//webauthn signature is sha256(auth_data || client_data_hash)
fc::sha256 client_data_hash = fc::sha256::hash(json);
fc::sha256::encoder e;
e.write((char*)auth_data.data(), auth_data.size());
e.write(client_data_hash.data(), client_data_hash.data_size());
r1::compact_signature sig = priv_key.sign_compact(e.result());
char buff[8192];
datastream<char*> ds(buff, sizeof(buff));
fc::raw::pack(ds, sig);
fc::raw::pack(ds, auth_data);
fc::raw::pack(ds, json);
ds.seekp(0);
fc::crypto::webauthn::signature ret;
fc::raw::unpack(ds, ret);
return ret;
}
void wa_benchmarking() {
static const r1::private_key priv = fc::crypto::r1::private_key::generate();
static const fc::sha256 d = fc::sha256::hash("sup"s);
static const fc::sha256 origin_hash = fc::sha256::hash("fctesting.invalid"s);
std::string json = "{\"origin\":\"https://fctesting.invalid\",\"type\":\"webauthn.get\", \"challenge\":\"" + fc::base64url_encode(d.data(), d.data_size()) + "\"}";
std::vector<uint8_t> auth_data(37);
memcpy(auth_data.data(), origin_hash.data(), sizeof(origin_hash));
auto sign = [&]() {
make_webauthn_sig(priv, auth_data, json);
};
benchmarking("webauthn_sign", sign);
auto sig = make_webauthn_sig(priv, auth_data, json);
auto recover= [&]() {
sig.recover(d, true);
};
benchmarking("webauthn_recover", recover);
}
void key_benchmarking() {
k1_benchmarking();
r1_benchmarking();
wa_benchmarking();
}
} // benchmark
-80
View File
@@ -1,80 +0,0 @@
#include <iostream>
#include <boost/program_options.hpp>
#include <benchmark.hpp>
namespace bpo = boost::program_options;
using bpo::options_description;
using bpo::variables_map;
int main(int argc, char* argv[]) {
uint32_t num_runs = 1;
std::string feature_name;
auto features = benchmark::get_features();
options_description cli ("benchmark command line options");
cli.add_options()
("feature,f", bpo::value<std::string>(), "feature to be benchmarked; if this option is not present, all features are benchmarked.")
("list,l", "list of supported features")
("runs,r", bpo::value<uint32_t>(&num_runs)->default_value(1000), "the number of times running a function during benchmarking")
("help,h", "benchmark functions, and report average, minimum, and maximum execution time in nanoseconds");
variables_map vmap;
try {
bpo::store(bpo::parse_command_line(argc, argv, cli), vmap);
bpo::notify(vmap);
if (vmap.count("help") > 0) {
cli.print(std::cerr);
return 0;
}
if (vmap.count("list") > 0) {
auto first = true;
std::cout << "Supported features are ";
for (auto& [name, f]: features) {
if (first) {
first = false;
} else {
std::cout << ", ";
}
std::cout << name;
}
std::cout << std::endl;
return 0;
}
if (vmap.count("feature") > 0) {
feature_name = vmap["feature"].as<std::string>();
if (features.find(feature_name) == features.end()) {
std::cout << feature_name << " is not supported" << std::endl;
return 1;
}
}
} catch (bpo::unknown_option &ex) {
std::cerr << ex.what() << std::endl;
cli.print (std::cerr);
return 1;
} catch( ... ) {
std::cerr << "unknown exception" << std::endl;
}
benchmark::set_num_runs(num_runs);
benchmark::print_header();
if (feature_name.empty()) {
for (auto& [name, f]: features) {
std::cout << name << ":" << std::endl;
f();
std::cout << std::endl;
}
} else {
std::cout << feature_name << ":" << std::endl;
features[feature_name]();
std::cout << std::endl;
}
return 0;
}
-58
View File
@@ -1,58 +0,0 @@
#include <fc/crypto/modular_arithmetic.hpp>
#include <random>
#include <benchmark.hpp>
namespace benchmark {
void modexp_benchmarking() {
std::mt19937 r(0x11223344);
auto generate_random_bytes = [](std::mt19937& rand_eng, unsigned int num_bytes) {
std::vector<char> result(num_bytes);
uint_fast32_t v = 0;
for(int byte_pos = 0, end = result.size(); byte_pos < end; ++byte_pos) {
if ((byte_pos & 0x03) == 0) { // if divisible by 4
v = rand_eng();
}
result[byte_pos] = v & 0xFF;
v >>= 8;
}
return result;
};
static constexpr unsigned int start_num_bytes = 128; // 64
static constexpr unsigned int end_num_bytes = 256; // 512
static constexpr unsigned int delta_num_bytes = 128; // 64
static_assert(start_num_bytes <= end_num_bytes);
static_assert(delta_num_bytes > 0);
static_assert((end_num_bytes - start_num_bytes) % delta_num_bytes == 0);
for (unsigned int n = start_num_bytes, slot = 0; n <= end_num_bytes; n += delta_num_bytes, ++slot) {
auto base = generate_random_bytes(r, n);
auto exponent = generate_random_bytes(r, n);
auto modulus = generate_random_bytes(r, n);
auto f = [&]() {
fc::modexp(base, exponent, modulus);
};
benchmarking(std::to_string(n*8) + " bit width", f);
}
// Running the above benchmark (using commented values for num_trials and *_num_bytes) with a release build on an AMD 3.4 GHz CPU
// provides average durations for executing mod_exp for increasing bit sizes for the value.
// For example: with 512-bit values, the average duration is approximately 40 microseconds; with 1024-bit values, the average duration
// is approximately 260 microseconds; with 2048-bit values, the average duration is approximately 2 milliseconds; and, with 4096-bit
// values, the average duration is approximately 14 milliseconds.
// It appears that a model of the average time that scales quadratically with the bit size fits the empirically generated data well.
// TODO: See if theoretical analysis of the modular exponentiation algorithm also justifies quadratic scaling.
}
} // benchmark
@@ -2,19 +2,19 @@
content_title: Build Antelope from Source
---
The shell scripts previously recommended for building the software have been removed in favor of a build process entirely driven by CMake. Those wishing to build from source are now responsible for installing the necessary dependencies. The list of dependencies and the recommended build procedure are in the [`README.md`](https://github.com/AntelopeIO/leap/blob/release/3.2/README.md) file. Instructions are also included for efficiently running the tests.
The shell scripts previously recommended for building the software have been removed in favor of a build process entirely driven by CMake. Those wishing to build from source are now responsible for installing the necessary dependencies. The list of dependencies and the recommended build procedure are in the [`README.md`](https://github.com/AntelopeIO/leap/blob/release/3.1/README.md) file. Instructions are also included for efficiently running the tests.
### Using DUNE
As an alternative to building from source, try [Docker Utilities for Node Execution](https://github.com/AntelopeIO/DUNE) for the easiest way to get started and for multi-platform support.
### Building From Source
You can also build and install Leap from source. Instructions for that currently live [here](https://github.com/AntelopeIO/leap/blob/release/3.2/README.md#build-and-install-from-source).
You can also build and install Leap from source. Instructions for that currently live [here](https://github.com/AntelopeIO/leap/blob/release/3.1/README.md#build-and-install-from-source).
#### Building Pinned Build Binary Packages
The pinned build instructions have moved [here](https://github.com/AntelopeIO/leap/blob/release/3.2/README.md#pinned-build). You may want to look at the [prerequisites](https://github.com/AntelopeIO/leap/blob/release/3.2/README.md#prerequisites) and our warning on parallelization using the `-j` jobs flag [here](https://github.com/AntelopeIO/leap/blob/release/3.2/README.md#step-3---build) before you build.
The pinned build instructions have moved [here](https://github.com/AntelopeIO/leap/blob/release/3.1/README.md#pinned-build). You may want to look at the [prerequisites](https://github.com/AntelopeIO/leap/blob/release/3.1/README.md#prerequisites) and our warning on parallelization using the `-j` jobs flag [here](https://github.com/AntelopeIO/leap/blob/release/3.1/README.md#step-3---build) before you build.
#### Manual (non "pinned") Build Instructions
The unpinned build instructions have moved [here](https://github.com/AntelopeIO/leap/blob/release/3.2/README.md#unpinned-build). You may want to look at the [prerequisites](https://github.com/AntelopeIO/leap/blob/release/3.2/README.md#prerequisites) and our warning on parallelization using the `-j` jobs flag [here](https://github.com/AntelopeIO/leap/blob/release/3.2/README.md#step-3---build) before you build.
The unpinned build instructions have moved [here](https://github.com/AntelopeIO/leap/blob/release/3.1/README.md#unpinned-build). You may want to look at the [prerequisites](https://github.com/AntelopeIO/leap/blob/release/3.1/README.md#prerequisites) and our warning on parallelization using the `-j` jobs flag [here](https://github.com/AntelopeIO/leap/blob/release/3.1/README.md#step-3---build) before you build.
### Running Tests
Documentation on available test suites and how to run them has moved [here](https://github.com/AntelopeIO/leap/blob/release/3.2/README.md#test).
Documentation on available test suites and how to run them has moved [here](https://github.com/AntelopeIO/leap/blob/release/3.1/README.md#test).
+113 -103
View File
@@ -21,33 +21,35 @@ These can only be specified from the `nodeos` command-line:
```console
Command Line Options for eosio::chain_plugin:
--genesis-json arg File to read Genesis State from
--genesis-timestamp arg override the initial timestamp in the
--genesis-timestamp arg override the initial timestamp in the
Genesis State file
--print-genesis-json extract genesis_state from blocks.log
--print-genesis-json extract genesis_state from blocks.log
as JSON, print to console, and exit
--extract-genesis-json arg extract genesis_state from blocks.log
--extract-genesis-json arg extract genesis_state from blocks.log
as JSON, write into specified file, and
exit
--print-build-info print build environment information to
--print-build-info print build environment information to
console as JSON and exit
--extract-build-info arg extract build environment information
--extract-build-info arg extract build environment information
as JSON, write into specified file, and
exit
--force-all-checks do not skip any checks that can be
skipped while replaying irreversible
blocks
--force-all-checks do not skip any validation checks while
replaying blocks (useful for replaying
blocks from untrusted source)
--disable-replay-opts disable optimizations that specifically
target replay
--replay-blockchain clear chain state database and replay
--replay-blockchain clear chain state database and replay
all blocks
--hard-replay-blockchain clear chain state database, recover as
many blocks as possible from the block
--hard-replay-blockchain clear chain state database, recover as
many blocks as possible from the block
log, and then replay those blocks
--delete-all-blocks clear chain state database and block
--delete-all-blocks clear chain state database and block
log
--truncate-at-block arg (=0) stop hard replay / block log recovery
at this block number (if set to
--truncate-at-block arg (=0) stop hard replay / block log recovery
at this block number (if set to
non-zero number)
--terminate-at-block arg (=0) terminate after reaching this block
number (if set to a non-zero number)
--snapshot arg File to read Snapshot State from
```
@@ -58,162 +60,170 @@ These can be specified from both the `nodeos` command-line or the `config.ini` f
```console
Config Options for eosio::chain_plugin:
--blocks-dir arg (="blocks") the location of the blocks directory
(absolute path or relative to
--blocks-dir arg (="blocks") the location of the blocks directory
(absolute path or relative to
application data dir)
--protocol-features-dir arg (="protocol_features")
the location of the protocol_features
the location of the protocol_features
directory (absolute path or relative to
application config dir)
--checkpoint arg Pairs of [BLOCK_NUM,BLOCK_ID] that
--checkpoint arg Pairs of [BLOCK_NUM,BLOCK_ID] that
should be enforced as checkpoints.
--wasm-runtime runtime (=eos-vm-jit) Override default WASM runtime (
--wasm-runtime runtime (=eos-vm-jit) Override default WASM runtime (
"eos-vm-jit", "eos-vm")
"eos-vm-jit" : A WebAssembly runtime
that compiles WebAssembly code to
"eos-vm-jit" : A WebAssembly runtime
that compiles WebAssembly code to
native x86 code prior to execution.
"eos-vm" : A WebAssembly interpreter.
--profile-account arg The name of an account whose code will
--profile-account arg The name of an account whose code will
be profiled
--abi-serializer-max-time-ms arg (=15)
Override default maximum ABI
Override default maximum ABI
serialization time allowed in ms
--chain-state-db-size-mb arg (=1024) Maximum size (in MiB) of the chain
--chain-state-db-size-mb arg (=1024) Maximum size (in MiB) of the chain
state database
--chain-state-db-guard-size-mb arg (=128)
Safely shut down node when free space
remaining in the chain state database
Safely shut down node when free space
remaining in the chain state database
drops below this size (in MiB).
--signature-cpu-billable-pct arg (=50)
Percentage of actual signature recovery
cpu to bill. Whole number percentages,
cpu to bill. Whole number percentages,
e.g. 50 for 50%
--chain-threads arg (=2) Number of worker threads in controller
--chain-threads arg (=2) Number of worker threads in controller
thread pool
--contracts-console print contract's output to console
--deep-mind print deeper information about chain
--deep-mind print deeper information about chain
operations
--actor-whitelist arg Account added to actor whitelist (may
--actor-whitelist arg Account added to actor whitelist (may
specify multiple times)
--actor-blacklist arg Account added to actor blacklist (may
--actor-blacklist arg Account added to actor blacklist (may
specify multiple times)
--contract-whitelist arg Contract account added to contract
--contract-whitelist arg Contract account added to contract
whitelist (may specify multiple times)
--contract-blacklist arg Contract account added to contract
--contract-blacklist arg Contract account added to contract
blacklist (may specify multiple times)
--action-blacklist arg Action (in the form code::action) added
to action blacklist (may specify
to action blacklist (may specify
multiple times)
--key-blacklist arg Public key added to blacklist of keys
that should not be included in
authorities (may specify multiple
--key-blacklist arg Public key added to blacklist of keys
that should not be included in
authorities (may specify multiple
times)
--sender-bypass-whiteblacklist arg Deferred transactions sent by accounts
in this list do not have any of the
subjective whitelist/blacklist checks
applied to them (may specify multiple
--sender-bypass-whiteblacklist arg Deferred transactions sent by accounts
in this list do not have any of the
subjective whitelist/blacklist checks
applied to them (may specify multiple
times)
--read-mode arg (=speculative) Database read mode ("speculative",
--read-mode arg (=speculative) Database read mode ("speculative",
"head", "read-only", "irreversible").
In "speculative" mode: database
contains state changes by transactions
in the blockchain up to the head block
as well as some transactions not yet
In "speculative" mode: database
contains state changes by transactions
in the blockchain up to the head block
as well as some transactions not yet
included in the blockchain.
In "head" mode: database contains state
changes by only transactions in the
blockchain up to the head block;
transactions received by the node are
changes by only transactions in the
blockchain up to the head block;
transactions received by the node are
relayed if valid.
In "read-only" mode: (DEPRECATED: see
p2p-accept-transactions &
api-accept-transactions) database
contains state changes by only
transactions in the blockchain up to
the head block; transactions received
In "read-only" mode: (DEPRECATED: see
p2p-accept-transactions &
api-accept-transactions) database
contains state changes by only
transactions in the blockchain up to
the head block; transactions received
via the P2P network are not relayed and
transactions cannot be pushed via the
transactions cannot be pushed via the
chain API.
In "irreversible" mode: database
contains state changes by only
transactions in the blockchain up to
the last irreversible block;
transactions received via the P2P
network are not relayed and
transactions cannot be pushed via the
In "irreversible" mode: database
contains state changes by only
transactions in the blockchain up to
the last irreversible block;
transactions received via the P2P
network are not relayed and
transactions cannot be pushed via the
chain API.
--api-accept-transactions arg (=1) Allow API transactions to be evaluated
--api-accept-transactions arg (=1) Allow API transactions to be evaluated
and relayed if valid.
--validation-mode arg (=full) Chain validation mode ("full" or
--validation-mode arg (=full) Chain validation mode ("full" or
"light").
In "full" mode all incoming blocks will
be fully validated.
In "light" mode all incoming blocks
headers will be fully validated;
transactions in those validated blocks
will be trusted
--disable-ram-billing-notify-checks Disable the check which subjectively
In "light" mode all incoming blocks
headers will be fully validated;
transactions in those validated blocks
will be trusted
--disable-ram-billing-notify-checks Disable the check which subjectively
fails a transaction if a contract bills
more RAM to another account within the
more RAM to another account within the
context of a notification handler (i.e.
when the receiver is not the code of
when the receiver is not the code of
the action).
--maximum-variable-signature-length arg (=16384)
Subjectively limit the maximum length
of variable components in a variable
Subjectively limit the maximum length
of variable components in a variable
legnth signature to this size in bytes
--trusted-producer arg Indicate a producer whose blocks
headers signed by it will be fully
validated, but transactions in those
--trusted-producer arg Indicate a producer whose blocks
headers signed by it will be fully
validated, but transactions in those
validated blocks will be trusted.
--database-map-mode arg (=mapped) Database map mode ("mapped", "heap", or
"locked").
In "mapped" mode database is memory
In "mapped" mode database is memory
mapped as a file.
In "heap" mode database is preloaded in
to swappable memory and will use huge
to swappable memory and will use huge
pages if available.
In "locked" mode database is preloaded,
locked in to memory, and will use huge
locked in to memory, and will use huge
pages if available.
--enable-account-queries arg (=0) enable queries to find accounts by
--eos-vm-oc-cache-size-mb arg (=1024) Maximum size (in MiB) of the EOS VM OC
code cache
--eos-vm-oc-compile-threads arg (=1) Number of threads to use for EOS VM OC
tier-up
--eos-vm-oc-enable Enable EOS VM OC tier-up runtime
--enable-account-queries arg (=0) enable queries to find accounts by
various metadata.
--max-nonprivileged-inline-action-size arg (=4096)
maximum allowed size (in bytes) of an
inline action for a nonprivileged
maximum allowed size (in bytes) of an
inline action for a nonprivileged
account
--transaction-retry-max-storage-size-gb arg
Maximum size (in GiB) allowed to be
allocated for the Transaction Retry
feature. Setting above 0 enables this
Maximum size (in GiB) allowed to be
allocated for the Transaction Retry
feature. Setting above 0 enables this
feature.
--transaction-retry-interval-sec arg (=20)
How often, in seconds, to resend an
incoming transaction to network if not
How often, in seconds, to resend an
incoming transaction to network if not
seen in a block.
--transaction-retry-max-expiration-sec arg (=90)
Maximum allowed transaction expiration
for retry transactions, will retry
--transaction-retry-max-expiration-sec arg (=120)
Maximum allowed transaction expiration
for retry transactions, will retry
transactions up to this value.
--transaction-finality-status-max-storage-size-gb arg
Maximum size (in GiB) allowed to be
allocated for the Transaction Finality
Maximum size (in GiB) allowed to be
allocated for the Transaction Finality
Status feature. Setting above 0 enables
this feature.
--transaction-finality-status-success-duration-sec arg (=180)
Duration (in seconds) a successful
transaction's Finality Status will
remain available from being first
Duration (in seconds) a successful
transaction's Finality Status will
remain available from being first
identified.
--transaction-finality-status-failure-duration-sec arg (=180)
Duration (in seconds) a failed
transaction's Finality Status will
remain available from being first
Duration (in seconds) a failed
transaction's Finality Status will
remain available from being first
identified.
--block-log-retain-blocks arg if set, periodically prune the block
log to store only configured number of
most recent blocks
```
@@ -1,59 +0,0 @@
[[warning | Deprecation Notice]]
| The `history_plugin` that the `history_api_plugin` depends upon is deprecated and will no longer be maintained. Please use the [`state_history_plugin`](../state_history_plugin/index.md) instead.
## Description
The `history_api_plugin` exposes functionality from the [`history_plugin`](../history_plugin/index.md) to the RPC API interface managed by the [`http_plugin`](../http_plugin/index.md), providing read-only access to blockchain data.
It provides four RPC API endpoints:
* get_actions
* get_transaction
* get_key_accounts
* get_controlled_accounts
The four actions listed above are used by the following `cleos` commands (matching order):
* get actions
* get transaction
* get accounts
* get servants
## Usage
```console
# config.ini
plugin = eosio::history_api_plugin
```
```sh
# command-line
nodeos ... --plugin eosio::history_api_plugin
```
## Options
None
## Dependencies
* [`history_plugin`](../history_plugin/index.md)
* [`chain_plugin`](../chain_plugin/index.md)
* [`http_plugin`](../http_plugin/index.md)
### Load Dependency Examples
```console
# config.ini
plugin = eosio::history_plugin
[options]
plugin = eosio::chain_plugin
[options]
plugin = eosio::http_plugin
[options]
```
```sh
# command-line
nodeos ... --plugin eosio::history_plugin [options] \
--plugin eosio::chain_plugin [operations] [options] \
--plugin eosio::http_plugin [options]
```
@@ -1,41 +0,0 @@
[[warning | Deprecation Notice]]
| The `history_plugin` is deprecated and will no longer be maintained. Please use the [`state_history_plugin`](../state_history_plugin/index.md) instead.
## Description
The `history_plugin` provides a cache layer to obtain historical data about the blockchain objects. It depends on [`chain_plugin`](../chain_plugin/index.md) for the data.
## Usage
```console
# config.ini
plugin = eosio::history_plugin
[options]
```
```sh
# command-line
nodeos ... --plugin eosio::history_plugin [options]
```
## Options
These can be specified from both the `nodeos` command-line or the `config.ini` file:
```console
Config Options for eosio::history_plugin:
-f [ --filter-on ] arg Track actions which match
receiver:action:actor. Actor may be
blank to include all. Action and Actor
both blank allows all from Recieiver.
Receiver may not be blank.
-F [ --filter-out ] arg Do not track actions which match
receiver:action:actor. Action and Actor
both blank excludes all from Reciever.
Actor blank excludes all from
reciever:action. Receiver may not be
blank.
```
## Dependencies
* [`chain_plugin`](../chain_plugin/index.md)
+23 -22
View File
@@ -22,46 +22,47 @@ These can be specified from both the command-line or the `config.ini` file:
```console
Config Options for eosio::http_plugin:
--unix-socket-path arg The filename (relative to data-dir) to
create a unix socket for HTTP RPC; set
blank to disable (=keosd.sock for keosd)
--http-server-address arg (=127.0.0.1:8888 for nodeos)
The local IP and port to listen for
--unix-socket-path arg The filename (relative to data-dir) to
create a unix socket for HTTP RPC; set
blank to disable.
--http-server-address arg (=127.0.0.1:8888)
The local IP and port to listen for
incoming http connections; set blank to
disable.
--https-server-address arg The local IP and port to listen for
--https-server-address arg The local IP and port to listen for
incoming https connections; leave blank
to disable.
--https-certificate-chain-file arg Filename with the certificate chain to
present on https connections. PEM
--https-certificate-chain-file arg Filename with the certificate chain to
present on https connections. PEM
format. Required for https.
--https-private-key-file arg Filename with https private key in PEM
--https-private-key-file arg Filename with https private key in PEM
format. Required for https
--https-ecdh-curve arg (=secp384r1) Configure https ECDH curve to use:
--https-ecdh-curve arg (=secp384r1) Configure https ECDH curve to use:
secp384r1 or prime256v1
--access-control-allow-origin arg Specify the Access-Control-Allow-Origin
to be returned on each request.
--access-control-allow-headers arg Specify the Access-Control-Allow-Header
s to be returned on each request.
--access-control-max-age arg Specify the Access-Control-Max-Age to
--access-control-max-age arg Specify the Access-Control-Max-Age to
be returned on each request.
--access-control-allow-credentials Specify if Access-Control-Allow-Credent
ials: true should be returned on each
ials: true should be returned on each
request.
--max-body-size arg (=1048576) The maximum body size in bytes allowed
--max-body-size arg (=2097152) The maximum body size in bytes allowed
for incoming RPC requests
--http-max-bytes-in-flight-mb arg (=500)
Maximum size in megabytes http_plugin
should use for processing http
requests. 503 error response when
exceeded.
Maximum size in megabytes http_plugin
should use for processing http
requests. -1 for unlimited. 429 error
response when exceeded.
--http-max-response-time-ms arg (=30) Maximum time for processing a request.
--verbose-http-errors Append the error log to HTTP responses
--http-validate-host arg (=1) If set to false, then any incoming
--http-validate-host arg (=1) If set to false, then any incoming
"Host" header is considered valid
--http-alias arg Additionaly acceptable values for the
"Host" header of incoming HTTP
requests, can be specified multiple
times. Includes http/s_server_address
--http-alias arg Additionaly acceptable values for the
"Host" header of incoming HTTP
requests, can be specified multiple
times. Includes http/s_server_address
by default.
--http-threads arg (=2) Number of worker threads in http thread
pool
@@ -44,7 +44,7 @@ Config Options for eosio::net_plugin:
--p2p-accept-transactions arg (=1) Allow transactions received over p2p
network to be evaluated and relayed if
valid.
--agent-name arg (="EOS Test Agent") The name supplied to identify this node
--agent-name arg (=EOS Test Agent) The name supplied to identify this node
amongst the peers.
--allowed-connection arg (=any) Can be 'any' or 'producers' or
'specified' or 'none'. If 'specified',
@@ -73,13 +73,15 @@ Config Options for eosio::net_plugin:
synchronization
--use-socket-read-watermark arg (=0) Enable experimental socket read
watermark optimization
--peer-log-format arg (=["${_name}" ${_ip}:${_port}])
--peer-log-format arg (=["${_name}" - ${_cid} ${_ip}:${_port}] )
The string used to format peers when
logging messages about them. Variables
are escaped with ${<variable name>}.
Available Variables:
_name self-reported name
_cid assigned connection id
_id self-reported ID (64 hex
characters)
@@ -94,7 +96,10 @@ Config Options for eosio::net_plugin:
peer
_lport local port number connected
to peer
to peer
--p2p-keepalive-interval-ms arg (=10000)
peer heartbeat keepalive message
interval in milliseconds
```
## Dependencies
@@ -23,7 +23,6 @@ These can be specified from both the `nodeos` command-line or the `config.ini` f
```console
Config Options for eosio::producer_plugin:
-e [ --enable-stale-production ] Enable block production, even if the
chain is stale.
-x [ --pause-on-startup ] Start this node in a state where
@@ -49,7 +48,7 @@ Config Options for eosio::producer_plugin:
<public-key>=<provider-spec>
Where:
<public-key> is a string form of
a vaild Antelope public
a valid EOS public
key
<provider-spec> is a string in the
@@ -59,7 +58,7 @@ Config Options for eosio::producer_plugin:
<provider-type> is KEY, or KEOSD
KEY:<data> is a string form of
a valid Antelope
a valid EOS
private key which
maps to the provided
public key
@@ -119,11 +118,6 @@ Config Options for eosio::producer_plugin:
Sets the maximum amount of failures
that are allowed for a given account
per block.
Disregarded for accounts that have been
whitelisted by disabling subjective
billing for the account using the
disable-subjective-account-billing
configuration option.
--subjective-account-decay-time-minutes arg (=1440)
Sets the time to return full subjective
cpu for accounts
@@ -142,9 +136,6 @@ Config Options for eosio::producer_plugin:
--disable-subjective-account-billing arg
Account which is excluded from
subjective CPU billing
Account is considered whitelisted and
will not be subject to enforcement of
subjective-account-max-failures.
--disable-subjective-p2p-billing arg (=1)
Disable subjective CPU billing for P2P
transactions
@@ -1,19 +1,10 @@
## Overview
The `resource_monitor_plugin` monitors space usage in the computing system where `nodeos` is running. Specifically, every `resource-monitor-interval-seconds` seconds,
it measures the individual space used by each of the file systems mounted
by `data-dir`, `state-dir`, `blocks-log-dir`, `snapshots-dir`,
`state-history-dir`, and `trace-dir`.
When space usage in any of the monitored file system is within `5%` of the threshold
specified by `resource-monitor-space-threshold`, a warning containing the file system
path and percentage of space has used is printed out.
When space usage exceeds the threshold,
if `resource-monitor-not-shutdown-on-threshold-exceeded` is not set,
`nodeos` gracefully shuts down; if `resource-monitor-not-shutdown-on-threshold-exceeded` is set, `nodeos` prints out warnings periodically
until space usage goes under the threshold.
The `resource_monitor_plugin` monitors space usage in the computing system where `nodeos` is running. Specifically, every `resource-monitor-interval-seconds` seconds, it measures the individual space used by each of the file systems mounted by `data-dir`, `state-dir`, `blocks-log-dir`, `snapshots-dir`, `state-history-dir`, and `trace-dir`. When space usage in any of the monitored file system is within `5%` of the threshold specified by `resource-monitor-space-threshold`, a warning containing the file system path and percentage of space has used is printed out. When space usage exceeds the threshold, if `resource-monitor-not-shutdown-on-threshold-exceeded` is not set, `nodeos` gracefully shuts down; if `resource-monitor-not-shutdown-on-threshold-exceeded` is set, `nodeos` prints out warnings periodically until space usage goes under the threshold.
`resource_monitor_plugin` is always loaded.
## Usage
```console
@@ -32,33 +23,28 @@ These can be specified from both the `nodeos` command-line or the `config.ini` f
```console
Config Options for eosio::resource_monitor_plugin:
--resource-monitor-interval-seconds arg (=2)
Time in seconds between two consecutive checks
of space usage. Should be between 1 and 300.
Time in seconds between two consecutive
checks of resource usage. Should be
between 1 and 300
--resource-monitor-space-threshold arg (=90)
Threshold in terms of percentage of used space
vs total space. If the used space is within
`5%` of the threshold, a warning is generated.
If the used space is above the threshold and
`resource-monitor-not-shutdown-on-threshold-exceeded`
is enabled, a shutdown is initiated; otherwise
a warning will be continuously printed out.
The value should be between 6 and 99.
Threshold in terms of percentage of
used space vs total space. If used
space is above (threshold - 5%), a
warning is generated. Unless
resource-monitor-not-shutdown-on-thresh
old-exceeded is enabled, a graceful
shutdown is initiated if used space is
above the threshold. The value should
be between 6 and 99
--resource-monitor-not-shutdown-on-threshold-exceeded
A switch used to indicate `nodeos` will "not"
shutdown when threshold is exceeded. When not
set, `nodeos` will shutdown.
Used to indicate nodeos will not
shutdown when threshold is exceeded.
--resource-monitor-warning-interval arg (=30)
Number of monitor intervals between which a
warning is displayed. For example, if
`resource-monitor-warning-interval` is to 10
and `resource-monitor-interval-seconds` is 2,
a warning will be displayed every 20 seconds,
even though the space usage is checked every
2 seconds. This is used to throttle the
number of warnings in the `nodeos` log file.
Should be between 1 and 450.
Number of resource monitor intervals
between two consecutive warnings when
the threshold is hit. Should be between
1 and 450
```
## Plugin Dependencies
@@ -31,19 +31,21 @@ These can be specified from both the `nodeos` command-line or the `config.ini` f
```console
Config Options for eosio::state_history_plugin:
--state-history-dir arg (="state-history")
the location of the state-history
the location of the state-history
directory (absolute path or relative to
application data dir)
--trace-history enable trace history
--chain-state-history enable chain state history
--state-history-endpoint arg (=127.0.0.1:8080)
the endpoint upon which to listen for
incoming connections. Caution: only
expose this port to your internal
the endpoint upon which to listen for
incoming connections. Caution: only
expose this port to your internal
network.
--trace-history-debug-mode enable debug mode for trace history
--state-history-log-retain-blocks arg if set, periodically prune the state
history files to store only configured
number of most recent blocks
```
## Examples
@@ -64,24 +64,3 @@ Sample `logging.json`:
]
}
```
## Expected Output of Log Levels
* `error` - Log output that likely requires operator intervention.
- Error level logging should be reserved for conditions that are completely unexpected or otherwise need human intervention.
- Also used to indicate software errors such as: impossible values for an `enum`, out of bounds array access, null pointers, or other conditions that likely will throw an exception.
- *Note*: Currently, there are numerous `error` level logging that likely should be `warn` as they do not require human intervention. The `net_plugin_impl`, for example, has a number of `error` level logs for bad network connections. This is handled and processed correctly. These should be changed to `warn` or `info`.
* `warn` - Log output indicating unexpected but recoverable errors.
- Although, `warn` level typically does not require human intervention, repeated output of `warn` level logs might indicate actions needed by an operator.
- `warn` should not be used simply for conveying information. A `warn` level log is something to take notice of, but not necessarily be concerned about.
* `info` (default) - Log output that provides useful information to an operator.
- Can be just progress indication or other useful data to a user. Care is taken not to create excessive log output with `info` level logging. For example, no `info` level logging should be produced for every transaction.
- For progress indication, some multiple of transactions should be processed between each log output; typically, every 1000 transactions.
* `debug` - Useful log output for when non-default logging is enabled.
- Answers the question: is this useful information for a user that is monitoring the log output. Care should be taken not to create excessive log output; similar to `info` level logging.
- Enabling `debug` level logging should provide greater insight into behavior without overwhelming the output with log entries.
- `debug` level should not be used for *trace* level logging; to that end, use `all` (see below).
- Like `info`, no `debug` level logging should be produced for every transaction. There are specific transaction level loggers dedicated to transaction level logging: `transaction`, `transaction_trace_failure`, `transaction_trace_success`, `transaction_failure_tracing`, `transaction_success_tracing`.
* `all` (trace) - For logging that would be overwhelming if `debug` level logging were used.
- Can be used for trace level logging. Only used in a few places and not completely supported.
- *Note*: In the future a different logging library may provide better trace level logging support. The current logging framework is not performant enough to enable excess trace level output.
+6 -8
View File
@@ -4,10 +4,15 @@ set(APPBASE_INSTALL_COMPONENT "dev")
set(SOFTFLOAT_INSTALL_COMPONENT "dev")
set(EOSVM_INSTALL_COMPONENT "dev")
add_subdirectory( libfc )
add_subdirectory( fc )
add_subdirectory( builtins )
# Suppress warnings on 3rdParty Library
add_definitions( -w )
add_subdirectory( softfloat )
add_subdirectory( wasm-jit )
remove_definitions( -w )
add_subdirectory( chainbase )
set(APPBASE_ENABLE_AUTO_VERSION OFF CACHE BOOL "enable automatic discovery of version via 'git describe'")
add_subdirectory( appbase )
@@ -15,7 +20,6 @@ add_subdirectory( chain )
add_subdirectory( testing )
add_subdirectory( version )
add_subdirectory( state_history )
add_subdirectory( cli11 )
set(USE_EXISTING_SOFTFLOAT ON CACHE BOOL "use pre-exisiting softfloat lib")
set(ENABLE_TOOLS OFF CACHE BOOL "Build tools")
@@ -27,12 +31,6 @@ if(eos-vm IN_LIST EOSIO_WASM_RUNTIMES OR eos-vm-jit IN_LIST EOSIO_WASM_RUNTIMES)
add_subdirectory( eos-vm )
endif()
#yubihsm's openssl discovery is via pkg-config instead of find_package. Help it out on macOS otherwise openssl's pkgconfig
# files may not be found down in the /opt/homebrew/opt directory
if(APPLE)
get_filename_component(OPENSSL_LIB_PATH "${OPENSSL_CRYPTO_LIBRARY}" DIRECTORY)
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${OPENSSL_LIB_PATH}/pkgconfig")
endif()
set(ENABLE_STATIC ON)
set(CMAKE_MACOSX_RPATH OFF)
set(BUILD_ONLY_LIB ON CACHE BOOL "Library only build")
+4 -4
View File
@@ -72,9 +72,6 @@ set(CHAIN_WEBASSEMBLY_SOURCES
webassembly/transaction.cpp
)
add_library(eosio_rapidjson INTERFACE)
target_include_directories(eosio_rapidjson INTERFACE ../rapidjson/include)
## SORT .cpp by most likely to change / break compile
add_library( eosio_chain
merkle.cpp
@@ -128,7 +125,7 @@ add_library( eosio_chain
${HEADERS}
)
target_link_libraries( eosio_chain PUBLIC fc chainbase eosio_rapidjson Logging IR WAST WASM Runtime
target_link_libraries( eosio_chain PUBLIC fc chainbase Logging IR WAST WASM Runtime
softfloat builtins ${CHAIN_EOSVM_LIBRARIES} ${LLVM_LIBS} ${CHAIN_RT_LINKAGE}
)
target_include_directories( eosio_chain
@@ -165,3 +162,6 @@ install( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/eosio/chain/
FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h" EXCLUDE
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/eosio/chain/core_symbol.hpp DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/eosio/chain COMPONENT dev EXCLUDE_FROM_ALL)
#if(MSVC)
# set_source_files_properties( db_init.cpp db_block.cpp database.cpp block_log.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
#endif(MSVC)
+5 -18
View File
@@ -77,7 +77,7 @@ namespace eosio { namespace chain {
abi_serializer::abi_serializer( const abi_def& abi, const fc::microseconds& max_serialization_time) {
configure_built_in_types();
set_abi(abi, create_yield_function(max_serialization_time));
set_abi(abi, max_serialization_time);
}
void abi_serializer::add_specialized_unpack_pack( const string& name,
@@ -209,19 +209,6 @@ namespace eosio { namespace chain {
return ends_with(type, "[]");
}
bool abi_serializer::is_szarray(const string_view& type)const {
auto pos1 = type.find_last_of('[');
auto pos2 = type.find_last_of(']');
if(pos1 == string_view::npos || pos2 == string_view::npos) return false;
auto pos = pos1 + 1;
if(pos == pos2) return false;
while(pos < pos2) {
if( ! (type[pos] >= '0' && type[pos] <= '9') ) return false;
++pos;
}
return true;
}
bool abi_serializer::is_optional(const string_view& type)const {
return ends_with(type, "?");
}
@@ -238,8 +225,6 @@ namespace eosio { namespace chain {
std::string_view abi_serializer::fundamental_type(const std::string_view& type)const {
if( is_array(type) ) {
return type.substr(0, type.size()-2);
} else if (is_szarray (type) ){
return type.substr(0, type.find_last_of('['));
} else if ( is_optional(type) ) {
return type.substr(0, type.size()-1);
} else {
@@ -410,8 +395,10 @@ namespace eosio { namespace chain {
for( decltype(size.value) i = 0; i < size; ++i ) {
ctx.set_array_index_of_path_back(i);
auto v = _binary_to_variant(ftype, stream, ctx);
// The exception below is commented out to allow array of optional as input data
//EOS_ASSERT( !v.is_null(), unpack_exception, "Invalid packed array '${p}'", ("p", ctx.get_path_string()) );
// QUESTION: Is it actually desired behavior to require the returned variant to not be null?
// This would disallow arrays of optionals in general (though if all optionals in the array were present it would be allowed).
// Is there any scenario in which the returned variant would be null other than in the case of an empty optional?
EOS_ASSERT( !v.is_null(), unpack_exception, "Invalid packed array '${p}'", ("p", ctx.get_path_string()) );
vars.emplace_back(std::move(v));
}
// QUESTION: Why would the assert below ever fail?
+41 -43
View File
@@ -71,53 +71,51 @@ void apply_context::exec_one()
try {
action_return_value.clear();
receiver_account = &db.get<account_metadata_object,by_name>( receiver );
if( !(context_free && control.skip_trx_checks()) ) {
privileged = receiver_account->is_privileged();
auto native = control.find_apply_handler( receiver, act->account, act->name );
if( native ) {
if( trx_context.enforce_whiteblacklist && control.is_producing_block() ) {
control.check_contract_list( receiver );
control.check_action_list( act->account, act->name );
}
(*native)( *this );
privileged = receiver_account->is_privileged();
auto native = control.find_apply_handler( receiver, act->account, act->name );
if( native ) {
if( trx_context.enforce_whiteblacklist && control.is_producing_block() ) {
control.check_contract_list( receiver );
control.check_action_list( act->account, act->name );
}
(*native)( *this );
}
if( ( receiver_account->code_hash != digest_type() ) &&
( !( act->account == config::system_account_name
&& act->name == "setcode"_n
&& receiver == config::system_account_name )
|| control.is_builtin_activated( builtin_protocol_feature_t::forward_setcode )
)
) {
if( trx_context.enforce_whiteblacklist && control.is_producing_block() ) {
control.check_contract_list( receiver );
control.check_action_list( act->account, act->name );
}
try {
control.get_wasm_interface().apply( receiver_account->code_hash, receiver_account->vm_type, receiver_account->vm_version, *this );
} catch( const wasm_exit& ) {}
if( ( receiver_account->code_hash != digest_type() ) &&
( !( act->account == config::system_account_name
&& act->name == "setcode"_n
&& receiver == config::system_account_name )
|| control.is_builtin_activated( builtin_protocol_feature_t::forward_setcode )
)
) {
if( trx_context.enforce_whiteblacklist && control.is_producing_block() ) {
control.check_contract_list( receiver );
control.check_action_list( act->account, act->name );
}
try {
control.get_wasm_interface().apply( receiver_account->code_hash, receiver_account->vm_type, receiver_account->vm_version, *this );
} catch( const wasm_exit& ) {}
}
if( !privileged && control.is_builtin_activated( builtin_protocol_feature_t::ram_restrictions ) ) {
const size_t checktime_interval = 10;
size_t counter = 0;
bool not_in_notify_context = (receiver == act->account);
const auto end = _account_ram_deltas.end();
for( auto itr = _account_ram_deltas.begin(); itr != end; ++itr, ++counter ) {
if( counter == checktime_interval ) {
trx_context.checktime();
counter = 0;
}
if( itr->delta > 0 && itr->account != receiver ) {
EOS_ASSERT( not_in_notify_context, unauthorized_ram_usage_increase,
"unprivileged contract cannot increase RAM usage of another account within a notify context: ${account}",
("account", itr->account)
);
EOS_ASSERT( has_authorization( itr->account ), unauthorized_ram_usage_increase,
"unprivileged contract cannot increase RAM usage of another account that has not authorized the action: ${account}",
("account", itr->account)
);
}
if( !privileged && control.is_builtin_activated( builtin_protocol_feature_t::ram_restrictions ) ) {
const size_t checktime_interval = 10;
size_t counter = 0;
bool not_in_notify_context = (receiver == act->account);
const auto end = _account_ram_deltas.end();
for( auto itr = _account_ram_deltas.begin(); itr != end; ++itr, ++counter ) {
if( counter == checktime_interval ) {
trx_context.checktime();
counter = 0;
}
if( itr->delta > 0 && itr->account != receiver ) {
EOS_ASSERT( not_in_notify_context, unauthorized_ram_usage_increase,
"unprivileged contract cannot increase RAM usage of another account within a notify context: ${account}",
("account", itr->account)
);
EOS_ASSERT( has_authorization( itr->account ), unauthorized_ram_usage_increase,
"unprivileged contract cannot increase RAM usage of another account that has not authorized the action: ${account}",
("account", itr->account)
);
}
}
}
+63 -149
View File
@@ -1,5 +1,6 @@
#include <eosio/chain/block_log.hpp>
#include <eosio/chain/exceptions.hpp>
#include <fstream>
#include <fc/bitutil.hpp>
#include <fc/io/cfile.hpp>
#include <fc/io/raw.hpp>
@@ -48,21 +49,14 @@ namespace eosio { namespace chain {
uint32_t first_block_num = 0; //the first number available to read
uint32_t index_first_block_num = 0; //the first number in index & the log had it not been pruned
std::optional<block_log_prune_config> prune_config;
bool not_generate_block_log = false;
explicit block_log_impl(std::optional<block_log_prune_config> prune_conf) :
block_log_impl(std::optional<block_log_prune_config> prune_conf) :
prune_config(prune_conf) {
if(prune_config) {
if (prune_config->prune_blocks == 0 ) {
// not to generate blocks.log
// disable prune log handling by resetting prune_config
prune_config.reset();
not_generate_block_log = true;
} else {
EOS_ASSERT(__builtin_popcount(prune_config->prune_threshold) == 1, block_log_exception, "block log prune threshold must be power of 2");
//switch this over to the mask that will be used
prune_config->prune_threshold = ~(prune_config->prune_threshold-1);
}
EOS_ASSERT(prune_config->prune_blocks, block_log_exception, "block log prune configuration requires at least one block");
EOS_ASSERT(__builtin_popcount(prune_config->prune_threshold) == 1, block_log_exception, "block log prune threshold must be power of 2");
//switch this over to the mask that will be used
prune_config->prune_threshold = ~(prune_config->prune_threshold-1);
}
}
@@ -71,7 +65,6 @@ namespace eosio { namespace chain {
reopen();
}
}
void reopen();
//close() is called all over the place. Let's make this an explict call to ensure it only is called when
@@ -106,17 +99,13 @@ namespace eosio { namespace chain {
template<typename T>
void reset( const T& t, const signed_block_ptr& genesis_block, uint32_t first_block_num );
void remove();
void write( const genesis_state& gs );
void write( const chain_id_type& chain_id );
void flush();
void append(const signed_block_ptr& b, const block_id_type& id, const std::vector<char>& packed_block);
void update_head(const signed_block_ptr& b, const std::optional<block_id_type>& id={});
void append(const signed_block_ptr& b);
void prune(const fc::log_level& loglevel);
@@ -302,7 +291,12 @@ namespace eosio { namespace chain {
}
my->index_first_block_num = my->first_block_num;
my->update_head(read_head());
my->head = read_head();
if( my->head ) {
my->head_id = my->head->calculate_id();
} else {
my->head_id = {};
}
my->block_file.seek_end(0);
if(is_currently_pruned && my->head) {
@@ -361,23 +355,14 @@ namespace eosio { namespace chain {
}
}
void block_log::append(const signed_block_ptr& b, const block_id_type& id) {
my->append(b, id, fc::raw::pack(*b));
void block_log::append(const signed_block_ptr& b) {
my->append(b);
}
void block_log::append(const signed_block_ptr& b, const block_id_type& id, const std::vector<char>& packed_block) {
my->append(b, id, packed_block);
}
void detail::block_log_impl::append(const signed_block_ptr& b, const block_id_type& id, const std::vector<char>& packed_block) {
void detail::block_log_impl::append(const signed_block_ptr& b) {
try {
EOS_ASSERT( genesis_written_to_block_log, block_log_append_fail, "Cannot append to block log until the genesis is first written" );
if (not_generate_block_log) {
update_head(b, id);
return;
}
check_open_files();
block_file.seek_end(0);
@@ -392,12 +377,13 @@ namespace eosio { namespace chain {
"Append to index file occuring at wrong position.",
("position", (uint64_t) index_file.tellp())
("expected", (b->block_num() - index_first_block_num) * sizeof(uint64_t)));
block_file.write(packed_block.data(), packed_block.size());
auto data = fc::raw::pack(*b);
block_file.write(data.data(), data.size());
block_file.write((char*)&pos, sizeof(pos));
const uint64_t end = block_file.tellp();
index_file.write((char*)&pos, sizeof(pos));
update_head(b, id);
head = b;
head_id = b->calculate_id();
if(prune_config) {
if((pos&prune_config->prune_threshold) != (end&prune_config->prune_threshold))
@@ -412,19 +398,6 @@ namespace eosio { namespace chain {
FC_LOG_AND_RETHROW()
}
void detail::block_log_impl::update_head(const signed_block_ptr& b, const std::optional<block_id_type>& id) {
head = b;
if (id) {
head_id = *id;
} else {
if (head) {
head_id = b->calculate_id();
} else {
head_id = {};
}
}
}
void detail::block_log_impl::prune(const fc::log_level& loglevel) {
if(!head)
return;
@@ -451,9 +424,6 @@ namespace eosio { namespace chain {
}
void block_log::flush() {
if (my->not_generate_block_log) {
return;
}
my->flush();
}
@@ -598,7 +568,7 @@ namespace eosio { namespace chain {
block_file.write((char*)&totem, sizeof(totem));
if (first_block) {
append(first_block, first_block->calculate_id(), fc::raw::pack(*first_block));
append(first_block);
} else {
head.reset();
head_id = {};
@@ -621,30 +591,15 @@ namespace eosio { namespace chain {
}
void block_log::reset( const genesis_state& gs, const signed_block_ptr& first_block ) {
// At startup, OK to be called in no blocks.log mode from controller.cpp
my->reset(gs, first_block, 1);
}
void block_log::reset( const chain_id_type& chain_id, uint32_t first_block_num ) {
// At startup, OK to be called in no blocks.log mode from controller.cpp
EOS_ASSERT( first_block_num > 1, block_log_exception,
"Block log version ${ver} needs to be created with a genesis state if starting from block number 1." );
my->reset(chain_id, signed_block_ptr(), first_block_num);
}
void detail::block_log_impl::remove() {
close();
fc::remove( block_file.get_file_path() );
fc::remove( index_file.get_file_path() );
ilog("block log ${l}, block index ${i} removed", ("l", block_file.get_file_path()) ("i", index_file.get_file_path()));
}
void block_log::remove() {
my->remove();
}
void detail::block_log_impl::write( const genesis_state& gs ) {
auto data = fc::raw::pack(gs);
block_file.write(data.data(), data.size());
@@ -655,10 +610,6 @@ namespace eosio { namespace chain {
}
signed_block_ptr block_log::read_block(uint64_t pos)const {
if (my->not_generate_block_log) {
return nullptr;
}
my->check_open_files();
my->block_file.seek(pos);
@@ -669,10 +620,6 @@ namespace eosio { namespace chain {
}
void block_log::read_block_header(block_header& bh, uint64_t pos)const {
if (my->not_generate_block_log) {
return;
}
my->check_open_files();
my->block_file.seek(pos);
@@ -683,12 +630,6 @@ namespace eosio { namespace chain {
signed_block_ptr block_log::read_block_by_num(uint32_t block_num)const {
try {
signed_block_ptr b;
if (my->not_generate_block_log) {
// No blocks exist. Avoid cascading failures if going further.
return b;
}
uint64_t pos = get_block_pos(block_num);
if (pos != npos) {
b = read_block(pos);
@@ -701,9 +642,6 @@ namespace eosio { namespace chain {
block_id_type block_log::read_block_id_by_num(uint32_t block_num)const {
try {
if (my->not_generate_block_log) {
return {};
}
uint64_t pos = get_block_pos(block_num);
if (pos != npos) {
block_header bh;
@@ -727,17 +665,10 @@ namespace eosio { namespace chain {
}
uint64_t block_log::get_block_pos(uint32_t block_num) const {
if (my->not_generate_block_log) {
return block_log::npos;
}
return my->get_block_pos(block_num);
}
signed_block_ptr block_log::read_head()const {
if (my->not_generate_block_log) {
return {};
}
my->check_open_files();
uint64_t pos;
@@ -777,11 +708,6 @@ namespace eosio { namespace chain {
}
void block_log::construct_index() {
if (my->not_generate_block_log) {
ilog("Not need to construct index in no blocks.log mode (block-log-retain-blocks=0)");
return;
}
ilog("Reconstructing Block Log Index...");
my->close();
@@ -1261,29 +1187,31 @@ namespace eosio { namespace chain {
}
}
bool block_log::extract_block_range(const fc::path& block_dir, const fc::path&output_dir, block_num_type& start, block_num_type& end, bool rename_input) {
EOS_ASSERT( block_dir != output_dir, block_log_exception, "block_dir and output_dir need to be different directories" );
bool block_log::trim_blocklog_front(const fc::path& block_dir, const fc::path& temp_dir, uint32_t truncate_at_block) {
using namespace std;
EOS_ASSERT( block_dir != temp_dir, block_log_exception, "block_dir and temp_dir need to be different directories" );
ilog("In directory ${dir} will trim all blocks before block ${n} from blocks.log and blocks.index.",
("dir", block_dir.generic_string())("n", truncate_at_block));
trim_data original_block_log(block_dir);
if(start < original_block_log.first_block) {
dlog("Requested start block of ${start} is less than the first available block ${n}; adjusting to ${n}", ("start", start)("n", original_block_log.first_block));
start = original_block_log.first_block;
if (truncate_at_block <= original_block_log.first_block) {
ilog("There are no blocks before block ${n} so do nothing.", ("n", truncate_at_block));
return false;
}
if(end > original_block_log.last_block) {
dlog("Requested end block of ${end} is greater than the last available block ${n}; adjusting to ${n}", ("end", end)("n", original_block_log.last_block));
end = original_block_log.last_block;
if (truncate_at_block > original_block_log.last_block) {
ilog("All blocks are before block ${n} so do nothing (trim front would delete entire blocks.log).", ("n", truncate_at_block));
return false;
}
ilog("In directory ${output} will create new block log with range ${start}-${end}",
("output", output_dir.generic_string())("start", start)("end", end));
// ****** create the new block log file and write out the header for the file
fc::create_directories(output_dir);
fc::path new_block_filename = output_dir / "blocks.log";
fc::create_directories(temp_dir);
fc::path new_block_filename = temp_dir / "blocks.log";
if (fc::remove(new_block_filename)) {
ilog("Removing existing blocks.log file");
ilog("Removing old blocks.out file");
}
fc::cfile new_block_file;
new_block_file.set_file_path(new_block_filename);
// need to open as write since the file doesn't already exist, then reopen
// with read/write to allow writing the file in any order
// need to open as append since the file doesn't already exist, then reopen without append to allow writing the
// file in any order
new_block_file.open( LOG_WRITE_C );
new_block_file.close();
new_block_file.open( LOG_RW_C );
@@ -1293,49 +1221,37 @@ namespace eosio { namespace chain {
uint32_t version = block_log::max_supported_version;
new_block_file.seek(0);
new_block_file.write((char*)&version, sizeof(version));
new_block_file.write((char*)&start, sizeof(start));
new_block_file.write((char*)&truncate_at_block, sizeof(truncate_at_block));
if (start > 1) {
new_block_file << original_block_log.chain_id;
} else {
fc::raw::pack(new_block_file, original_block_log.gs);
}
new_block_file << original_block_log.chain_id;
// append a totem to indicate the division between blocks and header
auto totem = block_log::npos;
new_block_file.write((char*)&totem, sizeof(totem));
// ****** end of new block log header
const auto new_block_file_first_block_pos = new_block_file.tellp();
// ****** end of new block log header
// copy over remainder of block log to new block log
auto buffer = std::make_unique<char[]>(detail::reverse_iterator::_buf_len);
auto buffer = make_unique<char[]>(detail::reverse_iterator::_buf_len);
char* buf = buffer.get();
// offset bytes to shift from old blocklog position to new blocklog position
const uint64_t original_file_start_block_pos = original_block_log.block_pos(start);
const uint64_t pos_delta = original_file_start_block_pos - new_block_file_first_block_pos;
uint64_t original_file_end_block_pos;
if (end == original_block_log.last_block) {
auto status = fseek(original_block_log.blk_in, 0, SEEK_END);
EOS_ASSERT( status == 0, block_log_exception, "blocks.log seek failed" );
original_file_end_block_pos = ftell(original_block_log.blk_in);
} else {
original_file_end_block_pos = original_block_log.block_pos(end+1);
auto status = fseek(original_block_log.blk_in, original_file_end_block_pos, SEEK_SET);
EOS_ASSERT( status == 0, block_log_exception, "blocks.log seek failed" );
}
const uint64_t original_file_block_pos = original_block_log.block_pos(truncate_at_block);
const uint64_t pos_delta = original_file_block_pos - new_block_file_first_block_pos;
auto status = fseek(original_block_log.blk_in, 0, SEEK_END);
EOS_ASSERT( status == 0, block_log_exception, "blocks.log seek failed" );
// all bytes to copy to the new blocklog
const uint64_t to_write = original_file_end_block_pos - original_file_start_block_pos;
// all blocks to copy to the new blocklog
const uint64_t to_write = ftell(original_block_log.blk_in) - original_file_block_pos;
const auto pos_size = sizeof(uint64_t);
// start with the last block's position stored at the end of the block
const auto pos_size = sizeof(uint64_t);
uint64_t original_pos = original_file_end_block_pos - pos_size;
uint64_t original_pos = ftell(original_block_log.blk_in) - pos_size;
const auto num_blocks = end - start + 1;
const auto num_blocks = original_block_log.last_block - truncate_at_block + 1;
fc::path new_index_filename = output_dir / "blocks.index";
fc::path new_index_filename = temp_dir / "blocks.index";
detail::index_writer index(new_index_filename, num_blocks);
uint64_t read_size = 0;
@@ -1347,11 +1263,10 @@ namespace eosio { namespace chain {
}
// read in the previous contiguous memory into the read buffer
const auto start_of_blk_buffer_pos = original_file_start_block_pos + to_write_remaining - read_size;
auto status = fseek(original_block_log.blk_in, start_of_blk_buffer_pos, SEEK_SET);
EOS_ASSERT( status == 0, block_log_exception, "original blocks.log seek failed" );
const auto start_of_blk_buffer_pos = original_file_block_pos + to_write_remaining - read_size;
status = fseek(original_block_log.blk_in, start_of_blk_buffer_pos, SEEK_SET);
const auto num_read = fread(buf, read_size, 1, original_block_log.blk_in);
EOS_ASSERT( num_read == 1, block_log_exception, "original blocks.log read failed" );
EOS_ASSERT( num_read == 1, block_log_exception, "blocks.log read failed" );
// walk this memory section to adjust block position to match the adjusted location
// of the block start and store in the new index file
@@ -1380,14 +1295,12 @@ namespace eosio { namespace chain {
new_block_file.flush();
new_block_file.close();
if (rename_input) {
fc::path old_log = output_dir / "old.log";
rename(original_block_log.block_file_name, old_log);
rename(new_block_filename, original_block_log.block_file_name);
fc::path old_ind = output_dir / "old.index";
rename(original_block_log.index_file_name, old_ind);
rename(new_index_filename, original_block_log.index_file_name);
}
fc::path old_log = temp_dir / "old.log";
rename(original_block_log.block_file_name, old_log);
rename(new_block_filename, original_block_log.block_file_name);
fc::path old_ind = temp_dir / "old.index";
rename(original_block_log.index_file_name, old_ind);
rename(new_index_filename, original_block_log.index_file_name);
return true;
}
@@ -1422,6 +1335,7 @@ namespace eosio { namespace chain {
EOS_ASSERT(size == 1, block_log_exception, "invalid format for file ${file}",
("file", block_file_name.string()));
if (block_log::contains_genesis_state(version, first_block)) {
genesis_state gs;
fc::raw::unpack(ds, gs);
chain_id = gs.compute_chain_id();
}
@@ -1517,4 +1431,4 @@ namespace eosio { namespace chain {
// used only for unit test to adjust the buffer length
void block_log_set_buff_len(uint64_t len){
eosio::chain::detail::reverse_iterator::_buf_len = len;
}
}
+1 -1
View File
@@ -88,7 +88,7 @@ namespace eosio { namespace chain {
block_state::block_state( pending_block_header_state&& cur,
signed_block_ptr&& b,
deque<transaction_metadata_ptr>&& trx_metas,
vector<transaction_metadata_ptr>&& trx_metas,
const protocol_feature_set& pfs,
const std::function<void( block_timestamp_type,
const flat_set<digest_type>&,
+129 -179
View File
@@ -115,23 +115,22 @@ struct building_block {
const vector<digest_type>& new_protocol_feature_activations )
:_pending_block_header_state( prev.next( when, num_prev_blocks_to_confirm ) )
,_new_protocol_feature_activations( new_protocol_feature_activations )
,_trx_mroot_or_receipt_digests( digests_t{} )
{}
pending_block_header_state _pending_block_header_state;
std::optional<producer_authority_schedule> _new_pending_producer_schedule;
vector<digest_type> _new_protocol_feature_activations;
size_t _num_new_protocol_features_that_have_activated = 0;
deque<transaction_metadata_ptr> _pending_trx_metas;
deque<transaction_receipt> _pending_trx_receipts; // boost deque in 1.71 with 1024 elements performs better
std::variant<checksum256_type, digests_t> _trx_mroot_or_receipt_digests;
digests_t _action_receipt_digests;
vector<transaction_metadata_ptr> _pending_trx_metas;
vector<transaction_receipt> _pending_trx_receipts;
vector<digest_type> _action_receipt_digests;
std::optional<checksum256_type> _transaction_mroot;
};
struct assembled_block {
block_id_type _id;
pending_block_header_state _pending_block_header_state;
deque<transaction_metadata_ptr> _trx_metas;
vector<transaction_metadata_ptr> _trx_metas;
signed_block_ptr _unsigned_block;
// if the _unsigned_block pre-dates block-signing authorities this may be present.
@@ -157,7 +156,6 @@ struct pending_state {
block_stage_type _block_stage;
controller::block_status _block_status = controller::block_status::incomplete;
std::optional<block_id_type> _producer_block_id;
controller::block_report _block_report{};
/** @pre _block_stage cannot hold completed_block alternative */
const pending_block_header_state& get_pending_block_header_state()const {
@@ -167,7 +165,17 @@ struct pending_state {
return std::get<assembled_block>(_block_stage)._pending_block_header_state;
}
deque<transaction_metadata_ptr> extract_trx_metas() {
const vector<transaction_receipt>& get_trx_receipts()const {
if( std::holds_alternative<building_block>(_block_stage) )
return std::get<building_block>(_block_stage)._pending_trx_receipts;
if( std::holds_alternative<assembled_block>(_block_stage) )
return std::get<assembled_block>(_block_stage)._unsigned_block->transactions;
return std::get<completed_block>(_block_stage)._block_state->block->transactions;
}
vector<transaction_metadata_ptr> extract_trx_metas() {
if( std::holds_alternative<building_block>(_block_stage) )
return std::move( std::get<building_block>(_block_stage)._pending_trx_metas );
@@ -239,7 +247,6 @@ struct controller_impl {
named_thread_pool thread_pool;
platform_timer timer;
deep_mind_handler* deep_mind_logger = nullptr;
bool okay_to_print_integrity_hash_on_stop = false;
#if defined(EOSIO_EOS_VM_RUNTIME_ENABLED) || defined(EOSIO_EOS_VM_JIT_RUNTIME_ENABLED)
vm::wasm_allocator wasm_alloc;
#endif
@@ -404,20 +411,12 @@ struct controller_impl {
if( fork_head->dpos_irreversible_blocknum <= lib_num )
return;
auto branch = fork_db.fetch_branch( fork_head->id, fork_head->dpos_irreversible_blocknum );
const auto branch = fork_db.fetch_branch( fork_head->id, fork_head->dpos_irreversible_blocknum );
try {
std::vector<std::future<std::vector<char>>> v;
v.reserve( branch.size() );
for( auto bitr = branch.rbegin(); bitr != branch.rend(); ++bitr ) {
v.emplace_back( async_thread_pool( thread_pool.get_executor(), [b=(*bitr)->block]() { return fc::raw::pack(*b); } ) );
}
auto it = v.begin();
for( auto bitr = branch.rbegin(); bitr != branch.rend(); ++bitr ) {
if( read_mode == db_read_mode::IRREVERSIBLE ) {
controller::block_report br;
apply_block( br, *bitr, controller::block_status::complete, trx_meta_cache_lookup{} );
apply_block( *bitr, controller::block_status::complete, trx_meta_cache_lookup{} );
head = (*bitr);
fork_db.mark_valid( head );
}
@@ -426,8 +425,7 @@ struct controller_impl {
// blog.append could fail due to failures like running out of space.
// Do it before commit so that in case it throws, DB can be rolled back.
blog.append( (*bitr)->block, (*bitr)->id, it->get() );
++it;
blog.append( (*bitr)->block );
db.commit( (*bitr)->block_num );
root_id = (*bitr)->id;
@@ -442,12 +440,8 @@ struct controller_impl {
//db.commit( fork_head->dpos_irreversible_blocknum ); // redundant
if( root_id != fork_db.root()->id ) {
branch.emplace_back(fork_db.root());
fork_db.advance_root( root_id );
}
// delete branch in thread pool
boost::asio::post( thread_pool.get_executor(), [branch{std::move(branch)}]() {} );
}
/**
@@ -574,6 +568,8 @@ struct controller_impl {
"Snapshot is invalid." );
blog.reset( chain_id, lib_num + 1 );
}
const auto hash = calculate_integrity_hash();
ilog( "database initialized with hash: ${hash}", ("hash", hash) );
init(check_shutdown);
ilog( "Finished initialization from snapshot" );
@@ -582,9 +578,6 @@ struct controller_impl {
shutdown();
}
if (conf.prune_config && conf.prune_config->prune_blocks == 0) {
blog.remove();
}
}
void startup(std::function<void()> shutdown, std::function<bool()> check_shutdown, const genesis_state& genesis) {
@@ -618,10 +611,6 @@ struct controller_impl {
blog.reset( genesis, head->block );
}
init(check_shutdown);
if (conf.prune_config && conf.prune_config->prune_blocks == 0) {
blog.remove();
}
}
void startup(std::function<void()> shutdown, std::function<bool()> check_shutdown) {
@@ -652,10 +641,6 @@ struct controller_impl {
head = fork_db.head();
init(check_shutdown);
if (conf.prune_config && conf.prune_config->prune_blocks == 0) {
blog.remove();
}
}
@@ -710,10 +695,6 @@ struct controller_impl {
dm_logger->on_startup(db, head->block_num);
}
if( conf.integrity_hash_on_start )
ilog( "chain database started with hash: ${hash}", ("hash", calculate_integrity_hash()) );
okay_to_print_integrity_hash_on_stop = true;
replay( check_shutdown ); // replay any irreversible and reversible blocks ahead of current head
if( check_shutdown() ) return;
@@ -733,8 +714,7 @@ struct controller_impl {
pending_head = fork_db.pending_head()
) {
wlog( "applying branch from fork database ending with block: ${id}", ("id", pending_head->id) );
controller::block_report br;
maybe_switch_forks( br, pending_head, controller::block_status::complete, forked_branch_callback{}, trx_meta_cache_lookup{} );
maybe_switch_forks( pending_head, controller::block_status::complete, forked_branch_callback{}, trx_meta_cache_lookup{} );
}
}
}
@@ -742,9 +722,6 @@ struct controller_impl {
~controller_impl() {
thread_pool.stop();
pending.reset();
//only log this not just if configured to, but also if initialization made it to the point we'd log the startup too
if(okay_to_print_integrity_hash_on_stop && conf.integrity_hash_on_stop)
ilog( "chain database stopped with hash: ${hash}", ("hash", calculate_integrity_hash()) );
}
void add_indices() {
@@ -1102,22 +1079,18 @@ struct controller_impl {
// The returned scoped_exit should not exceed the lifetime of the pending which existed when make_block_restore_point was called.
fc::scoped_exit<std::function<void()>> make_block_restore_point() {
auto& bb = std::get<building_block>(pending->_block_stage);
auto orig_trx_receipts_size = bb._pending_trx_receipts.size();
auto orig_trx_metas_size = bb._pending_trx_metas.size();
auto orig_trx_receipt_digests_size = std::holds_alternative<digests_t>(bb._trx_mroot_or_receipt_digests) ?
std::get<digests_t>(bb._trx_mroot_or_receipt_digests).size() : 0;
auto orig_block_transactions_size = bb._pending_trx_receipts.size();
auto orig_state_transactions_size = bb._pending_trx_metas.size();
auto orig_action_receipt_digests_size = bb._action_receipt_digests.size();
std::function<void()> callback = [this,
orig_trx_receipts_size,
orig_trx_metas_size,
orig_trx_receipt_digests_size,
orig_action_receipt_digests_size]()
orig_block_transactions_size,
orig_state_transactions_size,
orig_action_receipt_digests_size]()
{
auto& bb = std::get<building_block>(pending->_block_stage);
bb._pending_trx_receipts.resize(orig_trx_receipts_size);
bb._pending_trx_metas.resize(orig_trx_metas_size);
if( std::holds_alternative<digests_t>(bb._trx_mroot_or_receipt_digests) )
std::get<digests_t>(bb._trx_mroot_or_receipt_digests).resize(orig_trx_receipt_digests_size);
bb._pending_trx_receipts.resize(orig_block_transactions_size);
bb._pending_trx_metas.resize(orig_state_transactions_size);
bb._action_receipt_digests.resize(orig_action_receipt_digests_size);
};
@@ -1255,7 +1228,6 @@ struct controller_impl {
uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time = false )
{ try {
auto start = fc::time_point::now();
const bool validating = !self.is_producing_block();
EOS_ASSERT( !validating || explicit_billed_cpu_time, transaction_exception, "validating requires explicit billing" );
@@ -1295,10 +1267,6 @@ struct controller_impl {
trace->scheduled = true;
trace->receipt = push_receipt( gtrx.trx_id, transaction_receipt::expired, billed_cpu_time_us, 0 ); // expire the transaction
trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta );
trace->elapsed = fc::time_point::now() - start;
pending->_block_report.total_cpu_usage_us += billed_cpu_time_us;
pending->_block_report.total_elapsed_time += trace->elapsed;
pending->_block_report.total_time += trace->elapsed;
emit( self.accepted_transaction, trx );
dmlog_applied_transaction(trace);
emit( self.applied_transaction, std::tie(trace, trx->packed_trx()) );
@@ -1329,7 +1297,7 @@ struct controller_impl {
trace->error_code = controller::convert_exception_to_error_code( e );
trace->except = e;
trace->except_ptr = std::current_exception();
trace->elapsed = fc::time_point::now() - start;
trace->elapsed = fc::time_point::now() - trx_context.start;
if (auto dm_logger = get_deep_mind_logger()) {
dm_logger->on_fail_deferred();
@@ -1373,11 +1341,6 @@ struct controller_impl {
restore.cancel();
pending->_block_report.total_net_usage += trace->net_usage;
pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
pending->_block_report.total_elapsed_time += trace->elapsed;
pending->_block_report.total_time += fc::time_point::now() - start;
return trace;
} catch( const disallowed_transaction_extensions_bad_block_exception& ) {
throw;
@@ -1408,18 +1371,13 @@ struct controller_impl {
trace = error_trace;
if( !trace->except_ptr ) {
trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta );
trace->elapsed = fc::time_point::now() - start;
emit( self.accepted_transaction, trx );
dmlog_applied_transaction(trace);
emit( self.applied_transaction, std::tie(trace, trx->packed_trx()) );
undo_session.squash();
pending->_block_report.total_net_usage += trace->net_usage;
if( trace->receipt ) pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
pending->_block_report.total_elapsed_time += trace->elapsed;
pending->_block_report.total_time += trace->elapsed;
return trace;
}
trace->elapsed = fc::time_point::now() - start;
trace->elapsed = fc::time_point::now() - trx_context.start;
}
// Only subjective OR hard failure logic below:
@@ -1466,11 +1424,6 @@ struct controller_impl {
emit( self.applied_transaction, std::tie(trace, trx->packed_trx()) );
}
pending->_block_report.total_net_usage += trace->net_usage;
if( trace->receipt ) pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
pending->_block_report.total_elapsed_time += trace->elapsed;
pending->_block_report.total_time += fc::time_point::now() - start;
return trace;
} FC_CAPTURE_AND_RETHROW() } /// push_scheduled_transaction
@@ -1489,9 +1442,6 @@ struct controller_impl {
r.cpu_usage_us = cpu_usage_us;
r.net_usage_words = net_usage_words;
r.status = status;
auto& bb = std::get<building_block>(pending->_block_stage);
if( std::holds_alternative<digests_t>(bb._trx_mroot_or_receipt_digests) )
std::get<digests_t>(bb._trx_mroot_or_receipt_digests).emplace_back( r.digest() );
return r;
}
@@ -1611,13 +1561,6 @@ struct controller_impl {
trx_context.squash();
}
if( !trx->read_only ) {
pending->_block_report.total_net_usage += trace->net_usage;
pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
pending->_block_report.total_elapsed_time += trace->elapsed;
pending->_block_report.total_time += fc::time_point::now() - start;
}
return trace;
} catch( const disallowed_transaction_extensions_bad_block_exception& ) {
throw;
@@ -1635,14 +1578,9 @@ struct controller_impl {
}
if (!trx->read_only) {
emit(self.accepted_transaction, trx);
dmlog_applied_transaction(trace);
emit(self.applied_transaction, std::tie(trace, trx->packed_trx()));
pending->_block_report.total_net_usage += trace->net_usage;
if( trace->receipt ) pending->_block_report.total_cpu_usage_us += trace->receipt->cpu_usage_us;
pending->_block_report.total_elapsed_time += trace->elapsed;
pending->_block_report.total_time += fc::time_point::now() - start;
emit(self.accepted_transaction, trx);
dmlog_applied_transaction(trace);
emit(self.applied_transaction, std::tie(trace, trx->packed_trx()));
}
return trace;
@@ -1754,7 +1692,7 @@ struct controller_impl {
});
}
const auto& gpo = self.get_global_properties();
const auto& gpo = db.get<global_property_object>();
if( gpo.proposed_schedule_block_num && // if there is a proposed schedule that was proposed in a block ...
( *gpo.proposed_schedule_block_num <= pbhs.dpos_irreversible_blocknum ) && // ... that has now become irreversible ...
@@ -1789,7 +1727,7 @@ struct controller_impl {
});
in_trx_requiring_checks = true;
auto trace = push_transaction( onbtrx, fc::time_point::maximum(), fc::microseconds::maximum(),
gpo.configuration.min_transaction_cpu_usage, true, 0 );
self.get_global_properties().configuration.min_transaction_cpu_usage, true, 0 );
if( trace->except ) {
wlog("onblock ${block_num} is REJECTING: ${entire_trace}",("block_num", head->block_num + 1)("entire_trace", trace));
}
@@ -1825,21 +1763,6 @@ struct controller_impl {
auto& pbhs = pending->get_pending_block_header_state();
auto& bb = std::get<building_block>(pending->_block_stage);
auto action_merkle_fut = async_thread_pool( thread_pool.get_executor(),
[ids{std::move( bb._action_receipt_digests )}]() mutable {
return merkle( std::move( ids ) );
} );
const bool calc_trx_merkle = !std::holds_alternative<checksum256_type>(bb._trx_mroot_or_receipt_digests);
std::future<checksum256_type> trx_merkle_fut;
if( calc_trx_merkle ) {
trx_merkle_fut = async_thread_pool( thread_pool.get_executor(),
[ids{std::move( std::get<digests_t>(bb._trx_mroot_or_receipt_digests) )}]() mutable {
return merkle( std::move( ids ) );
} );
}
// Update resource limits:
resource_limits.process_account_limit_updates();
const auto& chain_config = self.get_global_properties().configuration;
@@ -1850,10 +1773,12 @@ struct controller_impl {
);
resource_limits.process_block_usage(pbhs.block_num);
auto& bb = std::get<building_block>(pending->_block_stage);
// Create (unsigned) block:
auto block_ptr = std::make_shared<signed_block>( pbhs.make_block_header(
calc_trx_merkle ? trx_merkle_fut.get() : std::get<checksum256_type>(bb._trx_mroot_or_receipt_digests),
action_merkle_fut.get(),
bb._transaction_mroot ? *bb._transaction_mroot : calculate_trx_merkle( bb._pending_trx_receipts ),
merkle( std::move( std::get<building_block>(pending->_block_stage)._action_receipt_digests ) ),
bb._new_pending_producer_schedule,
std::move( bb._new_protocol_feature_activations ),
protocol_features.get_protocol_feature_set()
@@ -2013,20 +1938,15 @@ struct controller_impl {
}
void apply_block( controller::block_report& br, const block_state_ptr& bsp, controller::block_status s,
const trx_meta_cache_lookup& trx_lookup )
void apply_block( const block_state_ptr& bsp, controller::block_status s, const trx_meta_cache_lookup& trx_lookup )
{ try {
try {
auto start = fc::time_point::now();
const signed_block_ptr& b = bsp->block;
const auto& new_protocol_feature_activations = bsp->get_new_protocol_feature_activations();
auto producer_block_id = bsp->id;
start_block( b->timestamp, b->confirmed, new_protocol_feature_activations, s, producer_block_id, fc::time_point::maximum() );
// validated in create_block_state_future()
std::get<building_block>(pending->_block_stage)._trx_mroot_or_receipt_digests = b->transaction_mroot;
const bool existing_trxs_metas = !bsp->trxs_metas().empty();
const bool pub_keys_recovered = bsp->is_pub_keys_recovered();
const bool skip_auth_checks = self.skip_auth_check();
@@ -2061,8 +1981,8 @@ struct controller_impl {
transaction_trace_ptr trace;
size_t packed_idx = 0;
const auto& trx_receipts = std::get<building_block>(pending->_block_stage)._pending_trx_receipts;
for( const auto& receipt : b->transactions ) {
const auto& trx_receipts = std::get<building_block>(pending->_block_stage)._pending_trx_receipts;
auto num_pending_receipts = trx_receipts.size();
if( std::holds_alternative<packed_transaction>(receipt.trx) ) {
const auto& trx_meta = ( use_bsp_cached ? bsp->trxs_metas().at( packed_idx )
@@ -2098,6 +2018,9 @@ struct controller_impl {
("lhs", r)("rhs", static_cast<const transaction_receipt_header&>(receipt)) );
}
// validated in create_block_state_future()
std::get<building_block>(pending->_block_stage)._transaction_mroot = b->transaction_mroot;
finalize_block();
auto& ab = std::get<assembled_block>(pending->_block_stage);
@@ -2116,9 +2039,7 @@ struct controller_impl {
// create completed_block with the existing block_state as we just verified it is the same as assembled_block
pending->_block_stage = completed_block{ bsp };
br = pending->_block_report; // copy before commit block destroys pending
commit_block(false);
br.total_time = fc::time_point::now() - start;
return;
} catch ( const std::bad_alloc& ) {
throw;
@@ -2135,44 +2056,64 @@ struct controller_impl {
}
} FC_CAPTURE_AND_RETHROW() } /// apply_block
// thread safe, expected to be called from thread other than the main thread
block_state_ptr create_block_state_i( const block_id_type& id, const signed_block_ptr& b, const block_header_state& prev ) {
auto trx_mroot = calculate_trx_merkle( b->transactions );
EOS_ASSERT( b->transaction_mroot == trx_mroot, block_validate_exception,
"invalid block transaction merkle root ${b} != ${c}", ("b", b->transaction_mroot)("c", trx_mroot) );
const bool skip_validate_signee = false;
auto bsp = std::make_shared<block_state>(
prev,
b,
protocol_features.get_protocol_feature_set(),
[this]( block_timestamp_type timestamp,
const flat_set<digest_type>& cur_features,
const vector<digest_type>& new_features )
{ check_protocol_features( timestamp, cur_features, new_features ); },
skip_validate_signee
);
EOS_ASSERT( id == bsp->id, block_validate_exception,
"provided id ${id} does not match block id ${bid}", ("id", id)("bid", bsp->id) );
return bsp;
}
std::future<block_state_ptr> create_block_state_future( const block_id_type& id, const signed_block_ptr& b ) {
EOS_ASSERT( b, block_validate_exception, "null block" );
return async_thread_pool( thread_pool.get_executor(), [b, id, control=this]() {
// no reason for a block_state if fork_db already knows about block
auto existing = control->fork_db.get_block( id );
EOS_ASSERT( !existing, fork_database_exception, "we already know about this block: ${id}", ("id", id) );
auto prev = control->fork_db.get_block_header( b->previous );
EOS_ASSERT( prev, unlinkable_block_exception,
"unlinkable block ${id}", ("id", id)("previous", b->previous) );
return control->create_block_state_i( id, b, *prev );
} );
}
// thread safe, expected to be called from thread other than the main thread
block_state_ptr create_block_state( const block_id_type& id, const signed_block_ptr& b ) {
EOS_ASSERT( b, block_validate_exception, "null block" );
// no reason for a block_state if fork_db already knows about block
auto existing = fork_db.get_block( id );
EOS_ASSERT( !existing, fork_database_exception, "we already know about this block: ${id}", ("id", id) );
// previous not found could mean that previous block not applied yet
auto prev = fork_db.get_block_header( b->previous );
EOS_ASSERT( prev, unlinkable_block_exception,
"unlinkable block ${id}", ("id", id)("previous", b->previous) );
if( !prev ) return {};
return async_thread_pool( thread_pool.get_executor(), [b, prev, id, control=this]() {
const bool skip_validate_signee = false;
auto trx_mroot = calculate_trx_merkle( b->transactions );
EOS_ASSERT( b->transaction_mroot == trx_mroot, block_validate_exception,
"invalid block transaction merkle root ${b} != ${c}", ("b", b->transaction_mroot)("c", trx_mroot) );
auto bsp = std::make_shared<block_state>(
*prev,
move( b ),
control->protocol_features.get_protocol_feature_set(),
[control]( block_timestamp_type timestamp,
const flat_set<digest_type>& cur_features,
const vector<digest_type>& new_features )
{ control->check_protocol_features( timestamp, cur_features, new_features ); },
skip_validate_signee
);
EOS_ASSERT( id == bsp->id, block_validate_exception,
"provided id ${id} does not match block id ${bid}", ("id", id)("bid", bsp->id) );
return bsp;
} );
return create_block_state_i( id, b, *prev );
}
void push_block( controller::block_report& br,
std::future<block_state_ptr>& block_state_future,
const forked_branch_callback& forked_branch_cb, const trx_meta_cache_lookup& trx_lookup )
void push_block( const block_state_ptr& bsp,
const forked_branch_callback& forked_branch_cb,
const trx_meta_cache_lookup& trx_lookup )
{
controller::block_status s = controller::block_status::complete;
EOS_ASSERT(!pending, block_validate_exception, "it is not valid to push a block when there is a pending block");
@@ -2181,10 +2122,10 @@ struct controller_impl {
trusted_producer_light_validation = old_value;
});
try {
block_state_ptr bsp = block_state_future.get();
EOS_ASSERT( bsp, block_validate_exception, "null block" );
const auto& b = bsp->block;
if( conf.terminate_at_block > 0 && conf.terminate_at_block < self.head_block_num()) {
if( conf.terminate_at_block > 0 && conf.terminate_at_block <= self.head_block_num()) {
ilog("Reached configured maximum block ${num}; terminating", ("num", conf.terminate_at_block) );
shutdown();
return;
@@ -2201,7 +2142,7 @@ struct controller_impl {
emit( self.accepted_block_header, bsp );
if( read_mode != db_read_mode::IRREVERSIBLE ) {
maybe_switch_forks( br, fork_db.pending_head(), s, forked_branch_cb, trx_lookup );
maybe_switch_forks( fork_db.pending_head(), s, forked_branch_cb, trx_lookup );
} else {
log_irreversible();
}
@@ -2219,7 +2160,7 @@ struct controller_impl {
EOS_ASSERT( (s == controller::block_status::irreversible || s == controller::block_status::validated),
block_validate_exception, "invalid block status for replay" );
if( conf.terminate_at_block > 0 && conf.terminate_at_block < self.head_block_num() ) {
if( conf.terminate_at_block > 0 && conf.terminate_at_block <= self.head_block_num() ) {
ilog("Reached configured maximum block ${num}; terminating", ("num", conf.terminate_at_block) );
shutdown();
return;
@@ -2245,9 +2186,8 @@ struct controller_impl {
emit( self.accepted_block_header, bsp );
controller::block_report br;
if( s == controller::block_status::irreversible ) {
apply_block( br, bsp, s, trx_meta_cache_lookup{} );
apply_block( bsp, s, trx_meta_cache_lookup{} );
head = bsp;
// On replay, log_irreversible is not called and so no irreversible_block signal is emitted.
@@ -2261,19 +2201,19 @@ struct controller_impl {
} else {
EOS_ASSERT( read_mode != db_read_mode::IRREVERSIBLE, block_validate_exception,
"invariant failure: cannot replay reversible blocks while in irreversible mode" );
maybe_switch_forks( br, bsp, s, forked_branch_callback{}, trx_meta_cache_lookup{} );
maybe_switch_forks( bsp, s, forked_branch_callback{}, trx_meta_cache_lookup{} );
}
} FC_LOG_AND_RETHROW( )
}
void maybe_switch_forks( controller::block_report& br, const block_state_ptr& new_head, controller::block_status s,
void maybe_switch_forks( const block_state_ptr& new_head, controller::block_status s,
const forked_branch_callback& forked_branch_cb, const trx_meta_cache_lookup& trx_lookup )
{
bool head_changed = true;
if( new_head->header.previous == head->id ) {
try {
apply_block( br, new_head, s, trx_lookup );
apply_block( new_head, s, trx_lookup );
fork_db.mark_valid( new_head );
head = new_head;
} catch ( const std::exception& e ) {
@@ -2304,9 +2244,8 @@ struct controller_impl {
for( auto ritr = branches.first.rbegin(); ritr != branches.first.rend(); ++ritr ) {
auto except = std::exception_ptr{};
try {
br = controller::block_report{};
apply_block( br, *ritr, (*ritr)->is_valid() ? controller::block_status::validated
: controller::block_status::complete, trx_lookup );
apply_block( *ritr, (*ritr)->is_valid() ? controller::block_status::validated
: controller::block_status::complete, trx_lookup );
fork_db.mark_valid( *ritr );
head = *ritr;
} catch ( const std::bad_alloc& ) {
@@ -2337,8 +2276,7 @@ struct controller_impl {
// re-apply good blocks
for( auto ritr = branches.second.rbegin(); ritr != branches.second.rend(); ++ritr ) {
br = controller::block_report{};
apply_block( br, *ritr, controller::block_status::validated /* we previously validated these blocks*/, trx_lookup );
apply_block( *ritr, controller::block_status::validated /* we previously validated these blocks*/, trx_lookup );
head = *ritr;
}
std::rethrow_exception(except);
@@ -2355,8 +2293,8 @@ struct controller_impl {
} /// push_block
deque<transaction_metadata_ptr> abort_block() {
deque<transaction_metadata_ptr> applied_trxs;
vector<transaction_metadata_ptr> abort_block() {
vector<transaction_metadata_ptr> applied_trxs;
if( pending ) {
applied_trxs = pending->extract_trx_metas();
pending.reset();
@@ -2365,8 +2303,9 @@ struct controller_impl {
return applied_trxs;
}
static checksum256_type calculate_trx_merkle( const deque<transaction_receipt>& trxs ) {
deque<digest_type> trx_digests;
static checksum256_type calculate_trx_merkle( const vector<transaction_receipt>& trxs ) {
vector<digest_type> trx_digests;
trx_digests.reserve( trxs.size() );
for( const auto& a : trxs )
trx_digests.emplace_back( a.digest() );
@@ -2857,7 +2796,7 @@ void controller::start_block( block_timestamp_type when,
block_status::incomplete, std::optional<block_id_type>(), deadline );
}
block_state_ptr controller::finalize_block( block_report& br, const signer_callback_type& signer_callback ) {
block_state_ptr controller::finalize_block( const signer_callback_type& signer_callback ) {
validate_db_available_size();
my->finalize_block();
@@ -2878,8 +2817,6 @@ block_state_ptr controller::finalize_block( block_report& br, const signer_callb
my->pending->_block_stage = completed_block{ bsp };
br = my->pending->_block_report;
return bsp;
}
@@ -2888,7 +2825,7 @@ void controller::commit_block() {
my->commit_block(true);
}
deque<transaction_metadata_ptr> controller::abort_block() {
vector<transaction_metadata_ptr> controller::abort_block() {
return my->abort_block();
}
@@ -2900,12 +2837,16 @@ std::future<block_state_ptr> controller::create_block_state_future( const block_
return my->create_block_state_future( id, b );
}
void controller::push_block( controller::block_report& br,
std::future<block_state_ptr>& block_state_future,
const forked_branch_callback& forked_branch_cb, const trx_meta_cache_lookup& trx_lookup )
block_state_ptr controller::create_block_state( const block_id_type& id, const signed_block_ptr& b ) const {
return my->create_block_state( id, b );
}
void controller::push_block( const block_state_ptr& bsp,
const forked_branch_callback& forked_branch_cb,
const trx_meta_cache_lookup& trx_lookup )
{
validate_db_available_size();
my->push_block( br, block_state_future, forked_branch_cb, trx_lookup );
my->push_block( bsp, forked_branch_cb, trx_lookup );
}
transaction_trace_ptr controller::push_transaction( const transaction_metadata_ptr& trx,
@@ -3061,6 +3002,11 @@ std::optional<block_id_type> controller::pending_producer_block_id()const {
return my->pending->_producer_block_id;
}
const vector<transaction_receipt>& controller::get_pending_trx_receipts()const {
EOS_ASSERT( my->pending, block_validate_exception, "no pending block" );
return my->pending->get_trx_receipts();
}
uint32_t controller::last_irreversible_block_num() const {
return my->fork_db.root()->block_num;
}
@@ -3552,7 +3498,11 @@ std::optional<chain_id_type> controller::extract_chain_id_from_db( const path& s
if (gpo==nullptr) return {};
return gpo->chain_id;
} catch (std::system_error &) {} // do not propagate db_error_code::not_found" for absent db, so it will be created
} catch( const std::system_error& e ) {
// do not propagate db_error_code::not_found for absent db, so it will be created
if( e.code().value() != chainbase::db_error_code::not_found )
throw;
}
return {};
}
-1
View File
@@ -42,7 +42,6 @@ namespace eosio::chain {
case deep_mind_handler::operation_qualifier::none: return "";
case deep_mind_handler::operation_qualifier::modify: return "MODIFY_";
case deep_mind_handler::operation_qualifier::push: return "PUSH_";
default: elog("Unknown operation_qualifier"); return "";
}
}
+180 -92
View File
@@ -9,6 +9,7 @@
#include <boost/multi_index/composite_key.hpp>
#include <fc/io/fstream.hpp>
#include <fstream>
#include <shared_mutex>
namespace eosio { namespace chain {
using boost::multi_index_container;
@@ -60,27 +61,44 @@ namespace eosio { namespace chain {
}
struct fork_database_impl {
fork_database_impl( fork_database& self, const fc::path& data_dir )
:self(self)
,datadir(data_dir)
explicit fork_database_impl( const fc::path& data_dir )
:datadir(data_dir)
{}
fork_database& self;
std::shared_mutex mtx;
fork_multi_index_type index;
block_state_ptr root; // Only uses the block_header_state portion
block_state_ptr head;
fc::path datadir;
void add( const block_state_ptr& n,
bool ignore_duplicate, bool validate,
const std::function<void( block_timestamp_type,
const flat_set<digest_type>&,
const vector<digest_type>& )>& validator );
void open_impl( const std::function<void( block_timestamp_type,
const flat_set<digest_type>&,
const vector<digest_type>& )>& validator );
void close_impl();
block_header_state_ptr get_block_header_impl( const block_id_type& id )const;
block_state_ptr get_block_impl( const block_id_type& id )const;
void reset_impl( const block_header_state& root_bhs );
void rollback_head_to_root_impl();
void advance_root_impl( const block_id_type& id );
void remove_impl( const block_id_type& id );
branch_type fetch_branch_impl( const block_id_type& h, uint32_t trim_after_block_num )const;
block_state_ptr search_on_branch_impl( const block_id_type& h, uint32_t block_num )const;
pair<branch_type, branch_type> fetch_branch_from_impl( const block_id_type& first,
const block_id_type& second )const;
void mark_valid_impl( const block_state_ptr& h );
void add_impl( const block_state_ptr& n,
bool ignore_duplicate, bool validate,
const std::function<void( block_timestamp_type,
const flat_set<digest_type>&,
const vector<digest_type>& )>& validator );
};
fork_database::fork_database( const fc::path& data_dir )
:my( new fork_database_impl( *this, data_dir ) )
:my( new fork_database_impl( data_dir ) )
{}
@@ -88,10 +106,18 @@ namespace eosio { namespace chain {
const flat_set<digest_type>&,
const vector<digest_type>& )>& validator )
{
if (!fc::is_directory(my->datadir))
fc::create_directories(my->datadir);
std::lock_guard g( my->mtx );
my->open_impl( validator );
}
auto fork_db_dat = my->datadir / config::forkdb_filename;
void fork_database_impl::open_impl( const std::function<void( block_timestamp_type,
const flat_set<digest_type>&,
const vector<digest_type>& )>& validator )
{
if (!fc::is_directory(datadir))
fc::create_directories(datadir);
auto fork_db_dat = datadir / config::forkdb_filename;
if( fc::exists( fork_db_dat ) ) {
try {
string content;
@@ -102,29 +128,29 @@ namespace eosio { namespace chain {
// validate totem
uint32_t totem = 0;
fc::raw::unpack( ds, totem );
EOS_ASSERT( totem == magic_number, fork_database_exception,
EOS_ASSERT( totem == fork_database::magic_number, fork_database_exception,
"Fork database file '${filename}' has unexpected magic number: ${actual_totem}. Expected ${expected_totem}",
("filename", fork_db_dat.generic_string())
("actual_totem", totem)
("expected_totem", magic_number)
("expected_totem", fork_database::magic_number)
);
// validate version
uint32_t version = 0;
fc::raw::unpack( ds, version );
EOS_ASSERT( version >= min_supported_version && version <= max_supported_version,
EOS_ASSERT( version >= fork_database::min_supported_version && version <= fork_database::max_supported_version,
fork_database_exception,
"Unsupported version of fork database file '${filename}'. "
"Fork database version is ${version} while code supports version(s) [${min},${max}]",
("filename", fork_db_dat.generic_string())
("version", version)
("min", min_supported_version)
("max", max_supported_version)
("min", fork_database::min_supported_version)
("max", fork_database::max_supported_version)
);
block_header_state bhs;
fc::raw::unpack( ds, bhs );
reset( bhs );
reset_impl( bhs );
unsigned_int size; fc::raw::unpack( ds, size );
for( uint32_t i = 0, n = size.value; i < n; ++i ) {
@@ -132,27 +158,27 @@ namespace eosio { namespace chain {
fc::raw::unpack( ds, s );
// do not populate transaction_metadatas, they will be created as needed in apply_block with appropriate key recovery
s.header_exts = s.block->validate_and_extract_header_extensions();
my->add( std::make_shared<block_state>( move( s ) ), false, true, validator );
add_impl( std::make_shared<block_state>( std::move( s ) ), false, true, validator );
}
block_id_type head_id;
fc::raw::unpack( ds, head_id );
if( my->root->id == head_id ) {
my->head = my->root;
if( root->id == head_id ) {
head = root;
} else {
my->head = get_block( head_id );
EOS_ASSERT( my->head, fork_database_exception,
head = get_block_impl( head_id );
EOS_ASSERT( head, fork_database_exception,
"could not find head while reconstructing fork database from file; '${filename}' is likely corrupted",
("filename", fork_db_dat.generic_string()) );
}
auto candidate = my->index.get<by_lib_block_num>().begin();
if( candidate == my->index.get<by_lib_block_num>().end() || !(*candidate)->is_valid() ) {
EOS_ASSERT( my->head->id == my->root->id, fork_database_exception,
auto candidate = index.get<by_lib_block_num>().begin();
if( candidate == index.get<by_lib_block_num>().end() || !(*candidate)->is_valid() ) {
EOS_ASSERT( head->id == root->id, fork_database_exception,
"head not set to root despite no better option available; '${filename}' is likely corrupted",
("filename", fork_db_dat.generic_string()) );
} else {
EOS_ASSERT( !first_preferred( **candidate, *my->head ), fork_database_exception,
EOS_ASSERT( !first_preferred( **candidate, *head ), fork_database_exception,
"head not set to best available option available; '${filename}' is likely corrupted",
("filename", fork_db_dat.generic_string()) );
}
@@ -163,10 +189,15 @@ namespace eosio { namespace chain {
}
void fork_database::close() {
auto fork_db_dat = my->datadir / config::forkdb_filename;
std::lock_guard g( my->mtx );
my->close_impl();
}
if( !my->root ) {
if( my->index.size() > 0 ) {
void fork_database_impl::close_impl() {
auto fork_db_dat = datadir / config::forkdb_filename;
if( !root ) {
if( index.size() > 0 ) {
elog( "fork_database is in a bad state when closing; not writing out '${filename}'",
("filename", fork_db_dat.generic_string()) );
}
@@ -174,13 +205,13 @@ namespace eosio { namespace chain {
}
std::ofstream out( fork_db_dat.generic_string().c_str(), std::ios::out | std::ios::binary | std::ofstream::trunc );
fc::raw::pack( out, magic_number );
fc::raw::pack( out, max_supported_version ); // write out current version which is always max_supported_version
fc::raw::pack( out, *static_cast<block_header_state*>(&*my->root) );
uint32_t num_blocks_in_fork_db = my->index.size();
fc::raw::pack( out, fork_database::magic_number );
fc::raw::pack( out, fork_database::max_supported_version ); // write out current version which is always max_supported_version
fc::raw::pack( out, *static_cast<block_header_state*>(&*root) );
uint32_t num_blocks_in_fork_db = index.size();
fc::raw::pack( out, unsigned_int{num_blocks_in_fork_db} );
const auto& indx = my->index.get<by_lib_block_num>();
const auto& indx = index.get<by_lib_block_num>();
auto unvalidated_itr = indx.rbegin();
auto unvalidated_end = boost::make_reverse_iterator( indx.lower_bound( false ) );
@@ -215,30 +246,40 @@ namespace eosio { namespace chain {
fc::raw::pack( out, *(*itr) );
}
if( my->head ) {
fc::raw::pack( out, my->head->id );
if( head ) {
fc::raw::pack( out, head->id );
} else {
elog( "head not set in fork database; '${filename}' will be corrupted",
("filename", fork_db_dat.generic_string()) );
}
my->index.clear();
index.clear();
}
fork_database::~fork_database() {
close();
my->close_impl();
}
void fork_database::reset( const block_header_state& root_bhs ) {
my->index.clear();
my->root = std::make_shared<block_state>();
static_cast<block_header_state&>(*my->root) = root_bhs;
my->root->validated = true;
my->head = my->root;
std::lock_guard g( my->mtx );
my->reset_impl(root_bhs);
}
void fork_database_impl::reset_impl( const block_header_state& root_bhs ) {
index.clear();
root = std::make_shared<block_state>();
static_cast<block_header_state&>(*root) = root_bhs;
root->validated = true;
head = root;
}
void fork_database::rollback_head_to_root() {
auto& by_id_idx = my->index.get<by_block_id>();
std::lock_guard g( my->mtx );
my->rollback_head_to_root_impl();
}
void fork_database_impl::rollback_head_to_root_impl() {
auto& by_id_idx = index.get<by_block_id>();
auto itr = by_id_idx.begin();
while (itr != by_id_idx.end()) {
by_id_idx.modify( itr, [&]( block_state_ptr& bsp ) {
@@ -246,13 +287,18 @@ namespace eosio { namespace chain {
} );
++itr;
}
my->head = my->root;
head = root;
}
void fork_database::advance_root( const block_id_type& id ) {
EOS_ASSERT( my->root, fork_database_exception, "root not yet set" );
std::lock_guard g( my->mtx );
my->advance_root_impl( id );
}
auto new_root = get_block( id );
void fork_database_impl::advance_root_impl( const block_id_type& id ) {
EOS_ASSERT( root, fork_database_exception, "root not yet set" );
auto new_root = get_block_impl( id );
EOS_ASSERT( new_root, fork_database_exception,
"cannot advance root to a block that does not exist in the fork database" );
EOS_ASSERT( new_root->is_valid(), fork_database_exception,
@@ -262,48 +308,53 @@ namespace eosio { namespace chain {
deque<block_id_type> blocks_to_remove;
for( auto b = new_root; b; ) {
blocks_to_remove.emplace_back( b->header.previous );
b = get_block( blocks_to_remove.back() );
EOS_ASSERT( b || blocks_to_remove.back() == my->root->id, fork_database_exception, "invariant violation: orphaned branch was present in forked database" );
b = get_block_impl( blocks_to_remove.back() );
EOS_ASSERT( b || blocks_to_remove.back() == root->id, fork_database_exception, "invariant violation: orphaned branch was present in forked database" );
}
// The new root block should be erased from the fork database index individually rather than with the remove method,
// because we do not want the blocks branching off of it to be removed from the fork database.
my->index.erase( my->index.find( id ) );
index.erase( index.find( id ) );
// The other blocks to be removed are removed using the remove method so that orphaned branches do not remain in the fork database.
for( const auto& block_id : blocks_to_remove ) {
remove( block_id );
remove_impl( block_id );
}
// Even though fork database no longer needs block or trxs when a block state becomes a root of the tree,
// avoid mutating the block state at all, for example clearing the block shared pointer, because other
// parts of the code which run asynchronously may later expect it remain unmodified.
my->root = new_root;
root = new_root;
}
block_header_state_ptr fork_database::get_block_header( const block_id_type& id )const {
if( my->root->id == id ) {
return my->root;
std::shared_lock g( my->mtx );
return my->get_block_header_impl( id );
}
block_header_state_ptr fork_database_impl::get_block_header_impl( const block_id_type& id )const {
if( root->id == id ) {
return root;
}
auto itr = my->index.find( id );
if( itr != my->index.end() )
auto itr = index.find( id );
if( itr != index.end() )
return *itr;
return block_header_state_ptr();
}
void fork_database_impl::add( const block_state_ptr& n,
bool ignore_duplicate, bool validate,
const std::function<void( block_timestamp_type,
const flat_set<digest_type>&,
const vector<digest_type>& )>& validator )
void fork_database_impl::add_impl( const block_state_ptr& n,
bool ignore_duplicate, bool validate,
const std::function<void( block_timestamp_type,
const flat_set<digest_type>&,
const vector<digest_type>& )>& validator )
{
EOS_ASSERT( root, fork_database_exception, "root not yet set" );
EOS_ASSERT( n, fork_database_exception, "attempt to add null block state" );
auto prev_bh = self.get_block_header( n->header.previous );
auto prev_bh = get_block_header_impl( n->header.previous );
EOS_ASSERT( prev_bh, unlinkable_block_exception,
"unlinkable block", ("id", n->id)("previous", n->header.previous) );
@@ -332,19 +383,27 @@ namespace eosio { namespace chain {
}
void fork_database::add( const block_state_ptr& n, bool ignore_duplicate ) {
my->add( n, ignore_duplicate, false,
[]( block_timestamp_type timestamp,
const flat_set<digest_type>& cur_features,
const vector<digest_type>& new_features )
{}
std::lock_guard g( my->mtx );
my->add_impl( n, ignore_duplicate, false,
[]( block_timestamp_type timestamp,
const flat_set<digest_type>& cur_features,
const vector<digest_type>& new_features )
{}
);
}
const block_state_ptr& fork_database::root()const { return my->root; }
block_state_ptr fork_database::root()const {
std::shared_lock g( my->mtx );
return my->root;
}
const block_state_ptr& fork_database::head()const { return my->head; }
block_state_ptr fork_database::head()const {
std::shared_lock g( my->mtx );
return my->head;
}
block_state_ptr fork_database::pending_head()const {
std::shared_lock g( my->mtx );
const auto& indx = my->index.get<by_lib_block_num>();
auto itr = indx.lower_bound( false );
@@ -357,8 +416,13 @@ namespace eosio { namespace chain {
}
branch_type fork_database::fetch_branch( const block_id_type& h, uint32_t trim_after_block_num )const {
std::shared_lock g( my->mtx );
return my->fetch_branch_impl( h, trim_after_block_num );
}
branch_type fork_database_impl::fetch_branch_impl( const block_id_type& h, uint32_t trim_after_block_num )const {
branch_type result;
for( auto s = get_block(h); s; s = get_block( s->header.previous ) ) {
for( auto s = get_block_impl(h); s; s = get_block_impl( s->header.previous ) ) {
if( s->block_num <= trim_after_block_num )
result.push_back( s );
}
@@ -367,7 +431,12 @@ namespace eosio { namespace chain {
}
block_state_ptr fork_database::search_on_branch( const block_id_type& h, uint32_t block_num )const {
for( auto s = get_block(h); s; s = get_block( s->header.previous ) ) {
std::shared_lock g( my->mtx );
return my->search_on_branch_impl( h, block_num );
}
block_state_ptr fork_database_impl::search_on_branch_impl( const block_id_type& h, uint32_t block_num )const {
for( auto s = get_block_impl(h); s; s = get_block_impl( s->header.previous ) ) {
if( s->block_num == block_num )
return s;
}
@@ -381,9 +450,15 @@ namespace eosio { namespace chain {
*/
pair< branch_type, branch_type > fork_database::fetch_branch_from( const block_id_type& first,
const block_id_type& second )const {
std::shared_lock g( my->mtx );
return my->fetch_branch_from_impl( first, second );
}
pair< branch_type, branch_type > fork_database_impl::fetch_branch_from_impl( const block_id_type& first,
const block_id_type& second )const {
pair<branch_type,branch_type> result;
auto first_branch = (first == my->root->id) ? my->root : get_block(first);
auto second_branch = (second == my->root->id) ? my->root : get_block(second);
auto first_branch = (first == root->id) ? root : get_block_impl(first);
auto second_branch = (second == root->id) ? root : get_block_impl(second);
EOS_ASSERT(first_branch, fork_db_block_not_found, "block ${id} does not exist", ("id", first));
EOS_ASSERT(second_branch, fork_db_block_not_found, "block ${id} does not exist", ("id", second));
@@ -392,7 +467,7 @@ namespace eosio { namespace chain {
{
result.first.push_back(first_branch);
const auto& prev = first_branch->header.previous;
first_branch = (prev == my->root->id) ? my->root : get_block( prev );
first_branch = (prev == root->id) ? root : get_block_impl( prev );
EOS_ASSERT( first_branch, fork_db_block_not_found,
"block ${id} does not exist",
("id", prev)
@@ -403,7 +478,7 @@ namespace eosio { namespace chain {
{
result.second.push_back( second_branch );
const auto& prev = second_branch->header.previous;
second_branch = (prev == my->root->id) ? my->root : get_block( prev );
second_branch = (prev == root->id) ? root : get_block_impl( prev );
EOS_ASSERT( second_branch, fork_db_block_not_found,
"block ${id} does not exist",
("id", prev)
@@ -417,9 +492,9 @@ namespace eosio { namespace chain {
result.first.push_back(first_branch);
result.second.push_back(second_branch);
const auto &first_prev = first_branch->header.previous;
first_branch = get_block( first_prev );
first_branch = get_block_impl( first_prev );
const auto &second_prev = second_branch->header.previous;
second_branch = get_block( second_prev );
second_branch = get_block_impl( second_prev );
EOS_ASSERT( first_branch, fork_db_block_not_found,
"block ${id} does not exist",
("id", first_prev)
@@ -436,13 +511,18 @@ namespace eosio { namespace chain {
result.second.push_back(second_branch);
}
return result;
} /// fetch_branch_from
} /// fetch_branch_from_impl
/// remove all of the invalid forks built off of this id including this id
void fork_database::remove( const block_id_type& id ) {
std::lock_guard g( my->mtx );
return my->remove_impl( id );
}
void fork_database_impl::remove_impl( const block_id_type& id ) {
deque<block_id_type> remove_queue{id};
const auto& previdx = my->index.get<by_prev>();
const auto& head_id = my->head->id;
const auto& previdx = index.get<by_prev>();
const auto& head_id = head->id;
for( uint32_t i = 0; i < remove_queue.size(); ++i ) {
EOS_ASSERT( remove_queue[i] != head_id, fork_database_exception,
@@ -456,16 +536,19 @@ namespace eosio { namespace chain {
}
for( const auto& block_id : remove_queue ) {
auto itr = my->index.find( block_id );
if( itr != my->index.end() )
my->index.erase(itr);
index.erase( block_id );
}
}
void fork_database::mark_valid( const block_state_ptr& h ) {
std::lock_guard g( my->mtx );
my->mark_valid_impl( h );
}
void fork_database_impl::mark_valid_impl( const block_state_ptr& h ) {
if( h->validated ) return;
auto& by_id_idx = my->index.get<by_block_id>();
auto& by_id_idx = index.get<by_block_id>();
auto itr = by_id_idx.find( h->id );
EOS_ASSERT( itr != by_id_idx.end(), fork_database_exception,
@@ -476,15 +559,20 @@ namespace eosio { namespace chain {
bsp->validated = true;
} );
auto candidate = my->index.get<by_lib_block_num>().begin();
if( first_preferred( **candidate, *my->head ) ) {
my->head = *candidate;
auto candidate = index.get<by_lib_block_num>().begin();
if( first_preferred( **candidate, *head ) ) {
head = *candidate;
}
}
block_state_ptr fork_database::get_block(const block_id_type& id)const {
auto itr = my->index.find( id );
if( itr != my->index.end() )
block_state_ptr fork_database::get_block(const block_id_type& id)const {
std::shared_lock g( my->mtx );
return my->get_block_impl(id);
}
block_state_ptr fork_database_impl::get_block_impl(const block_id_type& id)const {
auto itr = index.find( id );
if( itr != index.end() )
return *itr;
return block_state_ptr();
}
@@ -45,7 +45,6 @@ struct abi_serializer {
/// @return string_view of `t` or internal string type
std::string_view resolve_type(const std::string_view& t)const;
bool is_array(const std::string_view& type)const;
bool is_szarray(const std::string_view& type)const;
bool is_optional(const std::string_view& type)const;
bool is_type( const std::string_view& type, const yield_function_t& yield )const;
[[deprecated("use the overload with yield_function_t[=create_yield_function(max_serialization_time)]")]]
@@ -367,23 +366,6 @@ namespace impl {
mvo(name, std::move(array));
}
/**
* template which overloads add for deques of types which contain ABI information in their trees
* for these members we call ::add in order to trigger further processing
*/
template<typename M, typename Resolver, require_abi_t<M> = 1>
static void add( mutable_variant_object &mvo, const char* name, const deque<M>& v, Resolver resolver, abi_traverse_context& ctx )
{
auto h = ctx.enter_scope();
deque<fc::variant> array;
for (const auto& iter: v) {
mutable_variant_object elem_mvo;
add(elem_mvo, "_", iter, resolver, ctx);
array.emplace_back(std::move(elem_mvo["_"]));
}
mvo(name, std::move(array));
}
/**
* template which overloads add for shared_ptr of types which contain ABI information in their trees
* for these members we call ::add in order to trigger further processing
@@ -493,6 +475,7 @@ namespace impl {
binary_to_variant_context _ctx(*abi, ctx, type);
_ctx.short_path = true; // Just to be safe while avoiding the complexity of threading an override boolean all over the place
mvo( "data", abi->_binary_to_variant( type, act.data, _ctx ));
set_hex_data(mvo, "hex_data", act.data);
} catch(...) {
// any failure to serialize data, then leave as not serailzed
set_hex_data(mvo, "data", act.data);
@@ -506,7 +489,6 @@ namespace impl {
} catch(...) {
set_hex_data(mvo, "data", act.data);
}
set_hex_data(mvo, "hex_data", act.data);
out(name, std::move(mvo));
}
@@ -748,24 +730,6 @@ namespace impl {
}
}
/**
* template which overloads extract for deque of types which contain ABI information in their trees
* for these members we call ::extract in order to trigger further processing
*/
template<typename M, typename Resolver, require_abi_t<M> = 1>
static void extract( const fc::variant& v, deque<M>& o, Resolver resolver, abi_traverse_context& ctx )
{
auto h = ctx.enter_scope();
const variants& array = v.get_array();
o.clear();
for( auto itr = array.begin(); itr != array.end(); ++itr ) {
M o_iter;
extract(*itr, o_iter, resolver, ctx);
o.emplace_back(std::move(o_iter));
}
}
/**
* template which overloads extract for shared_ptr of types which contain ABI information in their trees
* for these members we call ::extract in order to trigger further processing
@@ -84,10 +84,6 @@ struct permission_level_weight {
friend bool operator == ( const permission_level_weight& lhs, const permission_level_weight& rhs ) {
return tie( lhs.permission, lhs.weight ) == tie( rhs.permission, rhs.weight );
}
friend bool operator < ( const permission_level_weight& lhs, const permission_level_weight& rhs ) {
return tie( lhs.permission, lhs.weight ) < tie( rhs.permission, rhs.weight );
}
};
struct key_weight {
@@ -97,10 +93,6 @@ struct key_weight {
friend bool operator == ( const key_weight& lhs, const key_weight& rhs ) {
return tie( lhs.key, lhs.weight ) == tie( rhs.key, rhs.weight );
}
friend bool operator < ( const key_weight& lhs, const key_weight& rhs ) {
return tie( lhs.key, lhs.weight ) < tie( rhs.key, rhs.weight );
}
};
@@ -145,10 +137,6 @@ struct wait_weight {
friend bool operator == ( const wait_weight& lhs, const wait_weight& rhs ) {
return tie( lhs.wait_sec, lhs.weight ) == tie( rhs.wait_sec, rhs.weight );
}
friend bool operator < ( const wait_weight& lhs, const wait_weight& rhs ) {
return tie( lhs.wait_sec, lhs.weight ) < tie( rhs.wait_sec, rhs.weight );
}
};
namespace config {
@@ -203,12 +191,6 @@ struct authority {
friend bool operator != ( const authority& lhs, const authority& rhs ) {
return tie( lhs.threshold, lhs.keys, lhs.accounts, lhs.waits ) != tie( rhs.threshold, rhs.keys, rhs.accounts, rhs.waits );
}
void sort_fields () {
std::sort(std::begin(keys), std::end(keys));
std::sort(std::begin(accounts), std::end(accounts));
std::sort(std::begin(waits), std::end(waits));
}
};
@@ -97,7 +97,7 @@ namespace eosio { namespace chain {
signed_block& operator=(signed_block&&) = default;
signed_block clone() const { return *this; }
deque<transaction_receipt> transactions; /// new or generated transactions
vector<transaction_receipt> transactions; /// new or generated transactions
extensions_type block_extensions;
flat_multimap<uint16_t, block_extension> validate_and_extract_extensions()const;
@@ -48,13 +48,10 @@ namespace eosio { namespace chain {
block_log(block_log&& other);
~block_log();
void append(const signed_block_ptr& b, const block_id_type& id);
void append(const signed_block_ptr& b, const block_id_type& id, const std::vector<char>& packed_block);
void append(const signed_block_ptr& b);
void flush();
void reset( const genesis_state& gs, const signed_block_ptr& genesis_block );
void reset( const chain_id_type& chain_id, uint32_t first_block_num );
void remove(); // remove blocks.log and blocks.index
signed_block_ptr read_block(uint64_t file_pos)const;
void read_block_header(block_header& bh, uint64_t file_pos)const;
@@ -94,7 +91,7 @@ namespace eosio { namespace chain {
static bool is_pruned_log(const fc::path& data_dir);
static bool extract_block_range(const fc::path& block_dir, const fc::path&output_dir, block_num_type& start, block_num_type& end, bool rename_input=false);
static bool trim_blocklog_front(const fc::path& block_dir, const fc::path& temp_dir, uint32_t truncate_at_block);
private:
void open(const fc::path& data_dir);
@@ -122,7 +119,6 @@ namespace eosio { namespace chain {
FILE* ind_in = nullptr; //C style files for reading blocks.log and blocks.index
//we use low level file IO because it is distinctly faster than C++ filebuf or iostream
uint64_t first_block_pos = 0; //file position in blocks.log for the first block in the log
genesis_state gs;
chain_id_type chain_id;
static constexpr int blknum_offset{14}; //offset from start of block to 4 byte block number, valid for the only allowed versions
@@ -19,7 +19,7 @@ namespace eosio { namespace chain {
block_state( pending_block_header_state&& cur,
signed_block_ptr&& b, // unsigned block
deque<transaction_metadata_ptr>&& trx_metas,
vector<transaction_metadata_ptr>&& trx_metas,
const protocol_feature_set& pfs,
const std::function<void( block_timestamp_type,
const flat_set<digest_type>&,
@@ -44,24 +44,24 @@ namespace eosio { namespace chain {
bool is_valid()const { return validated; }
bool is_pub_keys_recovered()const { return _pub_keys_recovered; }
deque<transaction_metadata_ptr> extract_trxs_metas() {
vector<transaction_metadata_ptr> extract_trxs_metas() {
_pub_keys_recovered = false;
auto result = std::move( _cached_trxs );
_cached_trxs.clear();
return result;
}
void set_trxs_metas( deque<transaction_metadata_ptr>&& trxs_metas, bool keys_recovered ) {
void set_trxs_metas( vector<transaction_metadata_ptr>&& trxs_metas, bool keys_recovered ) {
_pub_keys_recovered = keys_recovered;
_cached_trxs = std::move( trxs_metas );
}
const deque<transaction_metadata_ptr>& trxs_metas()const { return _cached_trxs; }
const vector<transaction_metadata_ptr>& trxs_metas()const { return _cached_trxs; }
bool validated = false;
bool _pub_keys_recovered = false;
/// this data is redundant with the data stored in block, but facilitates
/// recapturing transactions when we pop a block
deque<transaction_metadata_ptr> _cached_trxs;
vector<transaction_metadata_ptr> _cached_trxs;
};
using block_state_ptr = std::shared_ptr<block_state>;
@@ -84,9 +84,7 @@ namespace eosio { namespace chain {
bool allow_ram_billing_in_notify = false;
uint32_t maximum_variable_signature_length = chain::config::default_max_variable_signature_length;
bool disable_all_subjective_mitigations = false; //< for developer & testing purposes, can be configured using `disable-all-subjective-mitigations` when `EOSIO_DEVELOPER` build option is provided
uint32_t terminate_at_block = 0; //< primarily for testing purposes
bool integrity_hash_on_start= false;
bool integrity_hash_on_stop = false;
uint32_t terminate_at_block = 0;
wasm_interface::vm_type wasm_runtime = chain::config::default_wasm_runtime;
eosvmoc::config eosvmoc_config;
@@ -146,7 +144,7 @@ namespace eosio { namespace chain {
/**
* @return transactions applied in aborted block
*/
deque<transaction_metadata_ptr> abort_block();
vector<transaction_metadata_ptr> abort_block();
/**
*
@@ -164,27 +162,21 @@ namespace eosio { namespace chain {
fc::time_point block_deadline, fc::microseconds max_transaction_time,
uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time );
struct block_report {
size_t total_net_usage = 0;
size_t total_cpu_usage_us = 0;
fc::microseconds total_elapsed_time{};
fc::microseconds total_time{};
};
block_state_ptr finalize_block( block_report& br, const signer_callback_type& signer_callback );
block_state_ptr finalize_block( const signer_callback_type& signer_callback );
void sign_block( const signer_callback_type& signer_callback );
void commit_block();
// thread-safe
std::future<block_state_ptr> create_block_state_future( const block_id_type& id, const signed_block_ptr& b );
// thread-safe
block_state_ptr create_block_state( const block_id_type& id, const signed_block_ptr& b ) const;
/**
* @param br returns statistics for block
* @param block_state_future provide from call to create_block_state_future
* @param bsp block to push
* @param cb calls cb with forked applied transactions for each forked block
* @param trx_lookup user provided lookup function for externally cached transaction_metadata
*/
void push_block( block_report& br,
std::future<block_state_ptr>& block_state_future,
void push_block( const block_state_ptr& bsp,
const forked_branch_callback& cb,
const trx_meta_cache_lookup& trx_lookup );
@@ -241,6 +233,8 @@ namespace eosio { namespace chain {
std::optional<block_id_type> pending_producer_block_id()const;
uint32_t pending_block_num()const;
const vector<transaction_receipt>& get_pending_trx_receipts()const;
const producer_authority_schedule& active_producers()const;
const producer_authority_schedule& pending_producers()const;
std::optional<producer_authority_schedule> proposed_producers()const;
@@ -253,6 +247,7 @@ namespace eosio { namespace chain {
signed_block_ptr fetch_block_by_id( block_id_type id )const;
block_state_ptr fetch_block_state_by_number( uint32_t block_num )const;
// return block_state from forkdb, thread-safe
block_state_ptr fetch_block_state_by_id( block_id_type id )const;
block_id_type get_block_id_for_num( uint32_t block_num )const;
@@ -186,6 +186,17 @@ namespace fc {
b = eosio::chain::shared_blob(_s.begin(), _s.end(), b.get_allocator());
}
inline
void to_variant( const blob& b, variant& v ) {
v = variant(base64_encode(b.data.data(), b.data.size()));
}
inline
void from_variant( const variant& v, blob& b ) {
string _s = base64_decode(v.as_string());
b.data = std::vector<char>(_s.begin(), _s.end());
}
template<typename T>
void to_variant( const eosio::chain::shared_vector<T>& sv, variant& v ) {
to_variant(std::vector<T>(sv.begin(), sv.end()), v);
@@ -16,6 +16,8 @@ namespace eosio { namespace chain {
* database tracks the longest chain and the last irreversible block number. All
* blocks older than the last irreversible block are freed after emitting the
* irreversible signal.
*
* An internal mutex is used to provide thread-safety.
*/
class fork_database {
public:
@@ -55,9 +57,9 @@ namespace eosio { namespace chain {
void remove( const block_id_type& id );
const block_state_ptr& root()const;
const block_state_ptr& head()const;
block_state_ptr pending_head()const;
block_state_ptr root()const;
block_state_ptr head()const;
block_state_ptr pending_head()const;
/**
* Returns the sequence of block states resulting from trimming the branch from the
@@ -6,14 +6,11 @@
namespace eosio { namespace chain {
/**
* @brief limits for a kv database: NOT IN USE for mandel
* @brief limits for a kv database.
*
* Each database (ram or disk, currently) has its own limits for these parameters.
* The key and value limits apply when adding or modifying elements. They may be reduced
* below existing database entries.
*
* This has been marked for removal at a later date, when v7 snapshots are deemed necessary.
* kv_database_config will be removed as part of that effort.
*/
struct kv_database_config {
std::uint32_t max_key_size = 0; ///< the maximum size in bytes of a key
@@ -17,6 +17,6 @@ namespace eosio { namespace chain {
/**
* Calculates the merkle root of a set of digests, if ids is odd it will duplicate the last id.
*/
digest_type merkle( deque<digest_type> ids );
digest_type merkle( vector<digest_type> ids );
} } /// eosio::chain
@@ -4,7 +4,6 @@
#include <eosio/chain/config.hpp>
#include <eosio/chain/trace.hpp>
#include <eosio/chain/snapshot.hpp>
#include <eosio/chain/block_timestamp.hpp>
#include <chainbase/chainbase.hpp>
#include <set>
@@ -57,8 +56,6 @@ namespace eosio { namespace chain {
int64_t used = 0; ///< quantity used in current window
int64_t available = 0; ///< quantity available in current window (based upon fractional reserve)
int64_t max = 0; ///< max per window under current congestion
block_timestamp_type last_usage_update_time; ///< last usage timestamp
int64_t current_used = 0; ///< current usage according to the given timestamp
};
class resource_limits_manager {
@@ -105,10 +102,8 @@ namespace eosio { namespace chain {
std::pair<int64_t, bool> get_account_cpu_limit( const account_name& name, uint32_t greylist_limit = config::maximum_elastic_resource_multiplier ) const;
std::pair<int64_t, bool> get_account_net_limit( const account_name& name, uint32_t greylist_limit = config::maximum_elastic_resource_multiplier ) const;
std::pair<account_resource_limit, bool>
get_account_cpu_limit_ex( const account_name& name, uint32_t greylist_limit = config::maximum_elastic_resource_multiplier, const std::optional<block_timestamp_type>& current_time={} ) const;
std::pair<account_resource_limit, bool>
get_account_net_limit_ex( const account_name& name, uint32_t greylist_limit = config::maximum_elastic_resource_multiplier, const std::optional<block_timestamp_type>& current_time={} ) const;
std::pair<account_resource_limit, bool> get_account_cpu_limit_ex( const account_name& name, uint32_t greylist_limit = config::maximum_elastic_resource_multiplier ) const;
std::pair<account_resource_limit, bool> get_account_net_limit_ex( const account_name& name, uint32_t greylist_limit = config::maximum_elastic_resource_multiplier ) const;
int64_t get_account_ram_usage( const account_name& name ) const;
@@ -118,6 +113,6 @@ namespace eosio { namespace chain {
};
} } } /// eosio::chain
FC_REFLECT( eosio::chain::resource_limits::account_resource_limit, (used)(available)(max)(last_usage_update_time)(current_used) )
FC_REFLECT( eosio::chain::resource_limits::account_resource_limit, (used)(available)(max) )
FC_REFLECT( eosio::chain::resource_limits::ratio, (numerator)(denominator))
FC_REFLECT( eosio::chain::resource_limits::elastic_limit_parameters, (target)(max)(periods)(max_multiplier)(contract_rate)(expand_rate))
@@ -5,7 +5,6 @@
#include <fc/variant_object.hpp>
#include <boost/core/demangle.hpp>
#include <ostream>
#include <memory>
namespace eosio { namespace chain {
/**
@@ -273,6 +272,11 @@ namespace eosio { namespace chain {
read_section(detail::snapshot_section_traits<T>::section_name(), f);
}
template<typename T>
bool has_section(const std::string& suffix = std::string()) {
return has_section(suffix + detail::snapshot_section_traits<T>::section_name());
}
virtual void validate() const = 0;
virtual void return_to_header() = 0;
@@ -280,6 +284,7 @@ namespace eosio { namespace chain {
virtual ~snapshot_reader(){};
protected:
virtual bool has_section( const std::string& section_name ) = 0;
virtual void set_section( const std::string& section_name ) = 0;
virtual bool read_row( detail::abstract_snapshot_row_reader& row_reader ) = 0;
virtual bool empty( ) = 0;
@@ -308,6 +313,7 @@ namespace eosio { namespace chain {
explicit variant_snapshot_reader(const fc::variant& snapshot);
void validate() const override;
bool has_section( const string& section_name ) override;
void set_section( const string& section_name ) override;
bool read_row( detail::abstract_snapshot_row_reader& row_reader ) override;
bool empty ( ) override;
@@ -336,22 +342,7 @@ namespace eosio { namespace chain {
std::streampos header_pos;
std::streampos section_pos;
uint64_t row_count;
};
class ostream_json_snapshot_writer : public snapshot_writer {
public:
explicit ostream_json_snapshot_writer(std::ostream& snapshot);
void write_start_section( const std::string& section_name ) override;
void write_row( const detail::abstract_snapshot_row_writer& row_writer ) override;
void write_end_section() override;
void finalize();
static const uint32_t magic_number = 0x30510550;
private:
detail::ostream_wrapper snapshot;
uint64_t row_count;
};
class istream_snapshot_reader : public snapshot_reader {
@@ -359,6 +350,7 @@ namespace eosio { namespace chain {
explicit istream_snapshot_reader(std::istream& snapshot);
void validate() const override;
bool has_section( const string& section_name ) override;
void set_section( const string& section_name ) override;
bool read_row( detail::abstract_snapshot_row_reader& row_reader ) override;
bool empty ( ) override;
@@ -374,24 +366,6 @@ namespace eosio { namespace chain {
uint64_t cur_row;
};
class istream_json_snapshot_reader : public snapshot_reader {
public:
explicit istream_json_snapshot_reader(const fc::path& p);
~istream_json_snapshot_reader();
void validate() const override;
void set_section( const string& section_name ) override;
bool read_row( detail::abstract_snapshot_row_reader& row_reader ) override;
bool empty ( ) override;
void clear_section() override;
void return_to_header() override;
private:
bool validate_section() const;
std::unique_ptr<struct istream_json_snapshot_reader_impl> impl;
};
class integrity_hash_snapshot_writer : public snapshot_writer {
public:
explicit integrity_hash_snapshot_writer(fc::sha256::encoder& enc);
@@ -165,25 +165,6 @@ namespace eosio {
return lhs.value() > rhs.value();
}
inline bool operator== (const extended_symbol& lhs, const extended_symbol& rhs)
{
return std::tie(lhs.sym, lhs.contract) == std::tie(rhs.sym, rhs.contract);
}
inline bool operator!= (const extended_symbol& lhs, const extended_symbol& rhs)
{
return std::tie(lhs.sym, lhs.contract) != std::tie(rhs.sym, rhs.contract);
}
inline bool operator< (const extended_symbol& lhs, const extended_symbol& rhs)
{
return std::tie(lhs.sym, lhs.contract) < std::tie(rhs.sym, rhs.contract);
}
inline bool operator> (const extended_symbol& lhs, const extended_symbol& rhs)
{
return std::tie(lhs.sym, lhs.contract) > std::tie(rhs.sym, rhs.contract);
}
} // namespace chain
} // namespace eosio
@@ -49,6 +49,12 @@ namespace eosio { namespace chain {
* with a block_header::timestamp greater than expiration is
* deemed irreversible, then a user can safely trust the transaction
* will never be included.
*
* Each region is an independent blockchain, it is included as routing
* information for inter-blockchain communication. A contract in this
* region might generate or authorize a transaction intended for a foreign
* region.
*/
struct transaction_header {
time_point_sec expiration; ///< the time at which a transaction expires
@@ -70,7 +76,7 @@ namespace eosio { namespace chain {
};
/**
* A transaction consists of a set of messages which must all be applied or
* A transaction consits of a set of messages which must all be applied or
* all are rejected. These messages have access to data within the given
* read and write scopes.
*/
@@ -110,9 +110,9 @@ namespace eosio { namespace chain {
void schedule_transaction();
void record_transaction( const transaction_id_type& id, fc::time_point_sec expire );
void validate_cpu_usage_to_bill( int64_t billed_us, int64_t account_cpu_limit, bool check_minimum, int64_t subjective_billed_us )const;
void validate_account_cpu_usage( int64_t billed_us, int64_t account_cpu_limit, int64_t subjective_billed_us )const;
void validate_account_cpu_usage_estimate( int64_t billed_us, int64_t account_cpu_limit, int64_t subjective_billed_us )const;
void validate_cpu_usage_to_bill( int64_t billed_us, int64_t account_cpu_limit, bool check_minimum )const;
void validate_account_cpu_usage( int64_t billed_us, int64_t account_cpu_limit )const;
void validate_account_cpu_usage_estimate( int64_t billed_us, int64_t account_cpu_limit )const;
void disallow_transaction_extensions( const char* error_msg )const;
@@ -128,7 +128,7 @@ namespace eosio { namespace chain {
fc::time_point published;
deque<digest_type> executed_action_receipt_digests;
vector<digest_type> executed_action_receipt_digests;
flat_set<account_name> bill_to_accounts;
flat_set<account_name> validate_ram_usage;
+2 -13
View File
@@ -17,9 +17,6 @@
#include <fc/fixed_string.hpp>
#include <fc/crypto/private_key.hpp>
#include <boost/version.hpp>
#include <boost/container/deque.hpp>
#include <memory>
#include <vector>
#include <deque>
@@ -48,6 +45,7 @@ namespace eosio { namespace chain {
using std::vector;
using std::unordered_map;
using std::string;
using std::deque;
using std::shared_ptr;
using std::weak_ptr;
using std::unique_ptr;
@@ -78,15 +76,7 @@ namespace eosio { namespace chain {
using public_key_type = fc::crypto::public_key;
using private_key_type = fc::crypto::private_key;
using signature_type = fc::crypto::signature;
#if BOOST_VERSION >= 107100
// configurable boost deque performs much better than std::deque in our use cases
using block_1024_option_t = boost::container::deque_options< boost::container::block_size<1024u> >::type;
template<typename T>
using deque = boost::container::deque< T, void, block_1024_option_t >;
#else
template<typename T>
using deque = std::deque<T>;
#endif
struct void_t{};
using chainbase::allocator;
@@ -251,7 +241,6 @@ namespace eosio { namespace chain {
using int128_t = __int128;
using uint128_t = unsigned __int128;
using bytes = vector<char>;
using digests_t = deque<digest_type>;
struct sha256_less {
bool operator()( const fc::sha256& lhs, const fc::sha256& rhs ) const {
@@ -32,12 +32,12 @@ using next_func_t = std::function<void(const std::variant<fc::exception_ptr, tra
struct unapplied_transaction {
const transaction_metadata_ptr trx_meta;
const fc::time_point expiry;
trx_enum_type trx_type = trx_enum_type::unknown;
bool return_failure_trace = false;
next_func_t next;
const transaction_id_type& id()const { return trx_meta->id(); }
fc::time_point_sec expiration()const { return trx_meta->packed_trx()->expiration(); }
unapplied_transaction(const unapplied_transaction&) = delete;
unapplied_transaction() = delete;
@@ -61,7 +61,7 @@ private:
const_mem_fun<unapplied_transaction, const transaction_id_type&, &unapplied_transaction::id>
>,
ordered_non_unique< tag<by_type>, member<unapplied_transaction, trx_enum_type, &unapplied_transaction::trx_type> >,
ordered_non_unique< tag<by_expiry>, const_mem_fun<unapplied_transaction, fc::time_point_sec, &unapplied_transaction::expiration> >
ordered_non_unique< tag<by_expiry>, member<unapplied_transaction, const fc::time_point, &unapplied_transaction::expiry> >
>
> unapplied_trx_queue_type;
@@ -96,15 +96,15 @@ public:
return itr->trx_meta;
}
template <typename Func>
bool clear_expired( const time_point& pending_block_time, const time_point& deadline, Func&& callback ) {
template <typename Yield, typename Callback>
bool clear_expired( const time_point& pending_block_time, Yield&& yield, Callback&& callback ) {
auto& persisted_by_expiry = queue.get<by_expiry>();
while( !persisted_by_expiry.empty() ) {
const auto& itr = persisted_by_expiry.begin();
if( itr->expiration() > pending_block_time ) {
if( itr->expiry > pending_block_time ) {
break;
}
if( deadline <= fc::time_point::now() ) {
if( yield() ) {
return false;
}
callback( itr->trx_meta->packed_trx(), itr->trx_type );
@@ -146,15 +146,17 @@ public:
const block_state_ptr& bsptr = *ritr;
for( auto itr = bsptr->trxs_metas().begin(), end = bsptr->trxs_metas().end(); itr != end; ++itr ) {
const auto& trx = *itr;
auto insert_itr = queue.insert( { trx, trx_enum_type::forked } );
fc::time_point expiry = trx->packed_trx()->expiration();
auto insert_itr = queue.insert( { trx, expiry, trx_enum_type::forked } );
if( insert_itr.second ) added( insert_itr.first );
}
}
}
void add_aborted( deque<transaction_metadata_ptr> aborted_trxs ) {
void add_aborted( std::vector<transaction_metadata_ptr> aborted_trxs ) {
for( auto& trx : aborted_trxs ) {
auto insert_itr = queue.insert( { std::move( trx ), trx_enum_type::aborted } );
fc::time_point expiry = trx->packed_trx()->expiration();
auto insert_itr = queue.insert( { std::move( trx ), expiry, trx_enum_type::aborted } );
if( insert_itr.second ) added( insert_itr.first );
}
}
@@ -162,14 +164,14 @@ public:
void add_persisted( const transaction_metadata_ptr& trx ) {
auto itr = queue.get<by_trx_id>().find( trx->id() );
if( itr == queue.get<by_trx_id>().end() ) {
auto insert_itr = queue.insert( { trx, trx_enum_type::persisted } );
fc::time_point expiry = trx->packed_trx()->expiration();
auto insert_itr = queue.insert( { trx, expiry, trx_enum_type::persisted } );
if( insert_itr.second ) added( insert_itr.first );
} else if( itr->trx_type != trx_enum_type::persisted ) {
if (itr->trx_type == trx_enum_type::incoming || itr->trx_type == trx_enum_type::incoming_persisted)
--incoming_count;
queue.get<by_trx_id>().modify( itr, [](auto& un){
un.trx_type = trx_enum_type::persisted;
un.next = nullptr; // persisted already have ack'ed initial trace
} );
}
}
@@ -177,8 +179,9 @@ public:
void add_incoming( const transaction_metadata_ptr& trx, bool persist_until_expired, bool return_failure_trace, next_func_t next ) {
auto itr = queue.get<by_trx_id>().find( trx->id() );
if( itr == queue.get<by_trx_id>().end() ) {
fc::time_point expiry = trx->packed_trx()->expiration();
auto insert_itr = queue.insert(
{ trx, persist_until_expired ? trx_enum_type::incoming_persisted : trx_enum_type::incoming, return_failure_trace, std::move( next ) } );
{ trx, expiry, persist_until_expired ? trx_enum_type::incoming_persisted : trx_enum_type::incoming, return_failure_trace, std::move( next ) } );
if( insert_itr.second ) added( insert_itr.first );
} else {
if( itr->trx_meta == trx ) return; // same trx meta pointer
@@ -204,12 +207,6 @@ public:
iterator incoming_begin() { return queue.get<by_type>().lower_bound( trx_enum_type::incoming_persisted ); }
iterator incoming_end() { return queue.get<by_type>().end(); } // if changed to upper_bound, verify usage performance
iterator lower_bound( const transaction_id_type& id ) {
auto itr = queue.get<by_trx_id>().find( id );
if( itr == queue.get<by_trx_id>().end() ) return queue.get<by_type>().end();
return queue.project<by_type>(itr);
}
/// caller's responsibility to call next() if applicable
iterator erase( iterator itr ) {
removed( itr );
@@ -50,9 +50,7 @@ class memory {
// The maximum amount of data that PIC code can include in the prologue
static constexpr uintptr_t max_prologue_size = mutable_global_size + table_size;
// Changed from -cb_offset == EOS_VM_OC_CONTROL_BLOCK_OFFSET to get around
// of compile warning about comparing integers of different signedness
static_assert(EOS_VM_OC_CONTROL_BLOCK_OFFSET + cb_offset == 0, "EOS VM OC control block offset has slid out of place somehow");
static_assert(-cb_offset == EOS_VM_OC_CONTROL_BLOCK_OFFSET, "EOS VM OC control block offset has slid out of place somehow");
static_assert(stride == EOS_VM_OC_MEMORY_STRIDE, "EOS VM OC memory stride has slid out of place somehow");
private:
@@ -844,7 +844,7 @@ namespace webassembly {
/**
* Find the table row in a primary 64-bit integer index table that matches the lowerbound condition for a given primary key.
* Lowerbound record is the first nearest record which primary key is >= the given key.
* Lowerbound record is the first nearest record which primary key is <= the given key.
*
* @ingroup database primary-index
* @param code - the name of the owner of the table.
@@ -954,7 +954,7 @@ namespace webassembly {
/**
* Find the table row in a secondary 64-bit integer index table that matches the lowerbound condition for a given secondary key.
* Lowerbound secondary index is the first secondary index which key is >= the given secondary index key.
* Lowerbound secondary index is the first secondary index which key is <= the given secondary index key.
*
* @ingroup database uint64_t-secondary-index
* @param code - the name of the owner of the table.
@@ -1095,7 +1095,7 @@ namespace webassembly {
/**
* Find the table row in a secondary 128-bit integer index table that matches the lowerbound condition for a given secondary key.
* Lowerbound secondary index is the first secondary index which key is >= the given secondary index key.
* Lowerbound secondary index is the first secondary index which key is <= the given secondary index key.
*
* @ingroup database uint128_t-secondary-index
* @param code - the name of the owner of the table.
@@ -1236,7 +1236,7 @@ namespace webassembly {
/**
* Find the table row in a secondary 256-bit integer index table that matches the lowerbound condition for a given secondary key.
* Lowerbound secondary index is the first secondary index which key is >= the given secondary index key.
* Lowerbound secondary index is the first secondary index which key is <= the given secondary index key.
*
* @ingroup database 256-bit-secondary-index
* @param code - the name of the owner of the table.
@@ -1380,7 +1380,7 @@ namespace webassembly {
/**
* Find the table row in a secondary double-precision floating-point index table that matches the lowerbound condition for a given secondary key.
* Lowerbound secondary index is the first secondary index which key is >= the given secondary index key.
* Lowerbound secondary index is the first secondary index which key is <= the given secondary index key.
*
* @ingroup database double-secondary-index
* @param code - the name of the owner of the table.
@@ -1524,7 +1524,7 @@ namespace webassembly {
/**
* Find the table row in a secondary quadruple-precision floating-point index table that matches the lowerbound condition for a given secondary key.
* Lowerbound secondary index is the first secondary index which key is >= the given secondary index key.
* Lowerbound secondary index is the first secondary index which key is <= the given secondary index key.
*
* @ingroup database long-double-secondary-index
* @param code - the name of the owner of the table.
+1 -1
View File
@@ -32,7 +32,7 @@ bool is_canonical_right(const digest_type& val) {
}
digest_type merkle(deque<digest_type> ids) {
digest_type merkle(vector<digest_type> ids) {
if( 0 == ids.size() ) { return digest_type(); }
while( ids.size() > 1 ) {
@@ -28,7 +28,6 @@ platform_timer::platform_timer() {
if(refcount++ == 0) {
std::promise<void> p;
auto f = p.get_future();
checktime_thread = std::thread([&p]() {
fc::set_os_thread_name("checktime");
checktime_ios = std::make_unique<boost::asio::io_service>();
@@ -37,7 +36,7 @@ platform_timer::platform_timer() {
checktime_ios->run();
});
f.get();
p.get_future().get();
}
my->timer = std::make_unique<boost::asio::high_resolution_timer>(*checktime_ios);
@@ -65,12 +64,11 @@ void platform_timer::start(fc::time_point tp) {
else {
#if 0
std::promise<void> p;
auto f = p.get_future();
checktime_ios->post([&p,this]() {
expired = 0;
p.set_value();
});
f.get();
p.get_future().get();
#endif
expired = 0;
my->timer->expires_after(std::chrono::microseconds(x.count()));
+4 -24
View File
@@ -418,8 +418,7 @@ std::pair<int64_t, bool> resource_limits_manager::get_account_cpu_limit( const a
return {arl.available, greylisted};
}
std::pair<account_resource_limit, bool>
resource_limits_manager::get_account_cpu_limit_ex( const account_name& name, uint32_t greylist_limit, const std::optional<block_timestamp_type>& current_time) const {
std::pair<account_resource_limit, bool> resource_limits_manager::get_account_cpu_limit_ex( const account_name& name, uint32_t greylist_limit ) const {
const auto& state = _db.get<resource_limits_state_object>();
const auto& usage = _db.get<resource_usage_object, by_owner>(name);
@@ -429,7 +428,7 @@ resource_limits_manager::get_account_cpu_limit_ex( const account_name& name, uin
get_account_limits( name, x, y, cpu_weight );
if( cpu_weight < 0 || state.total_cpu_weight == 0 ) {
return {{ -1, -1, -1, block_timestamp_type(usage.cpu_usage.last_ordinal), -1 }, false};
return {{ -1, -1, -1 }, false};
}
account_resource_limit arl;
@@ -463,15 +462,6 @@ resource_limits_manager::get_account_cpu_limit_ex( const account_name& name, uin
arl.used = impl::downgrade_cast<int64_t>(cpu_used_in_window);
arl.max = impl::downgrade_cast<int64_t>(max_user_use_in_window);
arl.last_usage_update_time = block_timestamp_type(usage.cpu_usage.last_ordinal);
arl.current_used = arl.used;
if ( current_time ) {
if (current_time->slot > usage.cpu_usage.last_ordinal) {
auto history_usage = usage.cpu_usage;
history_usage.add(0, current_time->slot, window_size);
arl.current_used = impl::downgrade_cast<int64_t>(impl::integer_divide_ceil((uint128_t)history_usage.value_ex * window_size, (uint128_t)config::rate_limiting_precision));
}
}
return {arl, greylisted};
}
@@ -480,8 +470,7 @@ std::pair<int64_t, bool> resource_limits_manager::get_account_net_limit( const a
return {arl.available, greylisted};
}
std::pair<account_resource_limit, bool>
resource_limits_manager::get_account_net_limit_ex( const account_name& name, uint32_t greylist_limit, const std::optional<block_timestamp_type>& current_time) const {
std::pair<account_resource_limit, bool> resource_limits_manager::get_account_net_limit_ex( const account_name& name, uint32_t greylist_limit ) const {
const auto& config = _db.get<resource_limits_config_object>();
const auto& state = _db.get<resource_limits_state_object>();
const auto& usage = _db.get<resource_usage_object, by_owner>(name);
@@ -490,7 +479,7 @@ resource_limits_manager::get_account_net_limit_ex( const account_name& name, uin
get_account_limits( name, x, net_weight, y );
if( net_weight < 0 || state.total_net_weight == 0) {
return {{ -1, -1, -1, block_timestamp_type(usage.net_usage.last_ordinal), -1 }, false};
return {{ -1, -1, -1 }, false};
}
account_resource_limit arl;
@@ -524,15 +513,6 @@ resource_limits_manager::get_account_net_limit_ex( const account_name& name, uin
arl.used = impl::downgrade_cast<int64_t>(net_used_in_window);
arl.max = impl::downgrade_cast<int64_t>(max_user_use_in_window);
arl.last_usage_update_time = block_timestamp_type(usage.net_usage.last_ordinal);
arl.current_used = arl.used;
if ( current_time ) {
if (current_time->slot > usage.net_usage.last_ordinal) {
auto history_usage = usage.net_usage;
history_usage.add(0, current_time->slot, window_size);
arl.current_used = impl::downgrade_cast<int64_t>(impl::integer_divide_ceil((uint128_t)history_usage.value_ex * window_size, (uint128_t)config::rate_limiting_precision));
}
}
return {arl, greylisted};
}
+49 -134
View File
@@ -1,16 +1,6 @@
#define RAPIDJSON_NAMESPACE eosio_rapidjson // This is ABSOLUTELY necessary anywhere that is using eosio_rapidjson
#include <eosio/chain/snapshot.hpp>
#include <eosio/chain/exceptions.hpp>
#include <fc/scoped_exit.hpp>
#include <fc/io/json.hpp>
#include <rapidjson/document.h>
#include <rapidjson/filereadstream.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
using namespace eosio_rapidjson;
namespace eosio { namespace chain {
@@ -86,6 +76,17 @@ void variant_snapshot_reader::validate() const {
}
}
bool variant_snapshot_reader::has_section( const string& section_name ) {
const auto& sections = snapshot["sections"].get_array();
for( const auto& section: sections ) {
if (section["name"].as_string() == section_name) {
return true;
}
}
return false;
}
void variant_snapshot_reader::set_section( const string& section_name ) {
const auto& sections = snapshot["sections"].get_array();
for( const auto& section: sections ) {
@@ -189,45 +190,6 @@ void ostream_snapshot_writer::finalize() {
snapshot.write((char*)&end_marker, sizeof(end_marker));
}
ostream_json_snapshot_writer::ostream_json_snapshot_writer(std::ostream& snapshot)
:snapshot(snapshot)
,row_count(0)
{
snapshot << "{\n";
// write magic number
auto totem = magic_number;
snapshot << "\"magic_number\":" << fc::json::to_string(totem, fc::time_point::maximum()) << "\n";
// write version
auto version = current_snapshot_version;
snapshot << ",\"version\":" << fc::json::to_string(version, fc::time_point::maximum()) << "\n";
}
void ostream_json_snapshot_writer::write_start_section( const std::string& section_name )
{
row_count = 0;
snapshot.inner << "," << fc::json::to_string(section_name, fc::time_point::maximum()) << ":{\n\"rows\":[\n";
}
void ostream_json_snapshot_writer::write_row( const detail::abstract_snapshot_row_writer& row_writer ) {
const auto yield = [&](size_t s) {};
if(row_count != 0) snapshot.inner << ",";
snapshot.inner << fc::json::to_string(row_writer.to_variant(), yield) << "\n";
++row_count;
}
void ostream_json_snapshot_writer::write_end_section( ) {
snapshot.inner << "],\n\"num_rows\":" << row_count << "\n}\n";
row_count = 0;
}
void ostream_json_snapshot_writer::finalize() {
snapshot.inner << "}\n";
snapshot.inner.flush();
}
istream_snapshot_reader::istream_snapshot_reader(std::istream& snapshot)
:snapshot(snapshot)
,header_pos(snapshot.tellg())
@@ -284,6 +246,44 @@ bool istream_snapshot_reader::validate_section() const {
return true;
}
bool istream_snapshot_reader::has_section( const string& section_name ) {
auto restore_pos = fc::make_scoped_exit([this,pos=snapshot.tellg()](){
snapshot.seekg(pos);
});
const std::streamoff header_size = sizeof(ostream_snapshot_writer::magic_number) + sizeof(current_snapshot_version);
auto next_section_pos = header_pos + header_size;
while (true) {
snapshot.seekg(next_section_pos);
uint64_t section_size = 0;
snapshot.read((char*)&section_size,sizeof(section_size));
if (section_size == std::numeric_limits<uint64_t>::max()) {
break;
}
next_section_pos = snapshot.tellg() + std::streamoff(section_size);
uint64_t ignore = 0;
snapshot.read((char*)&ignore,sizeof(ignore));
bool match = true;
for(auto c : section_name) {
if(snapshot.get() != c) {
match = false;
break;
}
}
if (match && snapshot.get() == 0) {
return true;
}
}
return false;
}
void istream_snapshot_reader::set_section( const string& section_name ) {
auto restore_pos = fc::make_scoped_exit([this,pos=snapshot.tellg()](){
snapshot.seekg(pos);
@@ -346,91 +346,6 @@ void istream_snapshot_reader::return_to_header() {
clear_section();
}
struct istream_json_snapshot_reader_impl {
uint64_t num_rows;
uint64_t cur_row;
eosio_rapidjson::Document doc;
std::string sec_name;
};
istream_json_snapshot_reader::~istream_json_snapshot_reader() = default;
istream_json_snapshot_reader::istream_json_snapshot_reader(const fc::path& p)
: impl{new istream_json_snapshot_reader_impl{0, 0, {}, {}}}
{
FILE* fp = fopen(p.string().c_str(), "rb");
EOS_ASSERT(fp, snapshot_exception, "Failed to open JSON snapshot: ${file}", ("file", p));
auto close = fc::make_scoped_exit( [&fp]() { fclose( fp ); } );
char readBuffer[65536];
eosio_rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer));
impl->doc.ParseStream(is);
}
void istream_json_snapshot_reader::validate() const {
try {
// validate totem
auto expected_totem = ostream_json_snapshot_writer::magic_number;
EOS_ASSERT(impl->doc.HasMember("magic_number"), snapshot_exception, "magic_number section not found" );
auto actual_totem = impl->doc["magic_number"].GetUint();
EOS_ASSERT( actual_totem == expected_totem, snapshot_exception, "JSON snapshot has unexpected magic number" );
// validate version
auto expected_version = current_snapshot_version;
EOS_ASSERT(impl->doc.HasMember("version"), snapshot_exception, "version section not found" );
auto actual_version = impl->doc["version"].GetUint();
EOS_ASSERT( actual_version == expected_version, snapshot_exception,
"JSON snapshot is an unsupported version. Expected : ${expected}, Got: ${actual}",
("expected", expected_version)( "actual", actual_version ) );
} catch( const std::exception& e ) { \
snapshot_exception fce(FC_LOG_MESSAGE( warn, "JSON snapshot validation threw IO exception (${what})",("what",e.what())));
throw fce;
}
}
bool istream_json_snapshot_reader::validate_section() const {
return true;
}
void istream_json_snapshot_reader::set_section( const string& section_name ) {
EOS_ASSERT( impl->doc.HasMember( section_name.c_str() ), snapshot_exception, "JSON snapshot has no section ${sec}", ("sec", section_name) );
EOS_ASSERT( impl->doc[section_name.c_str()].HasMember( "num_rows" ), snapshot_exception, "JSON snapshot ${sec} num_rows not found", ("sec", section_name) );
EOS_ASSERT( impl->doc[section_name.c_str()].HasMember( "rows" ), snapshot_exception, "JSON snapshot ${sec} rows not found", ("sec", section_name) );
EOS_ASSERT( impl->doc[section_name.c_str()]["rows"].IsArray(), snapshot_exception, "JSON snapshot ${sec} rows is not an array", ("sec_name", section_name) );
impl->sec_name = section_name;
impl->num_rows = impl->doc[section_name.c_str()]["num_rows"].GetInt();
ilog( "reading ${section_name}, num_rows: ${num_rows}", ("section_name", section_name)( "num_rows", impl->num_rows ) );
}
bool istream_json_snapshot_reader::read_row( detail::abstract_snapshot_row_reader& row_reader ) {
EOS_ASSERT( impl->cur_row < impl->num_rows, snapshot_exception, "JSON snapshot ${sect}'s cur_row ${cur_row} >= num_rows ${num_rows}",
("sect_name", impl->sec_name)( "cur_row", impl->cur_row )( "num_rows", impl->num_rows ) );
const eosio_rapidjson::Value& rows = impl->doc[impl->sec_name.c_str()]["rows"];
eosio_rapidjson::StringBuffer buffer;
eosio_rapidjson::Writer<eosio_rapidjson::StringBuffer> writer( buffer );
rows[impl->cur_row].Accept( writer );
const auto& row = fc::json::from_string( buffer.GetString() );
row_reader.provide( row );
return ++impl->cur_row < impl->num_rows;
}
bool istream_json_snapshot_reader::empty ( ) {
return impl->num_rows == 0;
}
void istream_json_snapshot_reader::clear_section() {
impl->num_rows = 0;
impl->cur_row = 0;
impl->sec_name = "";
}
void istream_json_snapshot_reader::return_to_header() {
clear_section();
}
integrity_hash_snapshot_writer::integrity_hash_snapshot_writer(fc::sha256::encoder& enc)
:enc(enc)
{
+45 -66
View File
@@ -138,7 +138,7 @@ namespace eosio { namespace chain {
initial_objective_duration_limit = objective_duration_limit;
if( explicit_billed_cpu_time )
validate_cpu_usage_to_bill( billed_cpu_time_us, std::numeric_limits<int64_t>::max(), false, subjective_cpu_bill_us); // Fail early if the amount to be billed is too high
validate_cpu_usage_to_bill( billed_cpu_time_us, std::numeric_limits<int64_t>::max(), false ); // Fail early if the amount to be billed is too high
// Record accounts to be billed for network and CPU usage
if( control.is_builtin_activated(builtin_protocol_feature_t::only_bill_first_authorizer) ) {
@@ -204,7 +204,7 @@ namespace eosio { namespace chain {
if( validate_account_cpu_limit > 0 )
validate_account_cpu_limit -= EOS_PERCENT( validate_account_cpu_limit, 10 * config::percent_1 );
if( validate_account_cpu_limit < 0 ) validate_account_cpu_limit = 0;
validate_account_cpu_usage_estimate( billed_cpu_time_us, validate_account_cpu_limit, subjective_cpu_bill_us );
validate_account_cpu_usage_estimate( billed_cpu_time_us, validate_account_cpu_limit );
}
eager_net_limit = (eager_net_limit/8)*8; // Round down to nearest multiple of word size (8 bytes) so check_net_usage can be efficient
@@ -368,7 +368,7 @@ namespace eosio { namespace chain {
update_billed_cpu_time( now );
validate_cpu_usage_to_bill( billed_cpu_time_us, account_cpu_limit, true, subjective_cpu_bill_us );
validate_cpu_usage_to_bill( billed_cpu_time_us, account_cpu_limit, true );
rl.add_transaction_usage( bill_to_accounts, static_cast<uint64_t>(billed_cpu_time_us), net_usage,
block_timestamp_type(control.pending_block_time()).slot ); // Should never fail
@@ -415,19 +415,14 @@ namespace eosio { namespace chain {
"not enough time left in block to complete executing transaction ${billing_timer}us",
("now", now)("deadline", _deadline)("start", start)("billing_timer", now - pseudo_start) );
} else if( deadline_exception_code == tx_cpu_usage_exceeded::code_value ) {
std::string assert_msg = "transaction was executing for too long ${billing_timer}us";
if (subjective_cpu_bill_us > 0) {
assert_msg += " with a subjective cpu of (${subjective} us)";
}
if (cpu_limit_due_to_greylist) {
assert_msg = "greylisted " + assert_msg;
EOS_THROW( greylist_cpu_usage_exceeded,
assert_msg,
("now", now)("deadline", _deadline)("start", start)("billing_timer", now - pseudo_start)( "subjective", subjective_cpu_bill_us) );
"greylisted transaction was executing for too long ${billing_timer}us",
("now", now)("deadline", _deadline)("start", start)("billing_timer", now - pseudo_start) );
} else {
EOS_THROW( tx_cpu_usage_exceeded,
assert_msg,
("now", now)("deadline", _deadline)("start", start)("billing_timer", now - pseudo_start)("subjective", subjective_cpu_bill_us) );
"transaction was executing for too long ${billing_timer}us",
("now", now)("deadline", _deadline)("start", start)("billing_timer", now - pseudo_start) );
}
} else if( deadline_exception_code == leeway_deadline_exception::code_value ) {
EOS_THROW( leeway_deadline_exception,
@@ -465,7 +460,7 @@ namespace eosio { namespace chain {
transaction_timer.start(_deadline);
}
void transaction_context::validate_cpu_usage_to_bill( int64_t billed_us, int64_t account_cpu_limit, bool check_minimum, int64_t subjective_billed_us )const {
void transaction_context::validate_cpu_usage_to_bill( int64_t billed_us, int64_t account_cpu_limit, bool check_minimum )const {
if (!control.skip_trx_checks()) {
if( check_minimum ) {
const auto& cfg = control.get_global_properties().configuration;
@@ -475,11 +470,11 @@ namespace eosio { namespace chain {
);
}
validate_account_cpu_usage( billed_us, account_cpu_limit, subjective_billed_us );
validate_account_cpu_usage( billed_us, account_cpu_limit );
}
}
void transaction_context::validate_account_cpu_usage( int64_t billed_us, int64_t account_cpu_limit, int64_t subjective_billed_us )const {
void transaction_context::validate_account_cpu_usage( int64_t billed_us, int64_t account_cpu_limit )const {
if( (billed_us > 0) && !control.skip_trx_checks() ) {
const bool cpu_limited_by_account = (account_cpu_limit <= objective_duration_limit.count());
@@ -490,33 +485,26 @@ namespace eosio { namespace chain {
("billed", billed_us)( "billable", objective_duration_limit.count() )
);
} else {
auto assert_msg = [&](bool graylisted, bool subjective) {
std::string assert_msg = "billed CPU time (${billed} us) is greater than the maximum";
assert_msg += graylisted ? " greylisted" : "";
assert_msg += " billable CPU time for the transaction (${billable} us)";
assert_msg += subjective ? " with a subjective cpu of (${subjective} us)" : "";
return assert_msg;
};
auto graylisted = cpu_limit_due_to_greylist && cpu_limited_by_account;
auto subjective = subjective_billed_us > 0;
// exceeds trx.max_cpu_usage_ms or cfg.max_transaction_cpu_usage if objective_duration_limit is greater
auto limit = graylisted ? account_cpu_limit : (cpu_limited_by_account ? account_cpu_limit : objective_duration_limit.count());
if (graylisted)
EOS_ASSERT( billed_us <= limit,
greylist_cpu_usage_exceeded,
assert_msg(graylisted, subjective),
("billed", billed_us)("billable", limit)("subjective", subjective_billed_us));
else
EOS_ASSERT( billed_us <= limit,
if( cpu_limit_due_to_greylist && cpu_limited_by_account ) {
EOS_ASSERT( billed_us <= account_cpu_limit,
greylist_cpu_usage_exceeded,
"billed CPU time (${billed} us) is greater than the maximum greylisted billable CPU time for the transaction (${billable} us)",
("billed", billed_us)( "billable", account_cpu_limit )
);
} else {
// exceeds trx.max_cpu_usage_ms or cfg.max_transaction_cpu_usage if objective_duration_limit is greater
const int64_t cpu_limit = (cpu_limited_by_account ? account_cpu_limit : objective_duration_limit.count());
EOS_ASSERT( billed_us <= cpu_limit,
tx_cpu_usage_exceeded,
assert_msg(graylisted, subjective),
("billed", billed_us)("billable", limit)("subjective", subjective_billed_us));
"billed CPU time (${billed} us) is greater than the maximum billable CPU time for the transaction (${billable} us)",
("billed", billed_us)( "billable", cpu_limit )
);
}
}
}
}
void transaction_context::validate_account_cpu_usage_estimate( int64_t prev_billed_us, int64_t account_cpu_limit, int64_t subjective_billed_us )const {
void transaction_context::validate_account_cpu_usage_estimate( int64_t prev_billed_us, int64_t account_cpu_limit )const {
// prev_billed_us can be 0, but so can account_cpu_limit
if( (prev_billed_us >= 0) && !control.skip_trx_checks() ) {
const bool cpu_limited_by_account = (account_cpu_limit <= objective_duration_limit.count());
@@ -528,28 +516,21 @@ namespace eosio { namespace chain {
("billed", prev_billed_us)( "billable", objective_duration_limit.count() )
);
} else {
auto assert_msg = [&](bool graylisted, bool subjective) {
std::string assert_msg = "estimated CPU time (${billed} us) is not less than the maximum";
assert_msg += graylisted ? " greylisted" : "";
assert_msg += " billable CPU time for the transaction (${billable} us)";
assert_msg += subjective ? " with a subjective cpu of (${subjective} us)" : "";
return assert_msg;
};
auto graylisted = cpu_limit_due_to_greylist && cpu_limited_by_account;
auto subjective = subjective_billed_us > 0;
// exceeds trx.max_cpu_usage_ms or cfg.max_transaction_cpu_usage if objective_duration_limit is greater
auto limit = graylisted ? account_cpu_limit : (cpu_limited_by_account ? account_cpu_limit : objective_duration_limit.count());
if (graylisted)
EOS_ASSERT( prev_billed_us < limit,
greylist_cpu_usage_exceeded,
assert_msg(graylisted, subjective),
("billed", prev_billed_us)("billable", limit)("subjective", subjective_billed_us));
else
EOS_ASSERT( prev_billed_us < limit,
if( cpu_limit_due_to_greylist && cpu_limited_by_account ) {
EOS_ASSERT( prev_billed_us < account_cpu_limit,
greylist_cpu_usage_exceeded,
"estimated CPU time (${billed} us) is not less than the maximum greylisted billable CPU time for the transaction (${billable} us)",
("billed", prev_billed_us)( "billable", account_cpu_limit )
);
} else {
// exceeds trx.max_cpu_usage_ms or cfg.max_transaction_cpu_usage if objective_duration_limit is greater
const int64_t cpu_limit = (cpu_limited_by_account ? account_cpu_limit : objective_duration_limit.count());
EOS_ASSERT( prev_billed_us < cpu_limit,
tx_cpu_usage_exceeded,
assert_msg(graylisted, subjective),
("billed", prev_billed_us)("billable", limit)("subjective", subjective_billed_us));
"estimated CPU time (${billed} us) is not less than the maximum billable CPU time for the transaction (${billable} us)",
("billed", prev_billed_us)( "billable", cpu_limit )
);
}
}
}
}
@@ -740,14 +721,12 @@ namespace eosio { namespace chain {
const auto& db = control.db();
const auto& auth_manager = control.get_authorization_manager();
if( !trx.context_free_actions.empty() && !control.skip_trx_checks() ) {
for( const auto& a : trx.context_free_actions ) {
auto* code = db.find<account_object, by_name>( a.account );
EOS_ASSERT( code != nullptr, transaction_exception,
"action's code account '${account}' does not exist", ("account", a.account) );
EOS_ASSERT( a.authorization.size() == 0, transaction_exception,
"context-free actions cannot have authorizations" );
}
for( const auto& a : trx.context_free_actions ) {
auto* code = db.find<account_object, by_name>(a.account);
EOS_ASSERT( code != nullptr, transaction_exception,
"action's code account '${account}' does not exist", ("account", a.account) );
EOS_ASSERT( a.authorization.size() == 0, transaction_exception,
"context-free actions cannot have authorizations" );
}
flat_set<account_name> actors;
@@ -223,7 +223,7 @@ void executor::execute(const code_descriptor& code, memory& mem, apply_context&
cb->bounce_buffers->clear();
tt.set_expiration_callback(nullptr, nullptr);
int64_t base_pages = mem.size_of_memory_slice_mapping()/memory::stride - 1;
uint64_t base_pages = mem.size_of_memory_slice_mapping()/memory::stride - 1;
if(cb->current_linear_memory_pages > base_pages) {
mprotect(mem.full_page_memory_base() + base_pages * eosio::chain::wasm_constraints::wasm_page_size,
(cb->current_linear_memory_pages - base_pages) * eosio::chain::wasm_constraints::wasm_page_size, PROT_NONE);
@@ -25,7 +25,7 @@ memory::memory(uint64_t max_pages) {
FC_ASSERT(mapbase != MAP_FAILED, "Failed to mmap memory");
uint8_t* next_slice = mapbase;
uint8_t* last = nullptr;
uint8_t* last;
for(unsigned int p = 0; p < number_slices; ++p) {
last = (uint8_t*)mmap(next_slice, memory_prologue_size+64u*1024u*p, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, 0);
@@ -33,7 +33,6 @@ memory::memory(uint64_t max_pages) {
next_slice += total_memory_per_slice;
}
FC_ASSERT(last != nullptr, "expected last not nullptr");
zeropage_base = mapbase + memory_prologue_size;
fullpage_base = last + memory_prologue_size;
@@ -247,7 +247,7 @@ std::unique_ptr<wasm_instantiated_module_interface> eos_vm_runtime<Impl>::instan
wasm_code_ptr code((uint8_t*)code_bytes, code_size);
apply_options options = { .max_pages = 65536,
.max_call_depth = 0 };
std::unique_ptr<backend_t> bkend = std::make_unique<backend_t>(code, code_size, nullptr, options);
std::unique_ptr<backend_t> bkend = std::make_unique<backend_t>(code, code_size, nullptr, options, false); // uses 2-passes parsing
eos_vm_host_functions_t::resolve(bkend->get_module());
return std::make_unique<eos_vm_instantiated_module<Impl>>(this, std::move(bkend));
} catch(eosio::vm::exception& e) {
@@ -273,7 +273,7 @@ std::unique_ptr<wasm_instantiated_module_interface> eos_vm_profile_runtime::inst
wasm_code_ptr code((uint8_t*)code_bytes, code_size);
apply_options options = { .max_pages = 65536,
.max_call_depth = 0 };
std::unique_ptr<backend_t> bkend = std::make_unique<backend_t>(code, code_size, nullptr, options);
std::unique_ptr<backend_t> bkend = std::make_unique<backend_t>(code, code_size, nullptr, options, false); // uses 2-passes parsing
eos_vm_host_functions_t::resolve(bkend->get_module());
return std::make_unique<eos_vm_profiling_module>(std::move(bkend), code_bytes, code_size);
} catch(eosio::vm::exception& e) {
-2
View File
@@ -1,2 +0,0 @@
add_library(leap-cli11 INTERFACE)
target_include_directories(leap-cli11 INTERFACE include)
-26
View File
@@ -1,26 +0,0 @@
## instructions for building custom leap-cli11 library
leap-cli11 interface only library created in order to simplify integration of modified version of command line parsing library cli11
to update included in this library include/cli11/CLI11.hpp file it needs to be (re)geenerated from repository containing forked/modified version of it, in particular:
```bash
git clone https://github.com/AntelopeIO/CLI11.git
cd CLI11
mkdir build
cd build
cmake -DCLI11_SINGLE_FILE=ON ..
make -j
```
Resulting single-header will be located in:
```cpp
build/include/CLI11.hpp
```
And is ready to be copied to include/cli11/CLI11.hpp of leap-cli11 library
Automated CLI11 subproject build / import of CLI11.hpp header will be added in future versions.
@@ -1,26 +0,0 @@
#/usr/bin/env bash
_cleos_complete()
{
# Get cmdline while ignoring the last word
cmdline=${COMP_LINE}
if [[ "${cmdline:(-1)}" != " " ]]; then
cmdline=${COMP_WORDS[@]:0:${COMP_CWORD}}
fi
# Get complete candidates
words=$(${cmdline} --_autocomplete "${COMP_WORDS[${COMP_CWORD}]}")
# Remove candidates that begins with `-` if `-` is not passed as the first character
# TODO: move this logic inside CLI11? including the compgen?
if [[ ! ${COMP_WORDS[${COMP_CWORD}]} = -* ]]; then
words=(${words})
for index in "${!words[@]}" ; do [[ ${words[$index]} =~ ^- ]] && unset -v 'words[$index]' ; done
words="${words[@]}"
fi
# Get matches
COMPREPLY=($(compgen -W "${words}" -- "${COMP_WORDS[${COMP_CWORD}]}"))
}
complete -F _cleos_complete cleos
@@ -1,26 +0,0 @@
#/usr/bin/env bash
_leap_complete()
{
# Get cmdline while ignoring the last word
cmdline=${COMP_LINE}
if [[ "${cmdline:(-1)}" != " " ]]; then
cmdline=${COMP_WORDS[@]:0:${COMP_CWORD}}
fi
# Get complete candidates
words=$(${cmdline} --_autocomplete "${COMP_WORDS[${COMP_CWORD}]}")
# Remove candidates that begins with `-` if `-` is not passed as the first character
# TODO: move this logic inside CLI11? including the compgen?
if [[ ! ${COMP_WORDS[${COMP_CWORD}]} = -* ]]; then
words=(${words})
for index in "${!words[@]}" ; do [[ ${words[$index]} =~ ^- ]] && unset -v 'words[$index]' ; done
words="${words[@]}"
fi
# Get matches
COMPREPLY=($(compgen -W "${words}" -- "${COMP_WORDS[${COMP_CWORD}]}"))
}
complete -F _leap_complete leap-util
Submodule
+1
Submodule libraries/fc added at 35144b5563
-155
View File
@@ -1,155 +0,0 @@
add_subdirectory( secp256k1 )
set( WITH_PROCPS OFF CACHE BOOL "" FORCE)
set( CURVE "ALT_BN128" CACHE STRING "" FORCE)
set( USE_ASM OFF CACHE BOOL "" FORCE)
set( IS_LIBFF_PARENT OFF CACHE BOOL "" FORCE)
set( FF_INSTALL_COMPONENT "${FC_INSTALL_COMPONENT}")
add_subdirectory( libraries/ff )
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads)
find_package(OpenSSL REQUIRED)
set( fc_sources
src/uint128.cpp
src/real128.cpp
src/variant.cpp
src/exception.cpp
src/variant_object.cpp
src/string.cpp
src/time.cpp
src/mock_time.cpp
src/utf8.cpp
src/io/datastream.cpp
src/io/json.cpp
src/io/varint.cpp
src/io/fstream.cpp
src/io/console.cpp
src/filesystem.cpp
src/interprocess/file_mapping.cpp
src/interprocess/mmap_struct.cpp
src/log/log_message.cpp
src/log/logger.cpp
src/log/appender.cpp
src/log/console_appender.cpp
src/log/dmlog_appender.cpp
src/log/logger_config.cpp
src/crypto/_digest_common.cpp
src/crypto/aes.cpp
src/crypto/crc.cpp
src/crypto/city.cpp
# src/crypto/base32.cpp
src/crypto/base36.cpp
src/crypto/base58.cpp
src/crypto/base64.cpp
src/crypto/bigint.cpp
src/crypto/hex.cpp
src/crypto/sha1.cpp
src/crypto/sha3.cpp
src/crypto/ripemd160.cpp
src/crypto/sha256.cpp
src/crypto/sha224.cpp
src/crypto/sha512.cpp
src/crypto/dh.cpp
src/crypto/blowfish.cpp
src/crypto/elliptic_common.cpp
src/crypto/elliptic_impl_priv.cpp
src/crypto/elliptic_secp256k1.cpp
src/crypto/elliptic_r1.cpp
src/crypto/elliptic_webauthn.cpp
src/crypto/rand.cpp
src/crypto/public_key.cpp
src/crypto/private_key.cpp
src/crypto/signature.cpp
src/crypto/alt_bn128.cpp
src/crypto/modular_arithmetic.cpp
src/crypto/blake2.cpp
src/crypto/k1_recover.cpp
src/network/ip.cpp
src/network/platform_root_ca.cpp
src/network/resolve.cpp
src/network/udp_socket.cpp
src/network/url.cpp
src/network/http/http_client.cpp
src/compress/smaz.cpp
src/compress/zlib.cpp
src/log/gelf_appender.cpp
src/log/zipkin.cpp
)
file( GLOB_RECURSE fc_headers ${CMAKE_CURRENT_SOURCE_DIR} *.hpp *.h )
add_library(fc ${fc_sources} ${fc_headers})
function(detect_thread_name)
include(CheckSymbolExists)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
list(APPEND CMAKE_REQUIRED_LIBRARIES "-pthread")
check_symbol_exists(pthread_setname_np pthread.h HAVE_PTHREAD_SETNAME_NP)
if(HAVE_PTHREAD_SETNAME_NP)
set_source_files_properties(src/log/logger_config.cpp PROPERTIES COMPILE_DEFINITIONS FC_USE_PTHREAD_NAME_NP)
endif()
endfunction()
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
detect_thread_name()
endif()
# Yuck: newer CMake files from boost iostreams will effectively target_link_libraries(Boost::iostreams z;bz2;lzma;zstd)
# without first "finding" those libraries. This resolves to simple -lz -lbz2 etc: it'll look for those libraries in the linker's
# library search path. This is most problematic on macOS where something like libzstd isn't in the standard search path. Historically
# fc would just "-L/usr/local/lib" as a heavy handed way to make sure something like -lzstd can be found in brew's library path. But
# that isn't sufficient for something like ARM homebrew. Let's just "null" these libraries out since we're already linking to zlib
# explicitly anyways via a proper find_package(ZLIB) below.
if(APPLE)
add_library(z INTERFACE)
add_library(bz2 INTERFACE)
add_library(lzma INTERFACE)
add_library(zstd INTERFACE)
endif()
find_package(Boost 1.66 REQUIRED COMPONENTS
date_time
filesystem
chrono
unit_test_framework
iostreams)
# fc picks up a dependency on zlib via Boost::iostreams, however in some versions of cmake/boost (depending on if CMake config
# files are used) the Boost::iostreams target does not have a dependency on zlib itself so add it explicitly
find_package(ZLIB REQUIRED)
target_include_directories(fc PUBLIC include)
# try and make this very clear that this json parser is intended only for webauthn parsing..
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.11.0)
set_source_files_properties(src/crypto/elliptic_webauthn.cpp PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/include/fc/crypto/webauthn_json/include")
else()
set_source_files_properties(src/crypto/elliptic_webauthn.cpp PROPERTIES COMPILE_FLAGS "-I${CMAKE_CURRENT_SOURCE_DIR}/include/fc/crypto/webauthn_json/include")
endif()
if(WIN32)
target_link_libraries( fc PUBLIC ws2_32 mswsock userenv )
endif()
if(APPLE)
find_library(security_framework Security)
find_library(corefoundation_framework CoreFoundation)
endif()
target_link_libraries( fc PUBLIC ff
Boost::date_time Boost::filesystem Boost::chrono Boost::iostreams Threads::Threads
OpenSSL::Crypto OpenSSL::SSL ZLIB::ZLIB ${PLATFORM_SPECIFIC_LIBS} ${CMAKE_DL_LIBS} secp256k1 ${security_framework} ${corefoundation_framework} )
# Critically, this ensures that OpenSSL 1.1 & 3.0 both have a variant of BN_zero() with void return value. But it also allows access
# to some obsoleted AES functions in 3.0 too, since 3.0's API_COMPAT is effectively 3.0 by default
target_compile_definitions(fc PUBLIC "OPENSSL_API_COMPAT=0x10100000L" "OPENSSL_NO_DEPRECATED")
add_subdirectory( test )
install(TARGETS fc
LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} COMPONENT dev EXCLUDE_FROM_ALL
ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} COMPONENT dev EXCLUDE_FROM_ALL)
install(DIRECTORY include/fc DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR} COMPONENT dev EXCLUDE_FROM_ALL)
-65
View File
@@ -1,65 +0,0 @@
#pragma once
#include <fc/api.hpp>
#include <fc/thread/thread.hpp>
namespace fc {
namespace detail {
struct actor_member {
#if 1 // BOOST_NO_VARIADIC_TEMPLATES
#define RPC_MEMBER_FUNCTOR(z,n,IS_CONST) \
template<typename R, typename C, typename P BOOST_PP_ENUM_TRAILING_PARAMS( n, typename A)> \
static std::function<fc::future<R>( BOOST_PP_ENUM_PARAMS(n,A) ) > \
functor( P p, R (C::*mem_func)(BOOST_PP_ENUM_PARAMS(n,A)) IS_CONST, fc::thread* c = 0) { \
return [=](BOOST_PP_ENUM_BINARY_PARAMS(n,A,a))->fc::future<R>{ \
return c->async( [=](){ return (p->*mem_func)(BOOST_PP_ENUM_PARAMS(n,a)); } ); }; \
}
BOOST_PP_REPEAT( 8, RPC_MEMBER_FUNCTOR, const )
BOOST_PP_REPEAT( 8, RPC_MEMBER_FUNCTOR, BOOST_PP_EMPTY() )
#undef RPC_MEMBER_FUNCTOR
#else // g++ has a bug that prevents lambdas and varidic templates from working together (G++ Bug 41933)
template<typename R, typename C, typename P, typename... Args>
static std::function<fc::future<R>(Args...)> functor( P&& p, R (C::*mem_func)(Args...), fc::thread* c ) {
return [=](Args... args)->fc::future<R>{ c->async( [=]()->R { return p->*mem_func( fc::forward<Args>(args)... ); } ) };
}
template<typename R, typename C, typename P, typename... Args>
static std::function<fc::future<R>(Args...)> functor( P&& p, R (C::*mem_func)(Args...)const, fc::thread* c ){
return [=](Args... args)->fc::future<R>{ c->async( [=]()->R { return p->*mem_func( fc::forward<Args>(args)... ); } ) };
}
#endif
};
template<typename ThisPtr>
struct actor_vtable_visitor {
template<typename U>
actor_vtable_visitor( fc::thread* t, U&& u ):_thread(t),_this( fc::forward<U>(u) ){}
template<typename Function, typename MemberPtr>
void operator()( const char* name, Function& memb, MemberPtr m )const {
memb = actor_member::functor( _this, m, _thread );
}
fc::thread* _thread;
ThisPtr _this;
};
}
/**
* Posts all method calls to another thread and
* returns a future.
*/
template<typename Interface>
class actor : public api<Interface, detail::actor_member> {
public:
actor(){}
template<typename InterfaceType>
actor( InterfaceType* p, fc::thread* t = &fc::thread::current() )
{
this->_vtable.reset(new detail::vtable<Interface,detail::actor_member>() );
this->_vtable->template visit<InterfaceType>( detail::actor_vtable_visitor<InterfaceType*>(t, p) );
}
};
} // namespace fc
-14
View File
@@ -1,14 +0,0 @@
#pragma once
namespace fc {
template<unsigned int S, typename T=double>
struct aligned {
union {
T _align;
char _data[S];
} _store;
operator char*() { return _store._data; }
operator const char*()const { return _store._data; }
};
}
-7
View File
@@ -1,7 +0,0 @@
#pragma once
#include <boost/any.hpp>
namespace fc {
// TODO: define this without using boost
typedef boost::any any;
}
-134
View File
@@ -1,134 +0,0 @@
#pragma once
#include <fc/thread/future.hpp>
#include <fc/any.hpp>
#include <functional>
#include <boost/config.hpp>
// ms visual c++ (as of 2013) doesn't accept the standard syntax for calling a
// templated member function (foo->template bar();)
#ifdef _MSC_VER
# define FC_CALL_MEMBER_TEMPLATE_KEYWORD
#else
# define FC_CALL_MEMBER_TEMPLATE_KEYWORD template
#endif
namespace fc {
struct identity_member {
template<typename R, typename C, typename P, typename... Args>
static std::function<R(Args...)> functor( P&& p, R (C::*mem_func)(Args...) );
template<typename R, typename C, typename P, typename... Args>
static std::function<R(Args...)> functor( P&& p, R (C::*mem_func)(Args...)const );
};
template< typename Interface, typename Transform >
struct vtable : public std::enable_shared_from_this<vtable<Interface,Transform>>
{ private: vtable(); };
template<typename OtherType>
struct vtable_copy_visitor {
typedef OtherType other_type;
vtable_copy_visitor( OtherType& s):_source( s ){}
template<typename R, typename MemberPtr, typename... Args>
void operator()( const char* name, std::function<R(Args...)>& memb, MemberPtr m )const {
OtherType* src = &_source;
memb = [src,m]( Args... args ){ return (src->*m)(args...); };
}
OtherType& _source;
};
template<typename Interface, typename Transform >
class api;
class api_connection;
typedef uint32_t api_id_type;
class api_base
{
public:
api_base() {}
virtual ~api_base() {}
virtual uint64_t get_handle()const = 0;
virtual api_id_type register_api( api_connection& conn )const = 0;
// defined in api_connection.hpp
template< typename T >
api<T, identity_member> as();
};
typedef std::shared_ptr< api_base > api_ptr;
class api_connection;
template<typename Interface, typename Transform = identity_member >
class api : public api_base {
public:
typedef vtable<Interface,Transform> vtable_type;
api():_vtable( std::make_shared<vtable_type>() ) {}
/** T is anything with pointer semantics */
template<typename T >
api( const T& p )
:_vtable( std::make_shared<vtable_type>() )
{
_data = std::make_shared<fc::any>(p);
T& ptr = boost::any_cast<T&>(*_data);
auto& pointed_at = *ptr;
typedef typename std::remove_reference<decltype(pointed_at)>::type source_vtable_type;
_vtable->FC_CALL_MEMBER_TEMPLATE_KEYWORD visit_other( vtable_copy_visitor<source_vtable_type>(pointed_at) );
}
api( const api& cpy ):_vtable(cpy._vtable),_data(cpy._data) {}
virtual ~api() {}
friend bool operator == ( const api& a, const api& b ) { return a._data == b._data && a._vtable == b._vtable; }
friend bool operator != ( const api& a, const api& b ) { return !(a._data == b._data && a._vtable == b._vtable); }
virtual uint64_t get_handle()const override { return uint64_t(_data.get()); }
virtual api_id_type register_api( api_connection& conn )const override; // defined in api_connection.hpp
vtable_type& operator*()const { FC_ASSERT( _vtable ); return *_vtable; }
vtable_type* operator->()const { FC_ASSERT( _vtable ); return _vtable.get(); }
protected:
std::shared_ptr<vtable_type> _vtable;
std::shared_ptr<fc::any> _data;
};
} // namespace fc
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/stringize.hpp>
#define FC_API_VTABLE_DEFINE_MEMBER( r, data, elem ) \
decltype(Transform::functor( (data*)nullptr, &data::elem)) elem;
#define FC_API_VTABLE_DEFINE_VISIT_OTHER( r, data, elem ) \
{ typedef typename Visitor::other_type OtherType; \
v( BOOST_PP_STRINGIZE(elem), elem, &OtherType::elem ); }
#define FC_API_VTABLE_DEFINE_VISIT( r, data, elem ) \
v( BOOST_PP_STRINGIZE(elem), elem );
#define FC_API( CLASS, METHODS ) \
namespace fc { \
template<typename Transform> \
struct vtable<CLASS,Transform> : public std::enable_shared_from_this<vtable<CLASS,Transform>> { \
BOOST_PP_SEQ_FOR_EACH( FC_API_VTABLE_DEFINE_MEMBER, CLASS, METHODS ) \
template<typename Visitor> \
void visit_other( Visitor&& v ){ \
BOOST_PP_SEQ_FOR_EACH( FC_API_VTABLE_DEFINE_VISIT_OTHER, CLASS, METHODS ) \
} \
template<typename Visitor> \
void visit( Visitor&& v ){ \
BOOST_PP_SEQ_FOR_EACH( FC_API_VTABLE_DEFINE_VISIT, CLASS, METHODS ) \
} \
}; \
}
-145
View File
@@ -1,145 +0,0 @@
#pragma once
#include <fc/crypto/base64.hpp>
#include <fc/variant.hpp>
#include <fc/reflect/reflect.hpp>
#include <fc/exception/exception.hpp>
namespace fc {
/**
* Provides a fixed size array that is easier for templates to specialize
* against or overload than T[N].
*/
template<typename T, size_t N>
class array {
public:
/**
* Checked indexing (when in debug build) that also simplifies dereferencing
* when you have an array<T,N>*.
*/
///@{
T& at( size_t pos ) { FC_ASSERT( pos < N, "array out-of-bounds" ); return data[pos]; }
const T& at( size_t pos )const { FC_ASSERT( pos < N, "array out-of-bounds" ); return data[pos]; }
///@}
T& operator[]( size_t pos ) { FC_ASSERT( pos < N, "array out-of-bounds" ); return data[pos]; }
const T& operator[]( size_t pos )const { FC_ASSERT( pos < N, "array out-of-bounds" ); return data[pos]; }
const T* begin()const { return &data[0]; }
const T* end()const { return &data[N]; }
T* begin() { return &data[0]; }
T* end() { return &data[N]; }
size_t size()const { return N; }
T data[N];
};
/** provided for default 0 init */
template<size_t N>
class array<unsigned char,N>
{
public:
typedef unsigned char T;
array(){ memset( data, 0, sizeof(data) ); }
/**
* Checked indexing (when in debug build) that also simplifies dereferencing
* when you have an array<T,N>*.
*/
///@{
T& at( size_t pos ) { FC_ASSERT( pos < N, "array out-of-bounds" ); return data[pos]; }
const T& at( size_t pos )const { FC_ASSERT( pos < N, "array out-of-bounds" ); return data[pos]; }
///@}
T* begin() { return &data[0]; }
const T* begin()const { return &data[0]; }
const T* end()const { return &data[N]; }
size_t size()const { return N; }
T data[N];
};
/** provided for default 0 init */
template<size_t N>
class array<char,N>
{
public:
typedef char T;
array(){ memset( data, 0, sizeof(data) ); }
/**
* Checked indexing (when in debug build) that also simplifies dereferencing
* when you have an array<T,N>*.
*/
///@{
T& at( size_t pos ) { FC_ASSERT( pos < N, "array out-of-bounds" ); return data[pos]; }
const T& at( size_t pos )const { FC_ASSERT( pos < N, "array out-of-bounds" ); return data[pos]; }
///@}
T* begin() { return &data[0]; }
const T* begin()const { return &data[0]; }
const T* end()const { return &data[N]; }
size_t size()const { return N; }
T data[N];
};
template<typename T, size_t N>
bool operator == ( const array<T,N>& a, const array<T,N>& b )
{ return 0 == memcmp( a.data, b.data, N*sizeof(T) ); }
template<typename T, size_t N>
bool operator < ( const array<T,N>& a, const array<T,N>& b )
{ return memcmp( a.data, b.data, N*sizeof(T) ) < 0 ; }
template<typename T, size_t N>
bool operator > ( const array<T,N>& a, const array<T,N>& b )
{ return memcmp( a.data, b.data, N*sizeof(T) ) > 0 ; }
template<typename T, size_t N>
bool operator != ( const array<T,N>& a, const array<T,N>& b )
{ return 0 != memcmp( a.data, b.data, N*sizeof(T) ); }
template<typename T, size_t N>
void to_variant( const array<T,N>& bi, variant& v )
{
v = std::vector<char>( (const char*)&bi, ((const char*)&bi) + sizeof(bi) );
}
template<typename T, size_t N>
void from_variant( const variant& v, array<T,N>& bi )
{
std::vector<char> ve = v.as< std::vector<char> >();
if( ve.size() )
{
memcpy(bi.begin(), ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
}
else
memset( bi.begin(), char(0), sizeof(bi) );
}
template<typename T,size_t N> struct get_typename< fc::array<T,N> >
{
static const char* name()
{
static std::string _name = std::string("fc::array<")+std::string(fc::get_typename<T>::name())+","+ fc::to_string(N) + ">";
return _name.c_str();
}
};
}
#include <unordered_map>
#include <fc/crypto/city.hpp>
namespace std
{
template<typename T, size_t N>
struct hash<fc::array<T,N> >
{
size_t operator()( const fc::array<T,N>& e )const
{
return fc::city_hash_size_t( (char*)&e, sizeof(e) );
}
};
}
-28
View File
@@ -1,28 +0,0 @@
#pragma once
#include <stdint.h>
namespace fc {
inline uint64_t endian_reverse_u64( uint64_t x )
{
return (((x >> 0x38) & 0xFF) )
| (((x >> 0x30) & 0xFF) << 0x08)
| (((x >> 0x28) & 0xFF) << 0x10)
| (((x >> 0x20) & 0xFF) << 0x18)
| (((x >> 0x18) & 0xFF) << 0x20)
| (((x >> 0x10) & 0xFF) << 0x28)
| (((x >> 0x08) & 0xFF) << 0x30)
| (((x ) & 0xFF) << 0x38)
;
}
inline uint32_t endian_reverse_u32( uint32_t x )
{
return (((x >> 0x18) & 0xFF) )
| (((x >> 0x10) & 0xFF) << 0x08)
| (((x >> 0x08) & 0xFF) << 0x10)
| (((x ) & 0xFF) << 0x18)
;
}
} // namespace fc
-621
View File
@@ -1,621 +0,0 @@
#pragma once
/*
*********************************************************************
* *
* Open Bloom Filter *
* *
* Author: Arash Partow - 2000 *
* URL: http://www.partow.net *
* URL: http://www.partow.net/programming/hashfunctions/index.html *
* *
* Copyright notice: *
* Free use of the Open Bloom Filter Library is permitted under the *
* guidelines and in accordance with the most current version of the *
* Common Public License. *
* http://www.opensource.org/licenses/cpl1.0.php *
* *
*********************************************************************
*/
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <iterator>
#include <limits>
#include <string>
#include <vector>
#include <fc/reflect/reflect.hpp>
namespace fc {
static const std::size_t bits_per_char = 0x08; // 8 bits in 1 char(unsigned)
static const unsigned char bit_mask[bits_per_char] = {
0x01, //00000001
0x02, //00000010
0x04, //00000100
0x08, //00001000
0x10, //00010000
0x20, //00100000
0x40, //01000000
0x80 //10000000
};
class bloom_parameters
{
public:
bloom_parameters()
: minimum_size(1),
maximum_size(std::numeric_limits<unsigned long long int>::max()),
minimum_number_of_hashes(1),
maximum_number_of_hashes(std::numeric_limits<unsigned int>::max()),
projected_element_count(10000),
false_positive_probability(1.0 / projected_element_count),
random_seed(0xA5A5A5A55A5A5A5AULL)
{}
virtual ~bloom_parameters()
{}
inline bool operator!()
{
return (minimum_size > maximum_size) ||
(minimum_number_of_hashes > maximum_number_of_hashes) ||
(minimum_number_of_hashes < 1) ||
(0 == maximum_number_of_hashes) ||
(0 == projected_element_count) ||
(false_positive_probability < 0.0) ||
(std::numeric_limits<double>::infinity() == std::abs(false_positive_probability)) ||
(0 == random_seed) ||
(0xFFFFFFFFFFFFFFFFULL == random_seed);
}
//Allowed min/max size of the bloom filter in bits
unsigned long long int minimum_size;
unsigned long long int maximum_size;
//Allowed min/max number of hash functions
unsigned int minimum_number_of_hashes;
unsigned int maximum_number_of_hashes;
//The approximate number of elements to be inserted
//into the bloom filter, should be within one order
//of magnitude. The default is 10000.
unsigned long long int projected_element_count;
//The approximate false positive probability expected
//from the bloom filter. The default is the reciprocal
//of the projected_element_count.
double false_positive_probability;
unsigned long long int random_seed;
struct optimal_parameters_t
{
optimal_parameters_t()
: number_of_hashes(0),
table_size(0)
{}
unsigned int number_of_hashes;
unsigned long long int table_size;
};
optimal_parameters_t optimal_parameters;
virtual bool compute_optimal_parameters()
{
/*
Note:
The following will attempt to find the number of hash functions
and minimum amount of storage bits required to construct a bloom
filter consistent with the user defined false positive probability
and estimated element insertion count.
*/
if (!(*this))
return false;
double min_m = std::numeric_limits<double>::infinity();
double min_k = 0.0;
double curr_m = 0.0;
double k = 1.0;
while (k < 1000.0)
{
double numerator = (- k * projected_element_count);
double denominator = std::log(1.0 - std::pow(false_positive_probability, 1.0 / k));
curr_m = numerator / denominator;
if (curr_m < min_m)
{
min_m = curr_m;
min_k = k;
}
k += 1.0;
}
optimal_parameters_t& optp = optimal_parameters;
optp.number_of_hashes = static_cast<unsigned int>(min_k);
optp.table_size = static_cast<unsigned long long int>(min_m);
optp.table_size += (((optp.table_size % bits_per_char) != 0) ? (bits_per_char - (optp.table_size % bits_per_char)) : 0);
if (optp.number_of_hashes < minimum_number_of_hashes)
optp.number_of_hashes = minimum_number_of_hashes;
else if (optp.number_of_hashes > maximum_number_of_hashes)
optp.number_of_hashes = maximum_number_of_hashes;
if (optp.table_size < minimum_size)
optp.table_size = minimum_size;
else if (optp.table_size > maximum_size)
optp.table_size = maximum_size;
return true;
}
};
class bloom_filter
{
protected:
typedef unsigned int bloom_type;
typedef unsigned char cell_type;
public:
bloom_filter()
: salt_count_(0),
table_size_(0),
raw_table_size_(0),
projected_element_count_(0),
inserted_element_count_(0),
random_seed_(0),
desired_false_positive_probability_(0.0)
{}
bloom_filter(const bloom_parameters& p)
: projected_element_count_(p.projected_element_count),
inserted_element_count_(0),
random_seed_((p.random_seed * 0xA5A5A5A5) + 1),
desired_false_positive_probability_(p.false_positive_probability)
{
salt_count_ = p.optimal_parameters.number_of_hashes;
table_size_ = p.optimal_parameters.table_size;
generate_unique_salt();
raw_table_size_ = table_size_ / bits_per_char;
bit_table_.resize( static_cast<std::size_t>(raw_table_size_) );
//bit_table_ = new cell_type[static_cast<std::size_t>(raw_table_size_)];
std::fill_n(bit_table_.data(),raw_table_size_,0x00);
}
bloom_filter(const bloom_filter& filter)
{
this->operator=(filter);
}
inline bool operator == (const bloom_filter& f) const
{
if (this != &f)
{
return
(salt_count_ == f.salt_count_) &&
(table_size_ == f.table_size_) &&
(raw_table_size_ == f.raw_table_size_) &&
(projected_element_count_ == f.projected_element_count_) &&
(inserted_element_count_ == f.inserted_element_count_) &&
(random_seed_ == f.random_seed_) &&
(desired_false_positive_probability_ == f.desired_false_positive_probability_) &&
(salt_ == f.salt_) &&
std::equal(f.bit_table_.data(),f.bit_table_.data() + raw_table_size_,bit_table_.data());
}
else
return true;
}
inline bool operator != (const bloom_filter& f) const
{
return !operator==(f);
}
inline bloom_filter& operator = (const bloom_filter& f)
{
if (this != &f)
{
salt_count_ = f.salt_count_;
table_size_ = f.table_size_;
raw_table_size_ = f.raw_table_size_;
projected_element_count_ = f.projected_element_count_;
inserted_element_count_ = f.inserted_element_count_;
random_seed_ = f.random_seed_;
desired_false_positive_probability_ = f.desired_false_positive_probability_;
bit_table_.resize( raw_table_size_ );
std::copy(f.bit_table_.data(),f.bit_table_.data() + raw_table_size_,bit_table_.data());
salt_ = f.salt_;
}
return *this;
}
virtual ~bloom_filter()
{
}
inline bool operator!() const
{
return (0 == table_size_);
}
inline void clear()
{
std::fill_n(bit_table_.data(),raw_table_size_,0x00);
inserted_element_count_ = 0;
}
inline void insert(const unsigned char* key_begin, const std::size_t& length)
{
std::size_t bit_index = 0;
std::size_t bit = 0;
for (std::size_t i = 0; i < salt_.size(); ++i)
{
compute_indices(hash_ap(key_begin,length,salt_[i]),bit_index,bit);
bit_table_[bit_index / bits_per_char] |= bit_mask[bit];
}
++inserted_element_count_;
}
template<typename T>
inline void insert(const T& t)
{
// Note: T must be a C++ POD type.
insert(reinterpret_cast<const unsigned char*>(&t),sizeof(T));
}
inline void insert(const std::string& key)
{
insert(reinterpret_cast<const unsigned char*>(key.c_str()),key.size());
}
inline void insert(const char* data, const std::size_t& length)
{
insert(reinterpret_cast<const unsigned char*>(data),length);
}
template<typename InputIterator>
inline void insert(const InputIterator begin, const InputIterator end)
{
InputIterator itr = begin;
while (end != itr)
{
insert(*(itr++));
}
}
inline virtual bool contains(const unsigned char* key_begin, const std::size_t length) const
{
std::size_t bit_index = 0;
std::size_t bit = 0;
for (std::size_t i = 0; i < salt_.size(); ++i)
{
compute_indices(hash_ap(key_begin,length,salt_[i]),bit_index,bit);
if ((bit_table_[bit_index / bits_per_char] & bit_mask[bit]) != bit_mask[bit])
{
return false;
}
}
return true;
}
template<typename T>
inline bool contains(const T& t) const
{
return contains(reinterpret_cast<const unsigned char*>(&t),static_cast<std::size_t>(sizeof(T)));
}
inline bool contains(const std::string& key) const
{
return contains(reinterpret_cast<const unsigned char*>(key.c_str()),key.size());
}
inline bool contains(const char* data, const std::size_t& length) const
{
return contains(reinterpret_cast<const unsigned char*>(data),length);
}
template<typename InputIterator>
inline InputIterator contains_all(const InputIterator begin, const InputIterator end) const
{
InputIterator itr = begin;
while (end != itr)
{
if (!contains(*itr))
{
return itr;
}
++itr;
}
return end;
}
template<typename InputIterator>
inline InputIterator contains_none(const InputIterator begin, const InputIterator end) const
{
InputIterator itr = begin;
while (end != itr)
{
if (contains(*itr))
{
return itr;
}
++itr;
}
return end;
}
inline virtual unsigned long long int size() const
{
return table_size_;
}
inline std::size_t element_count() const
{
return inserted_element_count_;
}
inline double effective_fpp() const
{
/*
Note:
The effective false positive probability is calculated using the
designated table size and hash function count in conjunction with
the current number of inserted elements - not the user defined
predicated/expected number of inserted elements.
*/
return std::pow(1.0 - std::exp(-1.0 * salt_.size() * inserted_element_count_ / size()), 1.0 * salt_.size());
}
inline bloom_filter& operator &= (const bloom_filter& f)
{
/* intersection */
if (
(salt_count_ == f.salt_count_) &&
(table_size_ == f.table_size_) &&
(random_seed_ == f.random_seed_)
)
{
for (std::size_t i = 0; i < raw_table_size_; ++i)
{
bit_table_[i] &= f.bit_table_[i];
}
}
return *this;
}
inline bloom_filter& operator |= (const bloom_filter& f)
{
/* union */
if (
(salt_count_ == f.salt_count_) &&
(table_size_ == f.table_size_) &&
(random_seed_ == f.random_seed_)
)
{
for (std::size_t i = 0; i < raw_table_size_; ++i)
{
bit_table_[i] |= f.bit_table_[i];
}
}
return *this;
}
inline bloom_filter& operator ^= (const bloom_filter& f)
{
/* difference */
if (
(salt_count_ == f.salt_count_) &&
(table_size_ == f.table_size_) &&
(random_seed_ == f.random_seed_)
)
{
for (std::size_t i = 0; i < raw_table_size_; ++i)
{
bit_table_[i] ^= f.bit_table_[i];
}
}
return *this;
}
inline const cell_type* table() const
{
return bit_table_.data();
}
inline std::size_t hash_count()
{
return salt_.size();
}
protected:
inline virtual void compute_indices(const bloom_type& hash, std::size_t& bit_index, std::size_t& bit) const
{
bit_index = hash % table_size_;
bit = bit_index % bits_per_char;
}
void generate_unique_salt()
{
/*
Note:
A distinct hash function need not be implementation-wise
distinct. In the current implementation "seeding" a common
hash function with different values seems to be adequate.
*/
const unsigned int predef_salt_count = 128;
static const bloom_type predef_salt[predef_salt_count] =
{
0xAAAAAAAA, 0x55555555, 0x33333333, 0xCCCCCCCC,
0x66666666, 0x99999999, 0xB5B5B5B5, 0x4B4B4B4B,
0xAA55AA55, 0x55335533, 0x33CC33CC, 0xCC66CC66,
0x66996699, 0x99B599B5, 0xB54BB54B, 0x4BAA4BAA,
0xAA33AA33, 0x55CC55CC, 0x33663366, 0xCC99CC99,
0x66B566B5, 0x994B994B, 0xB5AAB5AA, 0xAAAAAA33,
0x555555CC, 0x33333366, 0xCCCCCC99, 0x666666B5,
0x9999994B, 0xB5B5B5AA, 0xFFFFFFFF, 0xFFFF0000,
0xB823D5EB, 0xC1191CDF, 0xF623AEB3, 0xDB58499F,
0xC8D42E70, 0xB173F616, 0xA91A5967, 0xDA427D63,
0xB1E8A2EA, 0xF6C0D155, 0x4909FEA3, 0xA68CC6A7,
0xC395E782, 0xA26057EB, 0x0CD5DA28, 0x467C5492,
0xF15E6982, 0x61C6FAD3, 0x9615E352, 0x6E9E355A,
0x689B563E, 0x0C9831A8, 0x6753C18B, 0xA622689B,
0x8CA63C47, 0x42CC2884, 0x8E89919B, 0x6EDBD7D3,
0x15B6796C, 0x1D6FDFE4, 0x63FF9092, 0xE7401432,
0xEFFE9412, 0xAEAEDF79, 0x9F245A31, 0x83C136FC,
0xC3DA4A8C, 0xA5112C8C, 0x5271F491, 0x9A948DAB,
0xCEE59A8D, 0xB5F525AB, 0x59D13217, 0x24E7C331,
0x697C2103, 0x84B0A460, 0x86156DA9, 0xAEF2AC68,
0x23243DA5, 0x3F649643, 0x5FA495A8, 0x67710DF8,
0x9A6C499E, 0xDCFB0227, 0x46A43433, 0x1832B07A,
0xC46AFF3C, 0xB9C8FFF0, 0xC9500467, 0x34431BDF,
0xB652432B, 0xE367F12B, 0x427F4C1B, 0x224C006E,
0x2E7E5A89, 0x96F99AA5, 0x0BEB452A, 0x2FD87C39,
0x74B2E1FB, 0x222EFD24, 0xF357F60C, 0x440FCB1E,
0x8BBE030F, 0x6704DC29, 0x1144D12F, 0x948B1355,
0x6D8FD7E9, 0x1C11A014, 0xADD1592F, 0xFB3C712E,
0xFC77642F, 0xF9C4CE8C, 0x31312FB9, 0x08B0DD79,
0x318FA6E7, 0xC040D23D, 0xC0589AA7, 0x0CA5C075,
0xF874B172, 0x0CF914D5, 0x784D3280, 0x4E8CFEBC,
0xC569F575, 0xCDB2A091, 0x2CC016B4, 0x5C5F4421
};
if (salt_count_ <= predef_salt_count)
{
std::copy(predef_salt,
predef_salt + salt_count_,
std::back_inserter(salt_));
for (unsigned int i = 0; i < salt_.size(); ++i)
{
/*
Note:
This is done to integrate the user defined random seed,
so as to allow for the generation of unique bloom filter
instances.
*/
salt_[i] = salt_[i] * salt_[(i + 3) % salt_.size()] + static_cast<bloom_type>(random_seed_);
}
}
else
{
std::copy(predef_salt,predef_salt + predef_salt_count,std::back_inserter(salt_));
srand(static_cast<unsigned int>(random_seed_));
while (salt_.size() < salt_count_)
{
bloom_type current_salt = static_cast<bloom_type>(rand()) * static_cast<bloom_type>(rand());
if (0 == current_salt) continue;
if (salt_.end() == std::find(salt_.begin(), salt_.end(), current_salt))
{
salt_.push_back(current_salt);
}
}
}
}
inline bloom_type hash_ap(const unsigned char* begin, std::size_t remaining_length, bloom_type hash) const
{
const unsigned char* itr = begin;
unsigned int loop = 0;
while (remaining_length >= 8)
{
const unsigned int& i1 = *(reinterpret_cast<const unsigned int*>(itr)); itr += sizeof(unsigned int);
const unsigned int& i2 = *(reinterpret_cast<const unsigned int*>(itr)); itr += sizeof(unsigned int);
hash ^= (hash << 7) ^ i1 * (hash >> 3) ^
(~((hash << 11) + (i2 ^ (hash >> 5))));
remaining_length -= 8;
}
if (remaining_length)
{
if (remaining_length >= 4)
{
const unsigned int& i = *(reinterpret_cast<const unsigned int*>(itr));
if (loop & 0x01)
hash ^= (hash << 7) ^ i * (hash >> 3);
else
hash ^= (~((hash << 11) + (i ^ (hash >> 5))));
++loop;
remaining_length -= 4;
itr += sizeof(unsigned int);
}
if (remaining_length >= 2)
{
const unsigned short& i = *(reinterpret_cast<const unsigned short*>(itr));
if (loop & 0x01)
hash ^= (hash << 7) ^ i * (hash >> 3);
else
hash ^= (~((hash << 11) + (i ^ (hash >> 5))));
++loop;
remaining_length -= 2;
itr += sizeof(unsigned short);
}
if (remaining_length)
{
hash += ((*itr) ^ (hash * 0xA5A5A5A5)) + loop;
}
}
return hash;
}
public:
std::vector<bloom_type> salt_;
std::vector<unsigned char> bit_table_;
unsigned int salt_count_;
unsigned long long int table_size_;
unsigned long long int raw_table_size_;
unsigned long long int projected_element_count_;
unsigned int inserted_element_count_;
unsigned long long int random_seed_;
double desired_false_positive_probability_;
};
inline bloom_filter operator & (const bloom_filter& a, const bloom_filter& b)
{
bloom_filter result = a;
result &= b;
return result;
}
inline bloom_filter operator | (const bloom_filter& a, const bloom_filter& b)
{
bloom_filter result = a;
result |= b;
return result;
}
inline bloom_filter operator ^ (const bloom_filter& a, const bloom_filter& b)
{
bloom_filter result = a;
result ^= b;
return result;
}
} // namespace fc
FC_REFLECT( fc::bloom_filter, (salt_)(bit_table_)(salt_count_)(table_size_)(raw_table_size_)(projected_element_count_)(inserted_element_count_)(random_seed_)(desired_false_positive_probability_) )
FC_REFLECT( fc::bloom_parameters::optimal_parameters_t, (number_of_hashes)(table_size) )
FC_REFLECT( fc::bloom_parameters, (minimum_size)(maximum_size)(minimum_number_of_hashes)(maximum_number_of_hashes)(projected_element_count)(false_positive_probability)(random_seed)(optimal_parameters) )
/*
Note 1:
If it can be guaranteed that bits_per_char will be of the form 2^n then
the following optimization can be used:
hash_table[bit_index >> n] |= bit_mask[bit_index & (bits_per_char - 1)];
Note 2:
For performance reasons where possible when allocating memory it should
be aligned (aligned_alloc) according to the architecture being used.
*/
@@ -1,9 +0,0 @@
#pragma once
#include <string>
namespace fc {
std::string smaz_compress( const std::string& in );
std::string smaz_decompress( const std::string& compressed );
} // namespace fc
@@ -1,10 +0,0 @@
#pragma once
#include <fc/string.hpp>
namespace fc
{
string zlib_compress(const string& in);
} // namespace fc
@@ -1,160 +0,0 @@
#pragma once
#include <fc/variant.hpp>
#include <fc/io/raw_fwd.hpp>
namespace fc {
namespace raw {
namespace detail {
template<template<typename...> class Set, typename Stream, typename T, typename... U>
inline void pack_set( Stream& s, const Set<T, U...>& value ) {
FC_ASSERT( value.size() <= MAX_NUM_ARRAY_ELEMENTS );
pack( s, unsigned_int((uint32_t)value.size()) );
for( const auto& item : value ) {
pack( s, item );
}
}
template<template<typename...> class Set, typename Stream, typename T, typename... U>
inline void unpack_set( Stream& s, Set<T, U...>& value ) {
unsigned_int size; unpack( s, size );
FC_ASSERT( size.value <= MAX_NUM_ARRAY_ELEMENTS );
value.clear();
for( uint32_t i = 0; i < size.value; ++i ) {
auto tmp = ::fc::detail::construct_maybe_with_allocator<T>( value.get_allocator() );
unpack( s, tmp );
value.insert( value.end(), std::move(tmp) );
}
}
template<template<typename...> class Set, typename Stream, typename T, typename... U>
inline void unpack_flat_set( Stream& s, Set<T, U...>& value ) {
unsigned_int size; unpack( s, size );
FC_ASSERT( size.value <= MAX_NUM_ARRAY_ELEMENTS );
value.clear();
value.reserve( size.value );
for( uint32_t i = 0; i < size.value; ++i ) {
auto tmp = ::fc::detail::construct_maybe_with_allocator<T>( value.get_allocator() );
unpack( s, tmp );
value.insert( value.end(), std::move(tmp) );
}
}
template<template<typename...> class Map, typename Stream, typename K, typename V, typename... U>
inline void pack_map( Stream& s, const Map<K, V, U...>& value ) {
FC_ASSERT( value.size() <= MAX_NUM_ARRAY_ELEMENTS );
pack( s, unsigned_int((uint32_t)value.size()) );
for( const auto& item : value ) {
pack( s, item );
}
}
template<template<typename...> class Map, typename Stream, typename K, typename V, typename... U>
inline void unpack_map( Stream& s, Map<K, V, U...>& value ) {
unsigned_int size; unpack( s, size );
FC_ASSERT( size.value <= MAX_NUM_ARRAY_ELEMENTS );
value.clear();
for( uint32_t i = 0; i < size.value; ++i ) {
auto tmp = ::fc::detail::default_construct_pair_maybe_with_allocator<K, V>( value.get_allocator() );
unpack( s, tmp );
value.insert( value.end(), std::move(tmp) );
}
}
template<template<typename...> class Map, typename Stream, typename K, typename V, typename... U>
inline void unpack_flat_map( Stream& s, Map<K, V, U...>& value ) {
unsigned_int size; unpack( s, size );
FC_ASSERT( size.value <= MAX_NUM_ARRAY_ELEMENTS );
value.clear();
value.reserve( size.value );
for( uint32_t i = 0; i < size.value; ++i ) {
auto tmp = ::fc::detail::default_construct_pair_maybe_with_allocator<K, V>( value.get_allocator() );
unpack( s, tmp );
value.insert( value.end(), std::move(tmp) );
}
}
}
}
namespace detail {
template<template<typename...> class Set, typename T, typename... U>
void to_variant_from_set( const Set<T, U...>& s, fc::variant& vo ) {
FC_ASSERT( s.size() <= MAX_NUM_ARRAY_ELEMENTS );
variants vars;
vars.reserve( s.size() );
for( const auto& item : s ) {
vars.emplace_back( item );
}
vo = std::move( vars );
}
template<template<typename...> class Set, typename T, typename... U>
void from_variant_to_set( const fc::variant& v, Set< T, U... >& s ) {
const variants& vars = v.get_array();
FC_ASSERT( vars.size() <= MAX_NUM_ARRAY_ELEMENTS );
s.clear();
for( const auto& var : vars ) {
auto item = construct_maybe_with_allocator<T>( s.get_allocator() );
var.as<T>( item );
s.insert( s.end(), std::move(item) );
}
}
template<template<typename...> class Set, typename T, typename... U>
void from_variant_to_flat_set( const fc::variant& v, Set< T, U... >& s ) {
const variants& vars = v.get_array();
FC_ASSERT( vars.size() <= MAX_NUM_ARRAY_ELEMENTS );
s.clear();
s.reserve( vars.size() );
for( const auto& var : vars ) {
auto item = construct_maybe_with_allocator<T>( s.get_allocator() );
var.as<T>( item );
s.insert( s.end(), std::move(item) );
}
}
template<template<typename...> class Map, typename K, typename V, typename... U >
void to_variant_from_map( const Map< K, V, U... >& m, fc::variant& vo ) {
FC_ASSERT( m.size() <= MAX_NUM_ARRAY_ELEMENTS );
variants vars;
vars.reserve( m.size() );
for( const auto& item : m ) {
vars.emplace_back( item );
}
vo = std::move( vars );
}
template<template<typename...> class Map, typename K, typename V, typename... U>
void from_variant_to_map( const variant& v, Map<K, V, U...>& m ) {
const variants& vars = v.get_array();
FC_ASSERT( vars.size() <= MAX_NUM_ARRAY_ELEMENTS );
m.clear();
for( const auto& var : vars ) {
auto item = default_construct_pair_maybe_with_allocator<K, V>( m.get_allocator() );
var.as< std::pair<K,V> >( item );
m.insert( m.end(), std::move(item) );
}
}
template<template<typename...> class Map, typename K, typename V, typename... U>
void from_variant_to_flat_map( const variant& v, Map<K, V, U...>& m ) {
const variants& vars = v.get_array();
FC_ASSERT( vars.size() <= MAX_NUM_ARRAY_ELEMENTS );
m.clear();
m.reserve( vars.size() );
for( const auto& var : vars ) {
auto item = default_construct_pair_maybe_with_allocator<K, V>( m.get_allocator() );
var.as< std::pair<K,V> >( item );
m.insert( m.end(), std::move(item) );
}
}
}
}
@@ -1,12 +0,0 @@
#pragma once
#include <deque>
#include <fc/io/raw.hpp>
namespace fc {
namespace raw {
} // namespace raw
} // namespace fc
@@ -1,13 +0,0 @@
#pragma once
#include <deque>
namespace fc {
namespace raw {
template<typename Stream, typename T>
void pack( Stream& s, const std::deque<T>& value );
template<typename Stream, typename T>
void unpack( Stream& s, std::deque<T>& value );
}
} // namespace fc
@@ -1,186 +0,0 @@
#pragma once
#include <fc/container/flat_fwd.hpp>
#include <fc/container/container_detail.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <fc/crypto/hex.hpp>
namespace fc {
namespace raw {
template<typename Stream, typename T, typename A>
void pack( Stream& s, const boost::container::vector<T, A>& value ) {
FC_ASSERT( value.size() <= MAX_NUM_ARRAY_ELEMENTS );
pack( s, unsigned_int((uint32_t)value.size()) );
if( !std::is_fundamental<T>::value ) {
for( const auto& item : value ) {
pack( s, item );
}
} else if( value.size() ) {
s.write( (const char*)value.data(), value.size() );
}
}
template<typename Stream, typename T, typename A>
void unpack( Stream& s, boost::container::vector<T, A>& value ) {
unsigned_int size;
unpack( s, size );
FC_ASSERT( size.value <= MAX_NUM_ARRAY_ELEMENTS );
value.clear();
value.resize( size.value );
if( !std::is_fundamental<T>::value ) {
for( auto& item : value ) {
unpack( s, item );
}
} else if( value.size() ) {
s.read( (char*)value.data(), value.size() );
}
}
template<typename Stream, typename A>
void pack( Stream& s, const boost::container::vector<char, A>& value ) {
FC_ASSERT( value.size() <= MAX_SIZE_OF_BYTE_ARRAYS );
pack( s, unsigned_int((uint32_t)value.size()) );
if( value.size() )
s.write( (const char*)value.data(), value.size() );
}
template<typename Stream, typename A>
void unpack( Stream& s, boost::container::vector<char, A>& value ) {
unsigned_int size;
unpack( s, size );
FC_ASSERT( size.value <= MAX_SIZE_OF_BYTE_ARRAYS );
value.clear();
value.resize( size.value );
if( value.size() )
s.read( (char*)value.data(), value.size() );
}
template<typename Stream, typename T, typename... U>
void pack( Stream& s, const flat_set<T, U...>& value ) {
detail::pack_set( s, value );
}
template<typename Stream, typename T, typename... U>
void unpack( Stream& s, flat_set<T, U...>& value ) {
detail::unpack_flat_set( s, value );
}
template<typename Stream, typename T, typename... U>
void pack( Stream& s, const flat_multiset<T, U...>& value ) {
detail::pack_set( s, value );
}
template<typename Stream, typename T, typename... U>
void unpack( Stream& s, flat_multiset<T, U...>& value ) {
detail::unpack_flat_set( s, value );
}
template<typename Stream, typename K, typename V, typename... U>
void pack( Stream& s, const flat_map<K, V, U...>& value ) {
detail::pack_map( s, value );
}
template<typename Stream, typename K, typename V, typename... U>
void unpack( Stream& s, flat_map<K, V, U...>& value ) {
detail::unpack_flat_map( s, value );
}
template<typename Stream, typename K, typename V, typename... U>
void pack( Stream& s, const flat_multimap<K, V, U...>& value ) {
detail::pack_map( s, value );
}
template<typename Stream, typename K, typename V, typename... U>
void unpack( Stream& s, flat_multimap<K, V, U...>& value ) {
detail::unpack_flat_map( s, value );
}
} // namespace raw
template<typename T, typename... U>
void to_variant( const boost::container::vector<T, U...>& vec, fc::variant& vo ) {
FC_ASSERT( vec.size() <= MAX_NUM_ARRAY_ELEMENTS );
variants vars;
vars.reserve( vec.size() );
for( const auto& item : vec ) {
vars.emplace_back( item );
}
vo = std::move(vars);
}
template<typename T, typename... U>
void from_variant( const fc::variant& v, boost::container::vector<T, U...>& vec ) {
const variants& vars = v.get_array();
FC_ASSERT( vars.size() <= MAX_NUM_ARRAY_ELEMENTS );
vec.clear();
vec.resize( vars.size() );
for( uint32_t i = 0; i < vars.size(); ++i ) {
from_variant( vars[i], vec[i] );
}
}
template<typename... U>
void to_variant( const boost::container::vector<char, U...>& vec, fc::variant& vo ) {
FC_ASSERT( vec.size() <= MAX_SIZE_OF_BYTE_ARRAYS );
if( vec.size() )
vo = variant( fc::to_hex( vec.data(), vec.size() ) );
else
vo = "";
}
template<typename... U>
void from_variant( const fc::variant& v, boost::container::vector<char, U...>& vec )
{
const auto& str = v.get_string();
FC_ASSERT( str.size() <= 2*MAX_SIZE_OF_BYTE_ARRAYS ); // Doubled because hex strings needs two characters per byte
vec.resize( str.size() / 2 );
if( vec.size() ) {
size_t r = fc::from_hex( str, vec.data(), vec.size() );
FC_ASSERT( r == vec.size() );
}
}
template<typename T, typename... U>
void to_variant( const flat_set< T, U... >& s, fc::variant& vo ) {
detail::to_variant_from_set( s, vo );
}
template<typename T, typename... U>
void from_variant( const fc::variant& v, flat_set< T, U... >& s ) {
detail::from_variant_to_flat_set( v, s );
}
template<typename T, typename... U>
void to_variant( const flat_multiset< T, U... >& s, fc::variant& vo ) {
detail::to_variant_from_set( s, vo );
}
template<typename T, typename... U>
void from_variant( const fc::variant& v, flat_multiset< T, U... >& s ) {
detail::from_variant_to_flat_set( v, s );
}
template<typename K, typename V, typename... U >
void to_variant( const flat_map< K, V, U... >& m, fc::variant& vo ) {
detail::to_variant_from_map( m, vo );
}
template<typename K, typename V, typename... U>
void from_variant( const variant& v, flat_map<K, V, U...>& m ) {
detail::from_variant_to_flat_map( v, m );
}
template<typename K, typename V, typename... U >
void to_variant( const flat_multimap< K, V, U... >& m, fc::variant& vo ) {
detail::to_variant_from_map( m, vo );
}
template<typename K, typename V, typename... U>
void from_variant( const variant& v, flat_multimap<K, V, U...>& m ) {
detail::from_variant_to_flat_map( v, m );
}
}
@@ -1,45 +0,0 @@
#pragma once
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <boost/container/vector.hpp>
#include <boost/interprocess/containers/vector.hpp> // only added to maintain backwards compatibility with existing consumers of fc (can eventually remove)
namespace fc {
using boost::container::flat_set;
using boost::container::flat_multiset;
using boost::container::flat_map;
using boost::container::flat_multimap;
namespace raw {
template<typename Stream, typename T, typename... U>
void pack( Stream& s, const boost::container::vector<T, U...>& value );
template<typename Stream, typename T, typename... U>
void unpack( Stream& s, boost::container::vector<T, U...>& value );
template<typename Stream, typename T, typename... U>
void pack( Stream& s, const flat_set<T, U...>& value );
template<typename Stream, typename T, typename... U>
void unpack( Stream& s, flat_set<T, U...>& value );
template<typename Stream, typename T, typename... U>
void pack( Stream& s, const flat_multiset<T, U...>& value );
template<typename Stream, typename T, typename... U>
void unpack( Stream& s, flat_multiset<T, U...>& value );
template<typename Stream, typename K, typename V, typename... U>
void pack( Stream& s, const flat_map<K, V, U...>& value );
template<typename Stream, typename K, typename V, typename... U>
void unpack( Stream& s, flat_map<K, V, U...>& value ) ;
template<typename Stream, typename K, typename V, typename... U>
void pack( Stream& s, const flat_multimap<K, V, U...>& value );
template<typename Stream, typename K, typename V, typename... U>
void unpack( Stream& s, flat_multimap<K, V, U...>& value ) ;
} // namespace raw
} // fc
@@ -1,124 +0,0 @@
#pragma once
#include <fc/exception/exception.hpp>
#include <fc/io/cfile.hpp>
#include <fc/io/datastream.hpp>
#include <fc/io/fstream.hpp>
#include <fc/io/raw.hpp>
#include <fstream>
namespace fc {
/**
* Specialize tracked::memory_size() if obj does not provide a memory_size() method that represents memory size.
*/
namespace tracked {
template<typename T>
size_t memory_size( const T& obj ) {
return obj.memory_size();
}
}
/**
* @class tracked_storage
* @brief tracks the size of storage allocated to its underlying multi_index
*
* This class wraps a multi_index container and tracks the memory allocated as
* the container creates, modifies, and deletes. It also provides read and write
* methods for persistence.
*
* Requires ContainerType::value_type to have a size() method that represents the
* memory used for that object or specialized tracked::size() and is required to
* be a pack/unpack-able type.
*/
template <typename ContainerType>
class tracked_storage {
private:
size_t _memory_size = 0;
ContainerType _index;
public:
typedef typename ContainerType::template nth_index<0>::type primary_index_type;
tracked_storage() = default;
// read in the contents of a persisted tracked_storage and prevent reading in
// more stored objects once max_memory is reached.
// returns true if entire persisted tracked_storage was read
bool read(fc::cfile_datastream& ds, size_t max_memory) {
auto container_size = _index.size();
fc::raw::unpack(ds, container_size);
for (size_t i = 0; i < container_size; ++i) {
if (memory_size() >= max_memory) {
return false;
}
typename ContainerType::value_type v;
fc::raw::unpack(ds, v);
insert(std::move(v));
}
return true;
}
void write(fc::cfile& dat_content) const {
const auto container_size = _index.size();
dat_content.write( reinterpret_cast<const char*>(&container_size), sizeof(container_size) );
for (const auto& item : _index) {
auto data = fc::raw::pack(item);
dat_content.write(data.data(), data.size());
}
}
std::pair<typename primary_index_type::iterator, bool> insert(typename ContainerType::value_type obj) {
const auto size = tracked::memory_size(obj);
auto result = _index.insert(std::move(obj));
if (result.second) {
_memory_size += size;
}
return result;
}
template<typename Key>
typename primary_index_type::iterator find(const Key& key) {
primary_index_type& primary_idx = _index.template get<0>();
return primary_idx.find(key);
}
template<typename Key>
typename primary_index_type::const_iterator find(const Key& key) const {
const primary_index_type& primary_idx = _index.template get<0>();
return primary_idx.find(key);
}
template<typename Lam>
void modify(typename primary_index_type::iterator itr, Lam lam) {
_memory_size -= tracked::memory_size(*itr);
if (_index.modify( itr, std::move(lam))) {
_memory_size += tracked::memory_size(*itr);
}
}
template<typename Key>
void erase(const Key& key) {
auto itr = _index.find(key);
if (itr == _index.end())
return;
_memory_size -= tracked::memory_size(*itr);
_index.erase(itr);
}
void erase(typename primary_index_type::iterator itr) {
_memory_size -= tracked::memory_size(*itr);
_index.erase(itr);
}
size_t memory_size() const {
return _memory_size;
}
const ContainerType& index() const {
return _index;
}
};
}
-54
View File
@@ -1,54 +0,0 @@
#pragma once
#include <fc/crypto/sha512.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/uint128.hpp>
#include <fc/fwd.hpp>
#include <vector>
namespace fc {
class path;
class aes_encoder
{
public:
void init( const fc::sha256& key, const fc::uint128& init_value );
uint32_t encode( const char* plaintxt, uint32_t len, char* ciphertxt );
// uint32_t final_encode( char* ciphertxt );
private:
struct impl;
fc::fwd<impl,96> my;
};
class aes_decoder
{
public:
void init( const fc::sha256& key, const fc::uint128& init_value );
uint32_t decode( const char* ciphertxt, uint32_t len, char* plaintext );
// uint32_t final_decode( char* plaintext );
private:
struct impl;
fc::fwd<impl,96> my;
};
unsigned aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
unsigned char *iv, unsigned char *ciphertext);
unsigned aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
unsigned char *iv, unsigned char *plaintext);
unsigned aes_cfb_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
unsigned char *iv, unsigned char *plaintext);
std::vector<char> aes_encrypt( const fc::sha512& key, const std::vector<char>& plain_text );
std::vector<char> aes_decrypt( const fc::sha512& key, const std::vector<char>& cipher_text );
/** encrypts plain_text and then includes a checksum that enables us to verify the integrety of
* the file / key prior to decryption.
*/
void aes_save( const fc::path& file, const fc::sha512& key, std::vector<char> plain_text );
/**
* recovers the plain_text saved via aes_save()
*/
std::vector<char> aes_load( const fc::path& file, const fc::sha512& key );
} // namespace fc
@@ -1,25 +0,0 @@
#pragma once
#include <functional>
#include <cstdint>
#include <variant>
#include <vector>
#include <fc/utility.hpp>
namespace fc {
using bytes = std::vector<char>;
enum class alt_bn128_error : int32_t {
operand_component_invalid,
operand_not_in_curve,
pairing_list_size_error,
operand_outside_g2,
input_len_error,
invalid_scalar_size
};
std::variant<alt_bn128_error, bytes> alt_bn128_add(const bytes& op1, const bytes& op2);
std::variant<alt_bn128_error, bytes> alt_bn128_mul(const bytes& g1_point, const bytes& scalar);
std::variant<alt_bn128_error, bool> alt_bn128_pair(const bytes& g1_g2_pairs, const yield_function_t& yield);
} // fc
@@ -1,10 +0,0 @@
#pragma once
#include <fc/vector.hpp>
#include <fc/string.hpp>
namespace fc
{
std::vector<char> from_base32( const fc::string& b32 );
fc::string to_base32( const std::vector<char>& vec );
fc::string to_base32( const char* data, size_t len );
}
@@ -1,10 +0,0 @@
#pragma once
#include <fc/vector.hpp>
#include <fc/string.hpp>
namespace fc
{
std::vector<char> from_base36( const fc::string& b36 );
fc::string to_base36( const std::vector<char>& vec );
fc::string to_base36( const char* data, size_t len );
}
@@ -1,11 +0,0 @@
#pragma once
#include <fc/string.hpp>
#include <fc/time.hpp>
#include <vector>
namespace fc {
std::string to_base58( const char* d, size_t s, const fc::yield_function_t& yield );
std::string to_base58( const std::vector<char>& data, const fc::yield_function_t& yield );
std::vector<char> from_base58( const std::string& base58_str );
size_t from_base58( const std::string& base58_str, char* out_data, size_t out_data_len );
}
@@ -1,14 +0,0 @@
#pragma once
#include <string>
namespace fc {
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len);
inline std::string base64_encode(char const* bytes_to_encode, unsigned int in_len) { return base64_encode( (unsigned char const*)bytes_to_encode, in_len); }
std::string base64_encode( const std::string& enc );
std::string base64_decode( const std::string& encoded_string);
std::string base64url_encode(unsigned char const* bytes_to_encode, unsigned int in_len);
inline std::string base64url_encode(char const* bytes_to_encode, unsigned int in_len) { return base64url_encode( (unsigned char const*)bytes_to_encode, in_len); }
std::string base64url_encode( const std::string& enc );
std::string base64url_decode( const std::string& encoded_string);
} // namespace fc
@@ -1,76 +0,0 @@
#pragma once
#include <stdint.h>
#include <fc/string.hpp>
#include <fc/vector.hpp>
struct bignum_st;
typedef bignum_st BIGNUM;
namespace fc {
class bigint {
public:
bigint( const std::vector<char>& bige );
bigint( const char* bige, uint32_t l );
bigint(uint64_t value);
bigint( );
bigint( const bigint& c );
bigint( bigint&& c );
explicit bigint( BIGNUM* n );
~bigint();
bigint& operator = ( const bigint& a );
bigint& operator = ( bigint&& a );
explicit operator bool()const;
bool is_negative()const;
int64_t to_int64()const;
int64_t log2()const;
bigint exp( const bigint& c )const;
static bigint random( uint32_t bits, int t, int );
bool operator < ( const bigint& c )const;
bool operator > ( const bigint& c )const;
bool operator >= ( const bigint& c )const;
bool operator == ( const bigint& c )const;
bool operator != ( const bigint& c )const;
bigint operator + ( const bigint& a )const;
bigint operator * ( const bigint& a )const;
bigint operator / ( const bigint& a )const;
bigint operator % ( const bigint& a )const;
bigint operator /= ( const bigint& a );
bigint operator *= ( const bigint& a );
bigint& operator += ( const bigint& a );
bigint& operator -= ( const bigint& a );
bigint& operator <<= ( uint32_t i );
bigint& operator >>= ( uint32_t i );
bigint operator - ( const bigint& a )const;
bigint operator++(int);
bigint& operator++();
bigint operator--(int);
bigint& operator--();
operator fc::string()const;
// returns bignum as bigendian bytes
operator std::vector<char>()const;
BIGNUM* dup()const;
BIGNUM* get()const { return n; }
private:
BIGNUM* n;
};
class variant;
/** encodes the big int as base64 string, or a number */
void to_variant( const bigint& bi, variant& v );
/** decodes the big int as base64 string, or a number */
void from_variant( const variant& v, bigint& bi );
} // namespace fc

Some files were not shown because too many files have changed in this diff Show More