From db47baa0349a488e81c1822e1401ba25262bff33 Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Fri, 22 Aug 2025 00:07:39 -0400 Subject: [PATCH 01/13] validate hash of pinned package repo --- tools/pinned.pl | 145 ++++++++++++++++++++++++++++++++++ tools/reproducible.Dockerfile | 16 +++- 2 files changed, 158 insertions(+), 3 deletions(-) create mode 100755 tools/pinned.pl diff --git a/tools/pinned.pl b/tools/pinned.pl new file mode 100755 index 0000000000..ba62ba3014 --- /dev/null +++ b/tools/pinned.pl @@ -0,0 +1,145 @@ +#!/usr/bin/perl +# An apt method that validates InRelease files are a configured hash value. Useful to ensure the package repo is exactly what is expected. +use strict; +use warnings; +use IPC::Open2; +use feature 'signatures'; +no warnings 'experimental::signatures'; + +$| = 1; # disable output buffering + +my %expected_hashes; +my ($http_child_out, $http_child_in); +my $pid = open2($http_child_out, $http_child_in, "/usr/lib/apt/methods/http"); + +# get the capabilities from the http method and forward it on to apt unchanged +print STDOUT read_block($http_child_out); + +# read the configuration from apt and forward it to http method unchanged, but also inspect for our configuration +my @config_block = read_block(*STDIN); +if (@config_block && $config_block[0] =~ /^601 Configuration/) { + for my $line (@config_block) { + if ($line =~ /^Config-Item: ?Acquire::pinned::InReleaseHashes::([^=]+)=([^\s]+)/) { + my ($key, $hash) = ($1, $2); + $expected_hashes{$key} = $hash; + } + } + print $http_child_in @config_block; +} else { + die "did not receive 601 Configuration message from apt as expected.\n"; +} + +#main loop: read a block from apt with the command to run +while (my @command_block = read_block(*STDIN)) { + my $original_uri_from_apt = parse_block(@command_block)->{URI} // die "failed to get URI from command block\n"; + #perform some filtering on the headers before forwarding on to http method + @command_block = map { s/(URI: ?)pinned:/$1http:/r } # replace URI: pinned://... with URI: http://... + grep { !/^Last-Modified:/ } # scrub Last-Modified because cache hits will not have a file to check hash against + @command_block; + + print $http_child_in @command_block; + + #make note if we're getting an InRelease file and the expected hash of it. We need to track this now because we may encounter a redirect + # to a very opaque filename + my $expected_hash; + if($original_uri_from_apt =~ /InRelease$/) { + my ($inrelease_suite) = $original_uri_from_apt =~ m{/([^/]+)/InRelease$} or die "\nInRelease without a suite match\n"; + unless (exists $expected_hashes{$inrelease_suite}) { + die "Unconfigured hash for suite '$inrelease_suite'\n"; + } + $expected_hash = $expected_hashes{$inrelease_suite}; + } + elsif($original_uri_from_apt =~ /Release$/) { #just paranoia that apt doesn't fetch from this unchecked Release file instead + die "Got $original_uri_from_apt which is not expected"; + } + + #read back all response blocks from http method until seeing a result code that is the end of the request + while (my @child_response_block = read_block($http_child_out)) { + my $child_response_info = parse_block(@child_response_block); + + #annoyingly, on buster, the http method won't handle redirects itself and expects apt to with this 103. Allowing apt + # to handle the redirect makes it much harder to be certain we are validating the file we think we ought to be validating. + # So we'll have to deal with the redirect ourselves. + if($child_response_info->{Code} == 103) { + @command_block = map { s/^URI:.*$/URI: $child_response_info->{'New-URI'}/r } @command_block; + print $http_child_in @command_block; + } + elsif($child_response_info->{Code} < 201) { + # an "in progress" notification; forward through + print STDOUT inject_original_uri($original_uri_from_apt, @child_response_block); + } + else { + # completion message; check if this is for InRelease and verify hash, or if for any other file just forward through. + # for failure cases 'die' which stops apt in its tracks, otherwise it might ignore a failure if a local cached file is still available. + if ($child_response_info->{Code} == 201 && $expected_hash) { + if (validate_file($child_response_info->{Filename}, $expected_hash)) { + print STDOUT inject_original_uri($original_uri_from_apt, @child_response_block); + } else { + die "\nHash mismatch for $child_response_info->{URI}\n"; + } + } + else { + print STDOUT inject_original_uri($original_uri_from_apt, @child_response_block); + } + + last; + } + } +} + +close($http_child_in); +close($http_child_out); +waitpid($pid, 0); + +sub read_block($fh) { + my @lines; + return @lines unless defined(my $first_line = <$fh>); + push @lines, $first_line; + while (my $line = <$fh>) { + push @lines, $line; + last if $line eq "\n"; + } + return @lines; +} + +sub parse_block(@block) { + return {} unless @block; + my $info = {}; + if ($block[0] =~ /^(\d+)\s+(.*)/) { + $info->{Code} = $1; + $info->{Description} = $2; + } + for my $line (@block[1 .. $#block]) { + if ($line =~ /^([^:]+):\s*(.*)/) { + $info->{$1} = $2; + } + } + return $info; +} + +#responses need to go back to apt with the URL it originally sent; since we're handling redirects internally need to touch this up +sub inject_original_uri($original_uri, @response_block) { + return map { s/^URI:.*$/URI: $original_uri/r } @response_block; +} + +sub validate_file($file_path, $expected_hash) { + return 0 unless defined $file_path && -f $file_path; + + #can't use Digest::SHA as that package is not installed; call off to sha256sum instead + my ($sha_out, $sha_in); + my $sha_pid = open2($sha_out, $sha_in, 'sha256sum', $file_path); + close $sha_in; + + my $output = <$sha_out>; + close $sha_out; + waitpid($sha_pid, 0); + + return 0 if $? != 0; #command failed + return 0 unless defined $output; + + chomp $output; + my ($calculated_hash) = split /\s+/, $output; + return 0 unless defined $calculated_hash; + + return $calculated_hash eq $expected_hash; +} diff --git a/tools/reproducible.Dockerfile b/tools/reproducible.Dockerfile index 451d7febad..4322a05679 100644 --- a/tools/reproducible.Dockerfile +++ b/tools/reproducible.Dockerfile @@ -10,9 +10,19 @@ ENV SOURCE_DATE_EPOCH=1752331000 # nominally exists to ensure older versions of the package repo which may contain defective packages aren't served in the far # future. But in our case, we want this pinned package repo at any future date. So [check-valid-until=no] to disable this check. RUN DATETIMESTR=$(date -d @${SOURCE_DATE_EPOCH} +%Y%m%dT%H%M%SZ) && cat < /etc/apt/sources.list -deb [check-valid-until=no] http://snapshot.debian.org/archive/debian/${DATETIMESTR}/ buster main -deb [check-valid-until=no] http://snapshot.debian.org/archive/debian/${DATETIMESTR}/ buster-updates main -deb [check-valid-until=no] http://snapshot.debian.org/archive/debian-security/${DATETIMESTR}/ buster/updates main +deb [check-valid-until=no] pinned://snapshot.debian.org/archive/debian/${DATETIMESTR}/ buster main +deb [check-valid-until=no] pinned://snapshot.debian.org/archive/debian/${DATETIMESTR}/ buster-updates main +deb [check-valid-until=no] pinned://snapshot.debian.org/archive/debian-security/${DATETIMESTR}/ buster/updates main +EOF + +# Install the 'pinned' apt method, and define required hashes for the InRelease files of the package repos +COPY tools/pinned.pl /usr/lib/apt/methods/pinned +RUN cat < /etc/apt/apt.conf.d/99pinned.conf +Acquire::pinned::InReleaseHashes { + "buster" "d2126c57347cfe5ca81d912ddfecc02e9a741c6e100d8d8295b735f979bc1a9d"; + "buster-updates" "2efadfba571a0c888a8e0175c6f782f7a0afe18dee0e3fbcf1939931639749b8"; + "updates" "5a9bda70b67ba71088bc7576dd6ee078f75428ea6291ca7b22ac7d79a9ec73e8"; +}; EOF RUN apt-get update && apt-get -y upgrade && DEBIAN_FRONTEND=noninteractive apt-get -y install build-essential \ From aeb0383e549c66815d773dd608f77a683b0ad0bc Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Mon, 25 Aug 2025 15:21:38 -0400 Subject: [PATCH 02/13] validate LLVM & cmake tarball hashes --- tools/reproducible.Dockerfile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/reproducible.Dockerfile b/tools/reproducible.Dockerfile index 4322a05679..108b235468 100644 --- a/tools/reproducible.Dockerfile +++ b/tools/reproducible.Dockerfile @@ -58,7 +58,13 @@ RUN gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys CBA23971357C2E6590D9 D574BD5D1D0E98895E3BF90044F2485E45D59042 RUN ls *.sig *.asc | xargs -n 1 gpg --verify && \ - sha256sum -c --ignore-missing cmake-*-SHA-256.txt + sha256sum --strict -c --ignore-missing cmake-*-SHA-256.txt + +RUN sha256sum --strict -c - <<-EOF + 0b58557a6d32ceee97c8d533a59b9212d87e0fc4d2833924eb6c611247db2f2a llvm-project-${_SPRING_CLANG_VERSION}.src.tar.xz + 74d2529159fd118c3eac6f90107b5611bccc6f647fdea104024183e8d5e25831 llvm-project-${_SPRING_LLVM_VERSION}.src.tar.xz + ef3056df528569e0e8956f6cf38806879347ac6de6a4ff7e4105dc4578732cfb cmake-${_SPRING_CMAKE_VERSION}.tar.gz +EOF RUN tar xf cmake-*.tar.gz && \ cd cmake*[0-9] && \ From b18a112960c259b6ccd0a5c7c7b96adf7ed3eeda Mon Sep 17 00:00:00 2001 From: kevin Heifner Date: Tue, 2 Dec 2025 09:13:47 -0600 Subject: [PATCH 03/13] Calculate block in round correctly --- tests/TestHarness/Node.py | 19 ++++++++++++++++--- tests/TestHarness/queries.py | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/TestHarness/Node.py b/tests/TestHarness/Node.py index f37e59b44e..1262b19b81 100644 --- a/tests/TestHarness/Node.py +++ b/tests/TestHarness/Node.py @@ -281,8 +281,17 @@ def missedNextProductionRound(self): self.getInfo() currBlockNum=self.lastRetrievedHeadBlockNum currProducer=self.lastRetrievedHeadBlockProducer - blocksRemainedInCurrRound = blocksPerProducer - currBlockNum % blocksPerProducer - 1 - if Utils.Debug: Utils.Print(f'currBlockNum {currBlockNum}, currProducer {currProducer}, blocksRemainedInCurrRound {blocksRemainedInCurrRound}') + + startOfRoundBlockNum = currBlockNum + for i in range(1, currBlockNum-1): # the producer might produce multiple rounds + if self.getBlockProducerByNum(currBlockNum-i) == currProducer: + startOfRoundBlockNum = currBlockNum-i + else: + break + + currBlockInRound = ( (currBlockNum - startOfRoundBlockNum) % blocksPerProducer ) + 1 + blocksRemainedInCurrRound = blocksPerProducer - currBlockInRound + if Utils.Debug: Utils.Print(f'currBlockNum {currBlockNum}, currProducer {currProducer}, blocksRemainedInCurrRound {blocksRemainedInCurrRound}, currBlockInRound {currBlockInRound}') # find the positions of currProducerPos and nodeProducer in the schedule currProducerPos=0 @@ -310,7 +319,11 @@ def missedNextProductionRound(self): timeout=blocksToNextScheduledRound/2 + 2 # leave 2 seconds for avoid flakiness if Utils.Debug: Utils.Print(f'blocksToNextScheduledRound {blocksToNextScheduledRound}, nextScheduledRoundBlockNum {nextScheduledRoundBlockNum}, timeout {timeout}') - return not self.waitForBlock(nextScheduledRoundBlockNum, timeout=timeout) + if not self.waitForBlock(nextScheduledRoundBlockNum, timeout=timeout): + return True + if self.getBlockProducer() != self.producerName: + return True + return False def killNodeOnProducer(self, producer, whereInSequence, blockType=BlockType.head, silentErrors=True, exitOnError=False, exitMsg=None, returnType=ReturnType.json): assert(isinstance(producer, str)) diff --git a/tests/TestHarness/queries.py b/tests/TestHarness/queries.py index 4a340b4cd2..89b91cbeda 100644 --- a/tests/TestHarness/queries.py +++ b/tests/TestHarness/queries.py @@ -718,7 +718,7 @@ def getBlockProducerByNum(self, blockNum, timeout=None, waitForBlock=True, exitO def getBlockProducer(self, timeout=None, waitForBlock=True, exitOnError=True, blockType=BlockType.head): blockNum=self.getBlockNum(blockType=blockType) - block=self.getBlock(blockNum, exitOnError=exitOnError, blockType=blockType) + block=self.getBlock(blockNum, exitOnError=exitOnError) if block is None: if exitOnError: Utils.errorExit(f"getBlock returned None for {blockNum}") From 4cb5fdc6855d921804fd247da42139cb5b864e4d Mon Sep 17 00:00:00 2001 From: kevin Heifner Date: Tue, 2 Dec 2025 21:29:32 -0600 Subject: [PATCH 04/13] Simplify and make more robust --- tests/TestHarness/Node.py | 54 ++++++--------------------------------- 1 file changed, 8 insertions(+), 46 deletions(-) diff --git a/tests/TestHarness/Node.py b/tests/TestHarness/Node.py index 1262b19b81..32e99be29c 100644 --- a/tests/TestHarness/Node.py +++ b/tests/TestHarness/Node.py @@ -278,52 +278,14 @@ def missedNextProductionRound(self): scheduled_producers.append(prod["producer_name"]) if Utils.Debug: Utils.Print(f'scheduled_producers {scheduled_producers}') - self.getInfo() - currBlockNum=self.lastRetrievedHeadBlockNum - currProducer=self.lastRetrievedHeadBlockProducer - - startOfRoundBlockNum = currBlockNum - for i in range(1, currBlockNum-1): # the producer might produce multiple rounds - if self.getBlockProducerByNum(currBlockNum-i) == currProducer: - startOfRoundBlockNum = currBlockNum-i - else: - break - - currBlockInRound = ( (currBlockNum - startOfRoundBlockNum) % blocksPerProducer ) + 1 - blocksRemainedInCurrRound = blocksPerProducer - currBlockInRound - if Utils.Debug: Utils.Print(f'currBlockNum {currBlockNum}, currProducer {currProducer}, blocksRemainedInCurrRound {blocksRemainedInCurrRound}, currBlockInRound {currBlockInRound}') - - # find the positions of currProducerPos and nodeProducer in the schedule - currProducerPos=0 - nodeProducerPos=0 - for i in range(0, len(scheduled_producers)): - if scheduled_producers[i] == currProducer: - currProducerPos=i - if scheduled_producers[i] == self.producerName: - nodeProducerPos=i - - # find the number of the blocks to node producer's next scheduled round - blocksToNextScheduledRound = 0 - if currProducerPos < nodeProducerPos: - # nodeProducerPos - currProducerPos - 1 is the number of producers - # from current producer to the node producer in the schedule - blocksToNextScheduledRound = (nodeProducerPos - currProducerPos - 1) * blocksPerProducer + blocksRemainedInCurrRound + 1 - else: - # nodeProducerPos is the number of producers before node producer in the schedule - # len(scheduled_producers) - currProducerPos - 1 is the number - # of producers after node producer in the schedule - blocksToNextScheduledRound = (nodeProducerPos + (len(scheduled_producers) - currProducerPos - 1)) * blocksPerProducer + blocksRemainedInCurrRound + 1 - - # find the block number of the node producer's next scheduled round - nextScheduledRoundBlockNum=currBlockNum + blocksToNextScheduledRound - timeout=blocksToNextScheduledRound/2 + 2 # leave 2 seconds for avoid flakiness - if Utils.Debug: Utils.Print(f'blocksToNextScheduledRound {blocksToNextScheduledRound}, nextScheduledRoundBlockNum {nextScheduledRoundBlockNum}, timeout {timeout}') - - if not self.waitForBlock(nextScheduledRoundBlockNum, timeout=timeout): - return True - if self.getBlockProducer() != self.producerName: - return True - return False + for i in range(0, len(scheduled_producers)*blocksPerProducer): + if not self.waitForNextBlock(timeout=13): + if Utils.Debug: Utils.Print(f'Failed to get next block') + return True + if self.getBlockProducer() == self.producerName: + if Utils.Debug: Utils.Print(f'{self.producerName} produced block {self.lastRetrievedHeadBlockNum}') + return False + return True def killNodeOnProducer(self, producer, whereInSequence, blockType=BlockType.head, silentErrors=True, exitOnError=False, exitMsg=None, returnType=ReturnType.json): assert(isinstance(producer, str)) From b2c54b7bd31acdc35d5eaf5bcdf20d58357f0e2f Mon Sep 17 00:00:00 2001 From: kevin Heifner Date: Thu, 4 Dec 2025 09:55:09 -0600 Subject: [PATCH 05/13] Avoid undefined behavior --- libraries/chain/include/eosio/chain/wasm_eosio_injection.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/chain/include/eosio/chain/wasm_eosio_injection.hpp b/libraries/chain/include/eosio/chain/wasm_eosio_injection.hpp index 020a4ad202..b9d4b0fc77 100644 --- a/libraries/chain/include/eosio/chain/wasm_eosio_injection.hpp +++ b/libraries/chain/include/eosio/chain/wasm_eosio_injection.hpp @@ -151,7 +151,8 @@ namespace eosio { namespace chain { namespace wasm_injections { static constexpr bool post = false; static void init() {} static void accept( wasm_ops::instr* inst, wasm_ops::visitor_arg& arg ) { - wasm_ops::op_types<>::call_t* call_inst = reinterpret_cast::call_t*>(inst); + // Cast to the exact dynamic type to avoid undefined behavior + auto* call_inst = static_cast*>(inst); auto mapped_index = injector_utils::injected_index_mapping.find(call_inst->field); if ( mapped_index != injector_utils::injected_index_mapping.end() ) { From 84be93c29b2a78d7203d66191c435fdcac7302dd Mon Sep 17 00:00:00 2001 From: kevin Heifner Date: Wed, 3 Dec 2025 15:28:19 -0600 Subject: [PATCH 06/13] Wait for block 2 otherwise block 1 can have a very old timestamp which means expiration of trx will not be valid --- tests/cli_test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/cli_test.py b/tests/cli_test.py index 74e730e60c..b0aa8f56bc 100755 --- a/tests/cli_test.py +++ b/tests/cli_test.py @@ -357,8 +357,10 @@ def abi_file_with_nodeos_test(): walletMgr.launch() cmd = "./programs/nodeos/nodeos -e -p eosio --plugin eosio::trace_api_plugin --trace-no-abis --plugin eosio::producer_plugin --plugin eosio::producer_api_plugin --plugin eosio::chain_api_plugin --plugin eosio::chain_plugin --plugin eosio::http_plugin --access-control-allow-origin=* --http-validate-host=false --max-transaction-time=-1 --resource-monitor-not-shutdown-on-threshold-exceeded " + "--data-dir " + data_dir + " --config-dir " + data_dir node = Node('localhost', 8888, nodeId, data_dir=Path(data_dir), config_dir=Path(data_dir), cmd=shlex.split(cmd), launch_time=datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S'), walletMgr=walletMgr) - time.sleep(5) - node.waitForBlock(1) + if not node or not Utils.waitForBool(node.checkPulse, timeout=15): + Utils.Print("ERROR: node doesn't appear to be running...") + assert False, "node doesn't appear to be running" + node.waitForBlock(2) accountNames = ["eosio", "eosio.token", "alice", "bob"] accounts = [] for name in accountNames: From 5cc99c9be9a2667956affd4a9d0c4af6509f760d Mon Sep 17 00:00:00 2001 From: kevin Heifner Date: Thu, 4 Dec 2025 10:51:47 -0600 Subject: [PATCH 07/13] Support multiple threads writing to subprocess_results.log --- tests/TestHarness/testUtils.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/TestHarness/testUtils.py b/tests/TestHarness/testUtils.py index 7b202c6318..d6b593371f 100644 --- a/tests/TestHarness/testUtils.py +++ b/tests/TestHarness/testUtils.py @@ -17,6 +17,7 @@ import shutil import sys from pathlib import Path +import threading ########################################################################################### @@ -82,6 +83,8 @@ class Utils: ConfigDir=f"{DataPath}/" TimeFmt='%Y-%m-%dT%H:%M:%S.%f' + # lock to serialize writes to subprocess_results.log across threads + _check_output_lock = threading.Lock() @staticmethod def timestamp(): @@ -92,19 +95,20 @@ def checkOutputFileWrite(time, cmd, output, error): stop=Utils.timestamp() os.makedirs(Utils.TestLogRoot, exist_ok=True) os.makedirs(Utils.DataPath, exist_ok=True) - if not hasattr(Utils, "checkOutputFile"): + + # Ensure filename is set + if not hasattr(Utils, "checkOutputFilename"): Utils.checkOutputFilename=f"{Utils.DataPath}/subprocess_results.log" - if Utils.Debug: Utils.Print("opening %s in dir: %s" % (Utils.checkOutputFilename, os.getcwd())) - Utils.checkOutputFile=open(Utils.checkOutputFilename,"w") - else: - Utils.checkOutputFile=open(Utils.checkOutputFilename,"a") - - Utils.checkOutputFile.write(Utils.FileDivider + "\n") - Utils.checkOutputFile.write("start={%s}\n" % (time)) - Utils.checkOutputFile.write("cmd={%s}\n" % (" ".join(cmd))) - Utils.checkOutputFile.write("cout={%s}\n" % (output)) - Utils.checkOutputFile.write("cerr={%s}\n" % (error)) - Utils.checkOutputFile.write("stop={%s}\n" % (stop)) + + # Serialize concurrent writes and open file per write to avoid sharing closed handles + with Utils._check_output_lock: + with open(Utils.checkOutputFilename, "a") as f: + f.write(Utils.FileDivider + "\n") + f.write("start={%s}\n" % (time)) + f.write("cmd={%s}\n" % (" ".join(cmd))) + f.write("cout={%s}\n" % (output)) + f.write("cerr={%s}\n" % (error)) + f.write("stop={%s}\n" % (stop)) @staticmethod def Print(*args, **kwargs): From 6df56202e06a2303b2326bacfdfd8032843b9f8e Mon Sep 17 00:00:00 2001 From: kevin Heifner Date: Thu, 4 Dec 2025 12:17:54 -0600 Subject: [PATCH 08/13] Hold lock for Utils.checkOutputFilename access --- tests/TestHarness/testUtils.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/TestHarness/testUtils.py b/tests/TestHarness/testUtils.py index d6b593371f..6fe1ed1cbb 100644 --- a/tests/TestHarness/testUtils.py +++ b/tests/TestHarness/testUtils.py @@ -93,15 +93,15 @@ def timestamp(): @staticmethod def checkOutputFileWrite(time, cmd, output, error): stop=Utils.timestamp() - os.makedirs(Utils.TestLogRoot, exist_ok=True) - os.makedirs(Utils.DataPath, exist_ok=True) - - # Ensure filename is set - if not hasattr(Utils, "checkOutputFilename"): - Utils.checkOutputFilename=f"{Utils.DataPath}/subprocess_results.log" - # Serialize concurrent writes and open file per write to avoid sharing closed handles with Utils._check_output_lock: + os.makedirs(Utils.TestLogRoot, exist_ok=True) + os.makedirs(Utils.DataPath, exist_ok=True) + + # Ensure filename is set + if not hasattr(Utils, "checkOutputFilename"): + Utils.checkOutputFilename=f"{Utils.DataPath}/subprocess_results.log" + with open(Utils.checkOutputFilename, "a") as f: f.write(Utils.FileDivider + "\n") f.write("start={%s}\n" % (time)) From 378a27a064345cbc0ea7a130c5348a86a07b698c Mon Sep 17 00:00:00 2001 From: kevin Heifner Date: Fri, 5 Dec 2025 09:47:48 -0600 Subject: [PATCH 09/13] It is possible due to an interrupt that the controller has stopped applying blocks. Give it a kick to make sure it continues. --- plugins/net_plugin/net_plugin.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index 03794c5ed4..aa084b01da 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -2178,6 +2178,10 @@ namespace eosio { fc_dlog(p2p_blk_log, "sync ahead not allowed. block ${bn}, head ${h}, fhead ${fh}, fhead->lib ${fl}, sync-fetch-span ${sp}, fork_db size ${s}", ("bn", blk_num)("h", head_num)("fh", cc.fork_db_head().block_num())("fl", cc.fork_db_head().irreversible_blocknum()) ("sp", sync_fetch_span)("s", cc.fork_db_size())); + + // make sure controller is processing blocks, might have been interrupted and need a kick + fc_dlog(p2p_blk_log, "sync post process_incoming_block to app thread, block ${n}", ("n", blk_num)); + my_impl->producer_plug->process_blocks(); } fc_dlog(p2p_blk_log, "sync ahead not allowed. block ${bn}, sync_last_requested_num ${lrn}, sync-fetch-span ${s}", From 543f15044f5ba302c960ef560cd6adcb7122ce46 Mon Sep 17 00:00:00 2001 From: kevin Heifner Date: Wed, 10 Dec 2025 09:15:03 -0600 Subject: [PATCH 10/13] Do not oc interrupt during replay. --- libraries/chain/controller.cpp | 4 ++++ libraries/chain/include/eosio/chain/controller.hpp | 2 ++ .../chain/include/eosio/chain/wasm_interface_private.hpp | 5 ++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 02682db1ea..f95c0069f4 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -5522,6 +5522,10 @@ void controller::set_disable_replay_opts( bool v ) { my->conf.disable_replay_opts = v; } +bool controller::is_replaying() const { + return my->replaying; +} + block_handle controller::head()const { return my->chain_head; } diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index cdeb3ea939..9d2b2822b0 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -286,6 +286,8 @@ namespace eosio::chain { void set_key_blacklist( const flat_set& ); void set_disable_replay_opts( bool v ); + // thread safe + bool is_replaying() const; block_handle head()const; block_handle fork_db_head()const; diff --git a/libraries/chain/include/eosio/chain/wasm_interface_private.hpp b/libraries/chain/include/eosio/chain/wasm_interface_private.hpp index b17176f5ab..4fd1151c65 100644 --- a/libraries/chain/include/eosio/chain/wasm_interface_private.hpp +++ b/libraries/chain/include/eosio/chain/wasm_interface_private.hpp @@ -171,7 +171,10 @@ struct eosvmoc_tier { // Not allowing interrupt for onblock seems rather harmless, so instead of distinguishing between onerror and // onblock, just disallow for all implicit. const bool allow_oc_interrupt = attempt_tierup && context.is_applying_block() && - context.trx_context.has_undo() && !context.trx_context.is_implicit() && !context.trx_context.is_scheduled(); + context.trx_context.has_undo() && + !context.trx_context.is_implicit() && + !context.trx_context.is_scheduled() && + !context.control.is_replaying(); auto ex = fc::make_scoped_exit([&]() { if (allow_oc_interrupt) { eos_vm_oc_compile_interrupt = false; From c72085bb6902d8cf05f78c6ead81f3e990ffc65f Mon Sep 17 00:00:00 2001 From: Tobias Date: Fri, 1 May 2026 12:44:16 -0400 Subject: [PATCH 11/13] Bootstrap TelosZero private staging --- .github/CODEOWNERS | 1 + .github/workflows/bootstrap-checks.yaml | 46 +++++ .github/workflows/build.yaml | 28 ++- .github/workflows/build_base.yaml | 8 +- .github/workflows/jiraIssueCreator.yml | 42 +--- .github/workflows/label_new_issues.yaml | 20 +- .github/workflows/release.yaml | 18 +- .gitignore | 3 + CMakeLists.txt | 23 ++- CONTRIBUTING.md | 37 ++++ GOVERNANCE.md | 52 +++++ LEGAL.md | 35 ++++ MAINTAINERS.md | 32 +++ PATCHES.md | 23 +++ README.md | 258 +++++++++--------------- SECURITY.md | 28 +++ SUPPORT.md | 26 +++ package.cmake | 34 +++- tools/reproducible.Dockerfile | 2 +- 19 files changed, 461 insertions(+), 255 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 .github/workflows/bootstrap-checks.yaml create mode 100644 CONTRIBUTING.md create mode 100644 GOVERNANCE.md create mode 100644 LEGAL.md create mode 100644 MAINTAINERS.md create mode 100644 PATCHES.md create mode 100644 SECURITY.md create mode 100644 SUPPORT.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..f0c31a3aaf --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @telosnetwork/telos-core-devs diff --git a/.github/workflows/bootstrap-checks.yaml b/.github/workflows/bootstrap-checks.yaml new file mode 100644 index 0000000000..f220d2f1a4 --- /dev/null +++ b/.github/workflows/bootstrap-checks.yaml @@ -0,0 +1,46 @@ +name: Bootstrap Checks + +on: + push: + branches: + - main + - "bootstrap/**" + - "release/**" + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + static: + name: Static checks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: false + + - name: Check shell scripts + run: | + bash -n tools/tweak-deb.sh + sh -n scripts/postinst + sh -n scripts/prerm + + - name: Check Perl scripts + run: | + perl -c tools/pinned.pl + + - name: Check Python syntax + run: | + python3 -m py_compile \ + tests/TestHarness/Node.py \ + tests/TestHarness/queries.py \ + tests/TestHarness/testUtils.py \ + tests/cli_test.py + + - name: Check package naming + run: | + grep -Fq 'project( teloszero-core )' CMakeLists.txt + grep -Fq 'CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/TelosNetwork/teloszero-core"' package.cmake + grep -Fq 'teloszero-core_*.deb' tools/reproducible.Dockerfile diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 6df61c28ff..3e1d00178e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,11 +1,9 @@ name: "Build & Test" +# This workflow is inherited from Spring and still requires Telos-owned +# self-hosted runners plus a platform cache workflow. Keep it manual until +# those resources are configured for TelosZero. on: - push: - branches: - - main - - "release/*" - pull_request: workflow_dispatch: inputs: override-cdt: @@ -101,12 +99,12 @@ jobs: zstdcat build.tar.zst | tar x cd build cpack - ../tools/tweak-deb.sh antelope-spring_*.deb + ../tools/tweak-deb.sh teloszero-core_*.deb - name: Install dev package if: matrix.platform != 'reproducible' run: | apt-get update && apt-get upgrade -y - apt-get install -y ./build/antelope-spring_*.deb ./build/antelope-spring-dev*.deb + apt-get install -y ./build/teloszero-core_*.deb ./build/teloszero-core-dev*.deb - name: Test using TestHarness if: matrix.platform != 'reproducible' run: | @@ -115,15 +113,15 @@ jobs: uses: actions/upload-artifact@v4 if: matrix.platform != 'reproducible' with: - name: antelope-spring-dev-${{matrix.platform}}-amd64 - path: build/antelope-spring-dev*.deb + name: teloszero-core-dev-${{matrix.platform}}-amd64 + path: build/teloszero-core-dev*.deb compression-level: 0 - - name: Upload spring package + - name: Upload TelosZero package uses: actions/upload-artifact@v4 if: matrix.platform == 'reproducible' with: - name: antelope-spring-deb-amd64 - path: build/antelope-spring_*.deb + name: teloszero-core-deb-amd64 + path: build/teloszero-core_*.deb compression-level: 0 tests: @@ -302,12 +300,12 @@ jobs: run: | rm -r * - if: ${{ matrix.test == 'deb-install' }} - name: Download antelope-spring-dev + name: Download teloszero-core-dev uses: actions/download-artifact@v4 with: - name: antelope-spring-dev-${{matrix.platform}}-amd64 + name: teloszero-core-dev-${{matrix.platform}}-amd64 - if: ${{ matrix.test == 'deb-install' }} - name: Install antelope-spring-dev Package + name: Install teloszero-core-dev Package run: | apt-get install -y ./*.deb rm ./*.deb diff --git a/.github/workflows/build_base.yaml b/.github/workflows/build_base.yaml index 49c8e2fd06..413349e7c3 100644 --- a/.github/workflows/build_base.yaml +++ b/.github/workflows/build_base.yaml @@ -1,4 +1,4 @@ -name: "Build spring" +name: "Build TelosZero" on: workflow_call: @@ -22,7 +22,7 @@ defaults: jobs: Build: - name: Build spring + name: Build TelosZero strategy: fail-fast: false matrix: @@ -38,7 +38,7 @@ jobs: run: | # https://github.com/actions/runner/issues/2033 chown -R $(id -u):$(id -g) $PWD - cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_SPRING_DEV_DEB=On ${SPRING_PLATFORM_HAS_EXTRAS_CMAKE:+-C /extras.cmake} -GNinja + cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_TELOSZERO_DEV_DEB=On ${SPRING_PLATFORM_HAS_EXTRAS_CMAKE:+-C /extras.cmake} -GNinja cmake --build build tar -pc --exclude "*.o" build | zstd --long -T0 -9 > build.tar.zst - name: Upload builddir @@ -46,4 +46,4 @@ jobs: with: name: ${{matrix.platform}}-build path: build.tar.zst - compression-level: 0 \ No newline at end of file + compression-level: 0 diff --git a/.github/workflows/jiraIssueCreator.yml b/.github/workflows/jiraIssueCreator.yml index e4b6359b6c..d485929c30 100644 --- a/.github/workflows/jiraIssueCreator.yml +++ b/.github/workflows/jiraIssueCreator.yml @@ -1,42 +1,12 @@ name: Jira Issue Creator + on: - issues: - types: - - labeled + workflow_dispatch: +# Inherited from Spring. This placeholder keeps the workflow name visible while +# Telos-owned issue automation is configured. jobs: - create-jira-issue: + disabled: 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 }} + - run: echo "Jira automation is disabled during TelosZero bootstrap." diff --git a/.github/workflows/label_new_issues.yaml b/.github/workflows/label_new_issues.yaml index a41254664e..671a0004a5 100644 --- a/.github/workflows/label_new_issues.yaml +++ b/.github/workflows/label_new_issues.yaml @@ -1,18 +1,12 @@ name: Label New Issue on: - issues: - types: opened + workflow_dispatch: +# Inherited from Spring. This placeholder keeps the workflow name visible while +# Telos-owned project labeling is configured. 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 - skip-if-existing-project: true - secrets: - token: ${{secrets.ENFCIBOT_REPO_AND_PROJECTS}} - + disabled: + runs-on: ubuntu-latest + steps: + - run: echo "Issue labeling automation is disabled during TelosZero bootstrap." diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0db8e648ed..e45ef5857b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -13,29 +13,29 @@ jobs: packages: write actions: read steps: - - name: Get ubuntu20 antelope-spring-dev.deb + - name: Get ubuntu20 teloszero-core-dev.deb uses: AntelopeIO/asset-artifact-download-action@v3 with: owner: ${{github.repository_owner}} repo: ${{github.event.repository.name}} - file: 'antelope-spring-dev.*amd64.deb' + file: 'teloszero-core-dev.*amd64.deb' target: ${{github.sha}} - artifact-name: antelope-spring-dev-ubuntu20-amd64 + artifact-name: teloszero-core-dev-ubuntu20-amd64 wait-for-exact-target: true - - name: Get ubuntu22 antelope-spring-dev.deb + - name: Get ubuntu22 teloszero-core-dev.deb uses: AntelopeIO/asset-artifact-download-action@v3 with: owner: ${{github.repository_owner}} repo: ${{github.event.repository.name}} - file: 'antelope-spring-dev.*amd64.deb' + file: 'teloszero-core-dev.*amd64.deb' target: ${{github.sha}} - artifact-name: antelope-spring-dev-ubuntu22-amd64 + artifact-name: teloszero-core-dev-ubuntu22-amd64 wait-for-exact-target: true - name: Create Dockerfile run: | cat < Dockerfile FROM scratch - LABEL org.opencontainers.image.description="A collection of experimental Spring binary packages" + LABEL org.opencontainers.image.description="A collection of experimental TelosZero Core binary packages" COPY *.deb / EOF - name: Login to ghcr @@ -45,9 +45,9 @@ jobs: username: ${{github.repository_owner}} password: ${{github.token}} - run: echo "REPOSITORY_OWNER_LOWER=${GITHUB_REPOSITORY_OWNER,,}" >> "${GITHUB_ENV}" - - name: Build and push antelope-spring-experimental-binaries + - name: Build and push teloszero-core-experimental-binaries uses: docker/build-push-action@v5 with: push: true - tags: ghcr.io/${{env.REPOSITORY_OWNER_LOWER}}/antelope-spring-experimental-binaries:${{github.ref_name}} + tags: ghcr.io/${{env.REPOSITORY_OWNER_LOWER}}/teloszero-core-experimental-binaries:${{github.ref_name}} context: . diff --git a/.gitignore b/.gitignore index bb757e42d0..6269ace926 100644 --- a/.gitignore +++ b/.gitignore @@ -93,3 +93,6 @@ package-lock.json snapshots !unittests/snapshots + +teloszero-core-*.tar.zst +teloszero-core_*.deb diff --git a/CMakeLists.txt b/CMakeLists.txt index 820d4c33b7..afa9342230 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required( VERSION 3.16 ) -project( antelope-spring ) +project( teloszero-core ) include(CTest) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") @@ -66,7 +66,7 @@ if(ENABLE_OC AND CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32) # can be created with the exact version found find_package(LLVM REQUIRED CONFIG) if(LLVM_VERSION_MAJOR VERSION_LESS 7 OR LLVM_VERSION_MAJOR VERSION_GREATER_EQUAL 12) - message(FATAL_ERROR "Spring requires an LLVM version 7 through 11") + message(FATAL_ERROR "TelosZero requires an LLVM version 7 through 11") endif() endif() endif() @@ -94,12 +94,12 @@ endif() if( APPLE AND UNIX ) # Apple Specific Options Here - message( STATUS "Configuring Spring on macOS" ) + message( STATUS "Configuring TelosZero on macOS" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-deprecated-declarations" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-deprecated-declarations" ) else() # Linux Specific Options Here - message( STATUS "Configuring Spring on Linux" ) + message( STATUS "Configuring TelosZero on Linux" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" ) if ( FULL_STATIC_BUILD ) @@ -129,13 +129,13 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_ set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wthread-safety" ) endif() -option(EOSIO_ENABLE_DEVELOPER_OPTIONS "enable developer options for Spring" OFF) +option(EOSIO_ENABLE_DEVELOPER_OPTIONS "enable developer options for TelosZero" OFF) # based on http://www.delorie.com/gnu/docs/gdb/gdb_70.html # uncomment this line to tell GDB about macros (slows compile times) # set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -gdwarf-2 -g3" ) -set(ENABLE_COVERAGE_TESTING FALSE CACHE BOOL "Build Spring for code coverage analysis") +set(ENABLE_COVERAGE_TESTING FALSE CACHE BOOL "Build TelosZero for code coverage analysis") if(ENABLE_COVERAGE_TESTING) SET(CMAKE_C_FLAGS "--coverage ${CMAKE_C_FLAGS}") @@ -168,7 +168,7 @@ message( STATUS "Using '${EOSIO_ROOT_KEY}' as public key for 'eosio' account" ) option(ENABLE_TCMALLOC "use tcmalloc (requires gperftools)" OFF) if( ENABLE_TCMALLOC ) find_package( Gperftools REQUIRED ) - message( STATUS "Compiling Spring with TCMalloc") + message( STATUS "Compiling TelosZero with TCMalloc") #if doing this by the book, simply link_libraries( ${GPERFTOOLS_TCMALLOC} ) here. That will #give the performance benefits of tcmalloc but since it won't be linked last #the heap profiler & checker may not be accurate. This here is rather undocumented behavior @@ -177,7 +177,7 @@ if( ENABLE_TCMALLOC ) set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} ${GPERFTOOLS_TCMALLOC}") endif() -# spring includes a bundled BoringSSL which conflicts with OpenSSL. Make sure any other bundled libraries (such as boost) +# TelosZero includes a bundled BoringSSL which conflicts with OpenSSL. Make sure any other bundled libraries (such as boost) # do not attempt to use an external OpenSSL in any manner set(CMAKE_DISABLE_FIND_PACKAGE_OpenSSL On) @@ -212,7 +212,7 @@ configure_file(${CMAKE_SOURCE_DIR}/CMakeModules/EosioCheckVersion.cmake ${CMAKE_ configure_file(${CMAKE_SOURCE_DIR}/CMakeModules/leap-config.cmake.in ${CMAKE_BINARY_DIR}/lib/cmake/leap/leap-config.cmake @ONLY) configure_file(${CMAKE_SOURCE_DIR}/CMakeModules/EosioTesterBuild.cmake.in ${CMAKE_BINARY_DIR}/lib/cmake/leap/EosioTester.cmake @ONLY) configure_file(${CMAKE_SOURCE_DIR}/CMakeModules/EosioCheckVersion.cmake ${CMAKE_BINARY_DIR}/lib/cmake/leap/EosioCheckVersion.cmake COPYONLY) -# spring CMake files +# spring-compatible CMake files configure_file(${CMAKE_SOURCE_DIR}/CMakeModules/spring-config.cmake.in ${CMAKE_BINARY_DIR}/lib/cmake/spring/spring-config.cmake @ONLY) configure_file(${CMAKE_SOURCE_DIR}/CMakeModules/EosioTesterBuild.cmake.in ${CMAKE_BINARY_DIR}/lib/cmake/spring/EosioTester.cmake @ONLY) configure_file(${CMAKE_SOURCE_DIR}/CMakeModules/EosioCheckVersion.cmake ${CMAKE_BINARY_DIR}/lib/cmake/spring/EosioCheckVersion.cmake COPYONLY) @@ -229,7 +229,7 @@ configure_file(${CMAKE_SOURCE_DIR}/CMakeModules/leap-config.cmake.in ${CMAKE_BIN install(FILES ${CMAKE_BINARY_DIR}/modules/leap-config.cmake DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/leap COMPONENT dev EXCLUDE_FROM_ALL) 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) -# spring CMake files +# spring-compatible CMake files configure_file(${CMAKE_SOURCE_DIR}/CMakeModules/spring-config.cmake.in ${CMAKE_BINARY_DIR}/modules/spring-config.cmake @ONLY) install(FILES ${CMAKE_BINARY_DIR}/modules/spring-config.cmake DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/spring COMPONENT dev EXCLUDE_FROM_ALL) install(FILES ${CMAKE_BINARY_DIR}/modules/EosioTester.cmake DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/spring COMPONENT dev EXCLUDE_FROM_ALL) @@ -313,7 +313,8 @@ add_custom_target(dev-install include(doxygen) -option(ENABLE_SPRING_DEV_DEB "Enable building the spring-dev .deb package" OFF) +option(ENABLE_TELOSZERO_DEV_DEB "Enable building the teloszero-core-dev .deb package" OFF) +option(ENABLE_SPRING_DEV_DEB "Compatibility alias for ENABLE_TELOSZERO_DEV_DEB" OFF) include(package.cmake) include(CPack) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..2dfc7181dd --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,37 @@ +# Contributing + +TelosZero Core is private during bootstrap. Contributions should go through pull +requests against `main` or a documented release branch. + +## Development Rules + +- Keep changes narrowly scoped. +- Preserve upstream attribution when cherry-picking. +- Do not make consensus or storage-format changes without a design note. +- Keep `nodeos`, `cleos`, and `keosd` compatibility unless a release plan says + otherwise. +- Update packaging and operator docs when behavior affects installation, + upgrades, or runtime configuration. + +## Commit And PR Expectations + +Pull requests should include: + +- a short summary +- compatibility impact +- tests run +- upstream or Community Edition references, if any + +For cherry-picks, include the source commit or PR URL in the PR description. + +## Local Verification + +At minimum, run syntax checks before opening a PR: + +```bash +bash -n tools/tweak-deb.sh +sh -n scripts/postinst +sh -n scripts/prerm +perl -c tools/pinned.pl +python3 -m py_compile tests/TestHarness/Node.py tests/TestHarness/queries.py tests/TestHarness/testUtils.py tests/cli_test.py +``` diff --git a/GOVERNANCE.md b/GOVERNANCE.md new file mode 100644 index 0000000000..4ce63b3d0c --- /dev/null +++ b/GOVERNANCE.md @@ -0,0 +1,52 @@ +# Governance + +TelosZero Core is maintained under the TelosNetwork GitHub organization. + +## Bootstrap Phase + +This repository is private while the project is being prepared for public use. +During bootstrap, maintainers should prioritize: + +- preserving upstream history and attribution +- keeping runtime behavior compatible unless a change is explicitly reviewed as a + protocol change +- documenting licensing provenance before any production release +- replacing inherited CI, release, and signing infrastructure with Telos-owned + equivalents +- publishing reproducible, signed artifacts before recommending operator use + +## Maintainer Authority + +Maintainers are responsible for reviewing code, release artifacts, security +updates, and public communications. No single maintainer should be the only +person able to merge, release, or administer the repository. + +The initial code owner team is `@telosnetwork/telos-core-devs`. + +## Branch Policy + +`main` is the development branch. + +Production release branches should use the `release/teloszero-*` naming pattern. +Release branches require: + +- a documented release plan +- passing CI for build and test targets selected for that release +- maintainer approval +- signed tags and checksums +- upgrade and rollback notes for node operators + +## Protocol Changes + +Consensus, serialization, database format, protocol feature, and network +compatibility changes require an explicit design note before implementation. +The design note should state expected compatibility, activation requirements, +test coverage, and operator impact. + +## Upstream And Community Edition Changes + +`AntelopeIO/spring` is tracked as `upstream`. The Spring Community Edition is +tracked as `ce` only as a reference source for legal/process cues and useful +patches. Changes from either source should be reviewed and merged intentionally; +bulk imports should be avoided unless they are part of a documented release +sync. diff --git a/LEGAL.md b/LEGAL.md new file mode 100644 index 0000000000..de232c25d6 --- /dev/null +++ b/LEGAL.md @@ -0,0 +1,35 @@ +# Legal And Licensing Notes + +This repository is a private TelosNetwork staging continuation of +`AntelopeIO/spring`. + +## Current Bootstrap Base + +The bootstrap base is upstream Spring `main` at commit: + +```text +e6a99f68b67abc4d89fe716755b2e1394a4991f7 +``` + +That commit updates the upstream `LICENSE` file to MIT terms. The existing +upstream copyright notices are preserved. + +## Older Branches And Tags + +Historical Spring branches and tags are preserved for auditability. Some older +release branches and tags may contain different license terms. Do not publish +TelosZero production binaries from those branches until their license status is +reviewed and documented. + +## Community Edition + +The Spring Community Edition repository is used only as a reference source for +process cues and candidate patches. TelosZero Core does not inherit the +Community Edition package rename or release tags unless maintainers explicitly +merge those changes. + +## Trademarks + +TelosZero maintainers should avoid implying endorsement by upstream Spring, +AntelopeIO, EOS Network Foundation, Vaulta Foundation, or other projects unless +that endorsement has been explicitly granted. diff --git a/MAINTAINERS.md b/MAINTAINERS.md new file mode 100644 index 0000000000..e79a875080 --- /dev/null +++ b/MAINTAINERS.md @@ -0,0 +1,32 @@ +# Maintainers + +Initial code ownership is assigned to: + +- `@telosnetwork/telos-core-devs` + +Before this repository is made public, confirm: + +- at least two maintainers have admin or maintain access +- branch protection is enabled for `main` and release branches +- release signing keys and recovery procedures are documented +- security reporting is enabled and monitored + +## Maintainer Expectations + +Maintainers should: + +- review protocol-affecting changes with extra care +- preserve attribution when cherry-picking from Spring or Community Edition +- keep package and release provenance clear +- avoid force-pushing shared branches +- use pull requests for changes intended for `main` or release branches + +## Release Roles + +Each production release should identify: + +- release owner +- build/reproducibility verifier +- test verifier +- security reviewer +- operator communications owner diff --git a/PATCHES.md b/PATCHES.md new file mode 100644 index 0000000000..7685dc2a2a --- /dev/null +++ b/PATCHES.md @@ -0,0 +1,23 @@ +# Patch Provenance + +This file records bootstrap patches imported after the initial +`AntelopeIO/spring` `main` mirror. + +## Bootstrap Cherry-Picks + +The following commits were cherry-picked from upstream Spring branches or the +Spring Community Edition history because they were already proposed upstream and +address reproducibility, test stability, or runtime stability: + +- `4c510d62d7c94df108c640b8a952d833a8d86d6c` - validate hash of pinned package repo +- `4f325af99cb87ddaad28040ec78f39f58e8672f8` - validate LLVM and CMake tarball hashes +- `4a927beeb8eb04d9d8ca196a8f8ed1f5852fd677` - calculate block in round correctly +- `8521492403d02446a8d422fed1c8ff550dae36d3` - simplify and make production-round test more robust +- `e190658864d4d21565a626e7d8ca38fdd5023e7e` - avoid undefined behavior in WASM injection +- `96fce4255754ad18aa9af008a1e0bcea6752f128` - wait for block 2 in CLI test +- `b6c36a0abd98cfe4b6e71cbc99e410e66d0b6d1b` - support multiple threads writing subprocess logs +- `f4824016fdfabb5ddb48db385ff6037c91d654ad` - hold log filename lock during access +- `6e77b88e8b56183416559b6b679256f9fa786e2c` - signal controller to apply blocks if sync is interrupted +- `96bcb7544e3ac92fb7696cfed9c9052a4ed02af3` - do not OC interrupt during replay + +Community Edition release commits and package rename commits were not imported. diff --git a/README.md b/README.md index 3ebe2c7268..dc572cb312 100644 --- a/README.md +++ b/README.md @@ -1,224 +1,166 @@ -# Spring +# TelosZero Core -1. [Branches](#branches) -2. [Supported Operating Systems](#supported-operating-systems) -3. [Binary Installation](#binary-installation) -4. [Build and Install from Source](#build-and-install-from-source) -5. [Bash Autocomplete](#bash-autocomplete) +TelosZero Core is the TelosNetwork-maintained continuation of Antelope Spring for +Telos operators, infrastructure providers, and protocol contributors. -Spring is a C++ implementation of the [Antelope](https://github.com/AntelopeIO) protocol with support for Savanna consensus. It contains blockchain node software and supporting tools for developers and node operators. +This private staging repository currently tracks the MIT-licensed +`AntelopeIO/spring` `main` line and keeps the runtime command names stable: +`nodeos`, `cleos`, `keosd`, and `spring-util`. -## Branches -The `main` branch is the development branch; do not use it for production. Refer to the [release page](https://github.com/AntelopeIO/spring/releases) for current information on releases, pre-releases, and obsolete releases, as well as the corresponding tags for those releases. +TelosZero packages are emitted as `teloszero-core` and `teloszero-core-dev`. +They conflict with the historical Spring/Leap/EOSIO packages because those +packages install overlapping node and CLI binaries. -## Supported Operating Systems -We currently support the following operating systems. -- Ubuntu 22.04 Jammy -- Ubuntu 20.04 Focal +## Current Status -Other Unix derivatives such as macOS are tended to on a best-effort basis and may not be full featured. If you aren't using Ubuntu, please visit the "[Build Unsupported OS](./docs/00_install/01_build-from-source/00_build-unsupported-os.md)" page to explore your options. +This repository is in private bootstrap. Do not use it for production until the +TelosZero maintainers publish a signed release and an operator upgrade notice. -If you are running an unsupported Ubuntu derivative, such as Linux Mint, you can find the version of Ubuntu your distribution was based on by using this command: -```bash -cat /etc/upstream-release/lsb-release -``` -Your best bet is to follow the instructions for your Ubuntu base, but we make no guarantees. +Initial bootstrap priorities: -## Binary Installation -This is the fastest way to get started. From the [latest release](https://github.com/AntelopeIO/spring/releases/latest) page, download a binary for one of our [supported operating systems](#supported-operating-systems), or visit the [release tags](https://github.com/AntelopeIO/spring/releases) page to download a binary for a specific version of Spring. +- preserve Spring history and compatibility +- publish Telos-controlled packages and release artifacts +- keep legal and licensing provenance clear +- replace inherited infrastructure with Telos-owned CI and release workflows +- review useful patches from upstream Spring and the Spring Community Edition -Once you have a `*.deb` file downloaded for your version of Ubuntu, you can install it as follows: -```bash -sudo apt-get update -sudo apt-get install -y ~/Downloads/spring*.deb -``` -Your download path may vary. If you are in an Ubuntu docker container, omit `sudo` because you run as `root` by default. +## Repository Remotes + +Recommended local remotes: -Finally, verify Spring was installed correctly: ```bash -nodeos --full-version +git remote -v ``` -You should see a [semantic version](https://semver.org) string followed by a `git` commit hash with no errors. For example: -``` -v1.0.1-9026a03c09c9b4f93edca696b5eef259f0ab96b3 + +```text +origin https://github.com/TelosNetwork/teloszero-core.git +upstream https://github.com/AntelopeIO/spring.git +ce https://github.com/eos-amsterdam-rnd/antelope_spring_ce.git ``` -## Build and Install from Source -You can also build and install Spring from source. +`origin` is the TelosZero canonical remote. `upstream` is fetch-only for Spring +changes. `ce` is fetch-only for reviewing Community Edition patches. -### Prerequisites -You will need to build on a [supported operating system](#supported-operating-systems). +## Branches -Requirements to build: -- C++20 compiler and standard library -- CMake 3.16+ -- LLVM 7 - 11 - for Linux only - - newer versions do not work -- libcurl 7.40.0+ -- git -- GMP -- Python 3 -- python3-numpy -- zlib +`main` is the development branch and should not be used for production. -### Step 1 - Clone -If you don't have the Spring repo cloned to your computer yet, [open a terminal](https://itsfoss.com/open-terminal-ubuntu) and navigate to the folder where you want to clone the Spring repository: -```bash -cd ~/Downloads -``` -Clone Spring using either HTTPS... -```bash -git clone --recursive https://github.com/AntelopeIO/spring.git -``` -...or SSH: -```bash -git clone --recursive git@github.com:AntelopeIO/spring.git -``` +Planned stable branches: -> ℹ️ **HTTPS vs. SSH Clone** ℹ️ -Both an HTTPS or SSH git clone will yield the same result - a folder named `spring` containing our source code. It doesn't matter which type you use. +- `release/teloszero-1.x` for the first Telos-compatible production line +- `release/teloszero-2.x` for future protocol work and developer previews -Navigate into that folder: -```bash -cd spring -``` +Historical upstream branches and tags are preserved for auditability. -### Step 2 - Checkout Release Tag or Branch -Choose which [release](https://github.com/AntelopeIO/spring/releases) or [branch](#branches) you would like to build, then check it out. If you are not sure, use the [latest release](https://github.com/AntelopeIO/spring/releases/latest). For example, if you want to build release 1.0.1 then you would check it out using its tag, `v1.0.1`. In the example below, replace `v0.0.0` with your selected release tag accordingly: -```bash -git fetch --all --tags -git checkout v0.0.0 -``` +## Licensing -Once you are on the branch or release tag you want to build, make sure everything is up-to-date: -```bash -git pull -git submodule update --init --recursive -``` +The bootstrap starts from upstream Spring `main` after the MIT license update. +Older Spring release branches and tags may carry different license terms. Do not +cut TelosZero production binaries from those branches until the licensing status +is reviewed and documented. -### Step 3 - Build -Select build instructions below for a [pinned build](#pinned-build) (preferred) or an [unpinned build](#unpinned-build). +The upstream copyright and license notice is preserved in `LICENSE`. -> ℹ️ **Pinned vs. Unpinned Build** ℹ️ -We have two types of builds for Spring: "pinned" and "unpinned." A pinned build is a reproducible build with the build environment and dependency versions fixed by the development team. In contrast, unpinned builds use the dependency versions provided by the build platform. Unpinned builds tend to be quicker because the pinned build environment must be built from scratch. Pinned builds, in addition to being reproducible, ensure the compiler remains the same between builds of different Spring major versions. Spring requires the compiler version to remain the same, otherwise its state might need to be recovered from a portable snapshot or the chain needs to be replayed. +## Build From Source -> ⚠️ **A Warning On Parallel Compilation Jobs (`-j` flag)** ⚠️ -When building C/C++ software, often the build is performed in parallel via a command such as `make -j "$(nproc)"` which uses all available CPU threads. However, be aware that some compilation units (`*.cpp` files) in Spring will consume nearly 4GB of memory. Failures due to memory exhaustion will typically, but not always, manifest as compiler crashes. Using all available CPU threads may also prevent you from doing other things on your computer during compilation. For these reasons, consider reducing this value. +Use Ubuntu 22.04 or Ubuntu 20.04. macOS and other Unix-like systems are +best-effort only. -> 🐋 **Docker and `sudo`** 🐋 -If you are in an Ubuntu docker container, omit `sudo` from all commands because you run as `root` by default. Most other docker containers also exclude `sudo`, especially Debian-family containers. If your shell prompt is a hash tag (`#`), omit `sudo`. +Requirements: + +- C++20 compiler and standard library +- CMake 3.16+ +- LLVM 7 through 11 for Linux OC builds +- libcurl 7.40.0+ +- git +- GMP +- Python 3 +- python3-numpy +- zlib + +Clone with submodules: -#### Pinned Reproducible Build -The pinned reproducible build requires Docker. Make sure you are in the root of the `spring` repo and then run -```bash -DOCKER_BUILDKIT=1 docker build -f tools/reproducible.Dockerfile -o . . -``` -This command will take a substantial amount of time because a toolchain is built from scratch. Upon completion, the current directory will contain a built `.deb` and `.tar.gz` (you can change the `-o .` argument to place the output in a different directory). If needing to reduce the number of parallel jobs as warned above, run the command as, ```bash -DOCKER_BUILDKIT=1 docker build --build-arg SPRING_BUILD_JOBS=4 -f tools/reproducible.Dockerfile -o . . +git clone --recursive https://github.com/TelosNetwork/teloszero-core.git +cd teloszero-core ``` -#### Unpinned Build -The following instructions are valid for this branch. Other release branches may have different requirements, so ensure you follow the directions in the branch or release you intend to build. If you are in an Ubuntu docker container, omit `sudo` because you run as `root` by default. +Install build dependencies on Ubuntu 22.04: -Install dependencies: ```bash sudo apt-get update sudo apt-get install -y \ - build-essential \ - cmake \ - git \ - libcurl4-openssl-dev \ - libgmp-dev \ - llvm-11-dev \ - python3-numpy \ - file \ - zlib1g-dev + build-essential \ + cmake \ + git \ + libcurl4-openssl-dev \ + libgmp-dev \ + llvm-11-dev \ + python3-numpy \ + file \ + zlib1g-dev ``` -On Ubuntu 20.04, install gcc-10 which has C++20 support: -```bash -sudo apt-get install -y g++-10 -``` +Configure and build: -To build, make sure you are in the root of the `spring` repo, then run the following command: ```bash mkdir -p build cd build - -## on Ubuntu 20, specify the gcc-10 compiler -cmake -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/usr/lib/llvm-11 .. - -## on Ubuntu 22, the default gcc version is 11, using the default compiler is fine cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/usr/lib/llvm-11 .. - make -j "$(nproc)" package ``` -Now you can optionally [test](#step-4---test) your build, or [install](#step-5---install) the `*.deb` binary packages, which will be in the root of your build directory. +For Ubuntu 20.04, install `g++-10` and pass the compiler explicitly: -### Step 4 - Test -Spring supports the following test suites: - -Test Suite | Test Type | [Test Size](https://testing.googleblog.com/2010/12/test-sizes.html) | Notes ----|:---:|:---:|--- -[Parallelizable tests](#parallelizable-tests) | Unit tests | Small -[WASM spec tests](#wasm-spec-tests) | Unit tests | Small | Unit tests for our WASM runtime, each short but _very_ CPU-intensive -[Serial tests](#serial-tests) | Component/Integration | Medium -[Long-running tests](#long-running-tests) | Integration | Medium-to-Large | Tests which take an extraordinarily long amount of time to run - -When building from source, we recommended running at least the [parallelizable tests](#parallelizable-tests). - -#### Parallelizable Tests -This test suite consists of any test that does not require shared resources, such as file descriptors, specific folders, or ports, and can therefore be run concurrently in different threads without side effects (hence, easily parallelized). These are mostly unit tests and [small tests](https://testing.googleblog.com/2010/12/test-sizes.html) which complete in a short amount of time. - -You can invoke them by running `ctest` from a terminal in your Spring build directory and specifying the following arguments: ```bash -ctest -j "$(nproc)" -LE _tests +sudo apt-get install -y g++-10 +cmake -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH=/usr/lib/llvm-11 .. ``` -#### WASM Spec Tests -The WASM spec tests verify that our WASM execution engine is compliant with the web assembly standard. These are very [small](https://testing.googleblog.com/2010/12/test-sizes.html), very fast unit tests. However, there are over a thousand of them so the suite can take a little time to run. These tests are extremely CPU-intensive. - -You can invoke them by running `ctest` from a terminal in your Spring build directory and specifying the following arguments: -```bash -ctest -j "$(nproc)" -L wasm_spec_tests -``` -We have observed severe performance issues when multiple virtual machines are running this test suite on the same physical host at the same time, for example in a CICD system. This can be resolved by disabling hyperthreading on the host. +## Tests -#### Serial Tests -The serial test suite consists of [medium](https://testing.googleblog.com/2010/12/test-sizes.html) component or integration tests that use specific paths, ports, rely on process names, or similar, and cannot be run concurrently with other tests. Serial tests can be sensitive to other software running on the same host and they may `SIGKILL` other `nodeos` processes. These tests take a moderate amount of time to complete, but we recommend running them. +From the build directory: -You can invoke them by running `ctest` from a terminal in your Spring build directory and specifying the following arguments: ```bash +ctest -j "$(nproc)" -LE _tests +ctest -j "$(nproc)" -L wasm_spec_tests ctest -L "nonparallelizable_tests" ``` -#### Long-Running Tests -The long-running tests are [medium-to-large](https://testing.googleblog.com/2010/12/test-sizes.html) integration tests that rely on shared resources and take a very long time to run. +Long-running integration tests are available with: -You can invoke them by running `ctest` from a terminal in your Spring build directory and specifying the following arguments: ```bash ctest -L "long_running_tests" ``` -### Step 5 - Install -Once you have [built](#step-3---build-the-source-code) Spring and [tested](#step-4---test) your build, you can install Spring on your system. Don't forget to omit `sudo` if you are running in a docker container. +## Reproducible Build + +The pinned reproducible Docker build is inherited from Spring and is being +carried forward for TelosZero: -We recommend installing the binary package you just built. Navigate to your Spring build directory in a terminal and run this command: ```bash -sudo apt-get update -sudo apt-get install -y ./spring_*.deb +DOCKER_BUILDKIT=1 docker build -f tools/reproducible.Dockerfile -o . . ``` -It is also possible to install using `make` instead: +To reduce memory pressure: + ```bash -sudo make install +DOCKER_BUILDKIT=1 docker build \ + --build-arg SPRING_BUILD_JOBS=4 \ + -f tools/reproducible.Dockerfile \ + -o . . ``` -## Bash Autocomplete -`cleos` and `spring-util` offer a substantial amount of functionality. Consider using bash's autocompletion support which makes it easier to discover all their various options. +## Governance And Security -For our provided `.deb` packages simply install Ubuntu's `bash-completion` package: `apt-get install bash-completion` (you may need to log out/in after installing). +See: -If building from source install the `build/programs/cleos/bash-completion/completions/cleos` and `build/programs/spring-util/bash-completion/completions/spring-util` files to your bash-completion directory. Refer to [bash-completion's documentation](https://github.com/scop/bash-completion#faq) on the possible install locations. +- `GOVERNANCE.md` +- `LEGAL.md` +- `MAINTAINERS.md` +- `PATCHES.md` +- `SECURITY.md` +- `SUPPORT.md` +- `CONTRIBUTING.md` diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..60c7cc5223 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,28 @@ +# Security Policy + +TelosZero Core is private during bootstrap and should not yet be treated as a +production release channel. + +## Reporting A Vulnerability + +Report suspected vulnerabilities privately. During bootstrap, use GitHub private +repository access to contact maintainers directly or email `devs@telos.net`. + +Do not open public issues for suspected vulnerabilities after the repository is +made public. + +## Supported Versions + +No TelosZero Core production version is currently supported. + +Support begins only after maintainers publish: + +- a signed production release +- checksums and artifact provenance +- operator upgrade guidance +- a support window for that release line + +## Disclosure + +Maintainers should coordinate fixes privately, prepare patched artifacts, and +publish disclosure notes only after affected operators have a safe upgrade path. diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000000..38f7d348ce --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,26 @@ +# Support + +TelosZero Core is in private bootstrap. There is no production support channel +until the first signed release is published. + +## Bootstrap Support + +Use private GitHub issues or TelosNetwork maintainer channels for: + +- build failures +- packaging issues +- CI runner setup +- release process questions +- upstream patch triage + +## Operator Support + +Operator support begins after a release is explicitly marked production-ready. +Production release notes must include: + +- supported operating systems +- package names and checksums +- upgrade steps +- rollback steps +- known incompatibilities +- test coverage summary diff --git a/package.cmake b/package.cmake index 3d7b875e8a..dfb4a606f8 100644 --- a/package.cmake +++ b/package.cmake @@ -37,25 +37,43 @@ string(REGEX REPLACE "^${CMAKE_PROJECT_NAME}-(.*)$" "${CMAKE_PROJECT_NAME}_\\1_$ string(APPEND CPACK_PACKAGE_FILE_NAME "-${CMAKE_SYSTEM_PROCESSOR}") -set(CPACK_PACKAGE_CONTACT "EOS Network Foundation") -set(CPACK_PACKAGE_VENDOR "EOS Network Foundation") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "C++ implementation of the Antelope protocol with Savanna consensus") +set(CPACK_PACKAGE_CONTACT "Telos Network") +set(CPACK_PACKAGE_VENDOR "Telos Network") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "TelosZero core node software for Antelope-derived networks with Savanna consensus") set(CPACK_COMPONENT_BASE_DESCRIPTION "daemon and CLI tools including ${NODE_EXECUTABLE_NAME}, ${CLI_CLIENT_EXECUTABLE_NAME}, and ${KEY_STORE_EXECUTABLE_NAME}") set(CPACK_COMPONENT_DEV_DESCRIPTION "headers and libraries for native contract unit testing") -set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/AntelopeIO/spring") +set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/TelosNetwork/teloszero-core") set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) set(CPACK_DEBIAN_BASE_PACKAGE_SECTION "utils") -set(CPACK_DEBIAN_PACKAGE_CONFLICTS "eosio, mandel, leap") -set(CPACK_RPM_PACKAGE_CONFLICTS "eosio, mandel, leap") +set(TELOSZERO_BASE_PACKAGE_CONFLICTS "eosio, mandel, leap, spring, antelope-spring") +set(TELOSZERO_DEV_PACKAGE_CONFLICTS "spring-dev, antelope-spring-dev") + +set(CPACK_DEBIAN_PACKAGE_CONFLICTS "${TELOSZERO_BASE_PACKAGE_CONFLICTS}") +set(CPACK_DEBIAN_BASE_PACKAGE_CONFLICTS "${TELOSZERO_BASE_PACKAGE_CONFLICTS}") +set(CPACK_DEBIAN_BASE_PACKAGE_REPLACES "spring, antelope-spring") +set(CPACK_DEBIAN_BASE_PACKAGE_PROVIDES "spring, antelope-spring") +set(CPACK_DEBIAN_DEV_PACKAGE_CONFLICTS "${TELOSZERO_DEV_PACKAGE_CONFLICTS}") +set(CPACK_DEBIAN_DEV_PACKAGE_REPLACES "spring-dev, antelope-spring-dev") +set(CPACK_DEBIAN_DEV_PACKAGE_PROVIDES "spring-dev, antelope-spring-dev") + +set(CPACK_RPM_PACKAGE_CONFLICTS "${TELOSZERO_BASE_PACKAGE_CONFLICTS}") +set(CPACK_RPM_BASE_PACKAGE_CONFLICTS "${TELOSZERO_BASE_PACKAGE_CONFLICTS}") +set(CPACK_RPM_BASE_PACKAGE_OBSOLETES "spring, antelope-spring") +set(CPACK_RPM_BASE_PACKAGE_PROVIDES "spring, antelope-spring") +set(CPACK_RPM_DEV_PACKAGE_CONFLICTS "${TELOSZERO_DEV_PACKAGE_CONFLICTS}") +set(CPACK_RPM_DEV_PACKAGE_OBSOLETES "spring-dev, antelope-spring-dev") +set(CPACK_RPM_DEV_PACKAGE_PROVIDES "spring-dev, antelope-spring-dev") set(CPACK_COMPONENTS_ALL "base") -if(ENABLE_SPRING_DEV_DEB) +if(ENABLE_TELOSZERO_DEV_DEB OR ENABLE_SPRING_DEV_DEB) list(APPEND CPACK_COMPONENTS_ALL "dev") endif() -#enable per component packages for .deb; ensure main package is just "antelope-spring", not "antelope-spring-base", and make the dev package have "antelope-spring-dev" at the front not the back +#enable per component packages for .deb; ensure main package is just "teloszero-core", +#not "teloszero-core-base", and make the dev package have "teloszero-core-dev" +#at the front not the back set(CPACK_DEB_COMPONENT_INSTALL ON) set(CPACK_DEBIAN_BASE_PACKAGE_NAME "${CMAKE_PROJECT_NAME}") set(CPACK_DEBIAN_BASE_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}.deb") diff --git a/tools/reproducible.Dockerfile b/tools/reproducible.Dockerfile index 108b235468..2f0716e93f 100644 --- a/tools/reproducible.Dockerfile +++ b/tools/reproducible.Dockerfile @@ -131,7 +131,7 @@ ARG SPRING_BUILD_JOBS COPY / /__w/spring/spring RUN cmake -S /__w/spring/spring -B build -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -GNinja && \ cmake --build build -t package -- ${SPRING_BUILD_JOBS:+-j$SPRING_BUILD_JOBS} && \ - /__w/spring/spring/tools/tweak-deb.sh build/antelope-spring_*.deb + /__w/spring/spring/tools/tweak-deb.sh build/teloszero-core_*.deb FROM scratch AS exporter COPY --from=build /build/*.deb /build/*.tar.* / From 13ff54ed81ef92be9e9fc1c2321e9cc8fb67ad8e Mon Sep 17 00:00:00 2001 From: Tobias Date: Fri, 1 May 2026 12:48:35 -0400 Subject: [PATCH 12/13] Make inherited submodule check manual during bootstrap --- .github/workflows/submod.yaml | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/.github/workflows/submod.yaml b/.github/workflows/submod.yaml index 35d9281185..c9c5248225 100644 --- a/.github/workflows/submod.yaml +++ b/.github/workflows/submod.yaml @@ -1,20 +1,12 @@ name: Submodule Check -on: [pull_request] -env: - PR_NUMBER: ${{ toJson(github.event.number) }} +on: + workflow_dispatch: +# Inherited from Spring. The recursive submodule regression check is kept as a +# manual workflow until TelosZero CI policy defines when it should gate PRs. jobs: - submodule_regression_check: - name: Submodule Regression Check + disabled: runs-on: ubuntu-latest steps: - - name: Checkout - run: | - git clone https://x-access-token:${{github.token}}@github.com/${GITHUB_REPOSITORY} . - git fetch -v --prune origin +refs/pull/${PR_NUMBER}/merge:refs/remotes/pull/${PR_NUMBER}/merge - git checkout --force --progress refs/remotes/pull/${PR_NUMBER}/merge - git submodule sync --recursive - git submodule update --init --force --recursive - - name: Submodule Regression Check - run: ./scripts/submodule-regression-check.sh + - run: echo "Submodule regression check is manual during TelosZero bootstrap." From dd0fcf61ab0fa2734b3f67f9ef4fd450024c6471 Mon Sep 17 00:00:00 2001 From: Tobias Date: Thu, 7 May 2026 10:26:41 -0400 Subject: [PATCH 13/13] Clean up genesis files for Telos --- genesis/README.md | 24 ++++++++------ genesis/jungle_chain_id.json | 3 -- genesis/jungle_genesis.json | 24 -------------- genesis/kylin_chain_id.json | 3 -- genesis/telos_mainnet_chain_id.json | 3 ++ ...enesis.json => telos_mainnet_genesis.json} | 31 ++++++++++--------- genesis/telos_testnet_chain_id.json | 3 ++ ...enesis.json => telos_testnet_genesis.json} | 6 ++-- genesis/vaulta_chain_id.json | 3 -- 9 files changed, 39 insertions(+), 61 deletions(-) delete mode 100644 genesis/jungle_chain_id.json delete mode 100644 genesis/jungle_genesis.json delete mode 100644 genesis/kylin_chain_id.json create mode 100644 genesis/telos_mainnet_chain_id.json rename genesis/{kylin_genesis.json => telos_mainnet_genesis.json} (63%) create mode 100644 genesis/telos_testnet_chain_id.json rename genesis/{vaulta_genesis.json => telos_testnet_genesis.json} (80%) delete mode 100644 genesis/vaulta_chain_id.json diff --git a/genesis/README.md b/genesis/README.md index aad024ecf4..2976657b11 100644 --- a/genesis/README.md +++ b/genesis/README.md @@ -1,15 +1,19 @@ -## Vaulta Mainnet +## Telos Genesis Files -See also: https://github.com/CryptoLions/EOS-MainNet +This directory contains the public Telos network genesis files used when +starting a node from genesis. -## Jungle testnet +| Network | Genesis file | Chain ID | +| --- | --- | --- | +| Telos Mainnet | `telos_mainnet_genesis.json` | `4667b205c6838ef70ff7988f6e8257e8be0e1284a2f59699054a018f743b1d11` | +| Telos Testnet | `telos_testnet_genesis.json` | `1eaa0824707c8c16bd25145493bf062aecddfeb56c736f6ba6397f3195f33c9f` | -See also: https://github.com/CryptoLions/EOS-Jungle-Testnet +The chain ID files are provided as convenient reference values for +configuration checks and node verification. The canonical chain ID is computed +from the corresponding genesis state. -## Kylin testnet +## Sources -See also: https://github.com/cryptokylin/CryptoKylin-Testnet - -## API Nodes - -- [Greymass API Nodes](https://www.greymass.com/endpoints) +- Telos node template: https://github.com/telosnetwork/node-template +- Telos validator node setup: https://docs.telos.net/nodes/bp-nodes/setting-up-telos-validator-nodes/ +- Telos node operation guide: https://docs.telos.net/nodes/non-bp-nodes/run_a_telos_node/ diff --git a/genesis/jungle_chain_id.json b/genesis/jungle_chain_id.json deleted file mode 100644 index e4c4677508..0000000000 --- a/genesis/jungle_chain_id.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "chain_id": "73e4385a2708e6d7048834fbc1079f2fabb17b3c125b146af438971e90716c4d" -} \ No newline at end of file diff --git a/genesis/jungle_genesis.json b/genesis/jungle_genesis.json deleted file mode 100644 index 574524c7ee..0000000000 --- a/genesis/jungle_genesis.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "initial_timestamp": "2022-02-22T22:22:22", - "initial_key": "EOS5UAjunGLeR6eBfbpU4CxGssxa9DKKjbPA4zrCuUpoJQwvdpACs", - "initial_configuration": { - "max_block_net_usage": 1048576, - "target_block_net_usage_pct": 1000, - "max_transaction_net_usage": 524287, - "base_per_transaction_net_usage": 12, - "net_usage_leeway": 500, - "context_free_discount_net_usage_num": 20, - "context_free_discount_net_usage_den": 100, - "max_block_cpu_usage": 200000, - "target_block_cpu_usage_pct": 10, - "max_transaction_cpu_usage": 150000, - "min_transaction_cpu_usage": 1, - "max_transaction_lifetime": 3600, - "deferred_trx_expiration_window": 600, - "max_transaction_delay": 3888000, - "max_inline_action_size": 524287, - "max_inline_action_depth": 32, - "max_authority_depth": 6, - "max_ram_size": 68719476736 - } -} \ No newline at end of file diff --git a/genesis/kylin_chain_id.json b/genesis/kylin_chain_id.json deleted file mode 100644 index c559623a7c..0000000000 --- a/genesis/kylin_chain_id.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "chain_id": "5fff1dae8dc8e2fc4d5b23b2c7665c97f9e9d8edf2b6485a86ba311c25639191" -} \ No newline at end of file diff --git a/genesis/telos_mainnet_chain_id.json b/genesis/telos_mainnet_chain_id.json new file mode 100644 index 0000000000..4e8c949080 --- /dev/null +++ b/genesis/telos_mainnet_chain_id.json @@ -0,0 +1,3 @@ +{ + "chain_id": "4667b205c6838ef70ff7988f6e8257e8be0e1284a2f59699054a018f743b1d11" +} diff --git a/genesis/kylin_genesis.json b/genesis/telos_mainnet_genesis.json similarity index 63% rename from genesis/kylin_genesis.json rename to genesis/telos_mainnet_genesis.json index f3c85322a9..39113411ab 100644 --- a/genesis/kylin_genesis.json +++ b/genesis/telos_mainnet_genesis.json @@ -1,23 +1,24 @@ { - "initial_timestamp": "2018-07-11T05:30:00.000", - "initial_key": "EOS7hHHDtnPRbhMmfHJHUEKQyiutKrt9wZPdy1JbaATVLyxpCkrop", + "initial_timestamp": "2018-12-12T10:29:00.000", + "initial_key": "EOS52vfcN43YHHU8Akh7VyfBdnDiMg15dPTELosWG9SR86ssBoU1T", "initial_configuration": { - "max_block_net_usage": 1048576, - "target_block_net_usage_pct": 1000, - "max_transaction_net_usage": 524288, - "base_per_transaction_net_usage": 12, + "max_transaction_delay": 3888000, + "min_transaction_cpu_usage": 100, "net_usage_leeway": 500, - "context_free_discount_net_usage_num": 20, "context_free_discount_net_usage_den": 100, - "max_block_cpu_usage": 200000, - "target_block_cpu_usage_pct": 1000, - "max_transaction_cpu_usage": 150000, - "min_transaction_cpu_usage": 100, + "max_transaction_net_usage": 524288, + "context_free_discount_net_usage_num": 20, "max_transaction_lifetime": 3600, "deferred_trx_expiration_window": 600, - "max_transaction_delay": 3888000, + "max_authority_depth": 6, + "max_transaction_cpu_usage": 5000000, + "max_block_net_usage": 1048576, + "target_block_net_usage_pct": 1000, + "max_generated_transaction_count": 16, "max_inline_action_size": 4096, - "max_inline_action_depth": 4, - "max_authority_depth": 6 + "target_block_cpu_usage_pct": 1000, + "base_per_transaction_net_usage": 12, + "max_block_cpu_usage": 50000000, + "max_inline_action_depth": 4 } -} \ No newline at end of file +} diff --git a/genesis/telos_testnet_chain_id.json b/genesis/telos_testnet_chain_id.json new file mode 100644 index 0000000000..a05086fcea --- /dev/null +++ b/genesis/telos_testnet_chain_id.json @@ -0,0 +1,3 @@ +{ + "chain_id": "1eaa0824707c8c16bd25145493bf062aecddfeb56c736f6ba6397f3195f33c9f" +} diff --git a/genesis/vaulta_genesis.json b/genesis/telos_testnet_genesis.json similarity index 80% rename from genesis/vaulta_genesis.json rename to genesis/telos_testnet_genesis.json index 6520761a25..7499fa44f6 100644 --- a/genesis/vaulta_genesis.json +++ b/genesis/telos_testnet_genesis.json @@ -1,6 +1,6 @@ { - "initial_timestamp": "2018-06-08T08:08:08.888", - "initial_key": "EOS7EarnUhcyYqmdnPon8rm7mBCTnBoot6o7fE2WzjvEX2TdggbL3", + "initial_timestamp": "2019-08-07T12:00:00.000", + "initial_key": "EOS7xyPWfh6743fhZ46zQQcXSctddoqG65d44YsyRnCJCs54mJLrH", "initial_configuration": { "max_block_net_usage": 1048576, "target_block_net_usage_pct": 1000, @@ -9,7 +9,7 @@ "net_usage_leeway": 500, "context_free_discount_net_usage_num": 20, "context_free_discount_net_usage_den": 100, - "max_block_cpu_usage": 200000, + "max_block_cpu_usage": 5000000, "target_block_cpu_usage_pct": 1000, "max_transaction_cpu_usage": 150000, "min_transaction_cpu_usage": 100, diff --git a/genesis/vaulta_chain_id.json b/genesis/vaulta_chain_id.json deleted file mode 100644 index ceb0775ba8..0000000000 --- a/genesis/vaulta_chain_id.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "chain_id": "aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906" -} \ No newline at end of file