diff --git a/.github/workflows/ci-pr.yaml b/.github/workflows/ci-pr.yaml index a92b074360..421f6ea1cd 100644 --- a/.github/workflows/ci-pr.yaml +++ b/.github/workflows/ci-pr.yaml @@ -58,6 +58,21 @@ jobs: go-version: '1.24.2' cache-dependency-path: go/src/github.com/harmony-one/harmony/go.sum + - &cache-native-libs + name: Cache native mcl/bls libraries + uses: actions/cache@v4 + with: + path: | + go/src/github.com/harmony-one/mcl/bin + go/src/github.com/harmony-one/mcl/lib + go/src/github.com/harmony-one/mcl/obj + go/src/github.com/harmony-one/bls/bin + go/src/github.com/harmony-one/bls/lib + go/src/github.com/harmony-one/bls/obj + key: ${{ runner.os }}-native-libs-${{ hashFiles('go/src/github.com/harmony-one/mcl/**', 'go/src/github.com/harmony-one/bls/**') }} + restore-keys: | + ${{ runner.os }}-native-libs- + - &build-mcl name: Build mcl run: make -j4 @@ -82,6 +97,7 @@ jobs: - *checkout-mcl - *checkout-bls - *setup-go + - *cache-native-libs - *build-mcl - *build-bls - *build-harmony @@ -107,6 +123,7 @@ jobs: - *checkout-mcl - *checkout-bls - *setup-go + - *cache-native-libs - *build-mcl - *build-bls - *build-harmony @@ -121,6 +138,10 @@ jobs: path: go/src/github.com/harmony-one/harmony-test persist-credentials: false + - &setup-docker-buildx + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Run RPC checker run: | make go-get @@ -140,10 +161,12 @@ jobs: - *checkout-mcl - *checkout-bls - *setup-go + - *cache-native-libs - *build-mcl - *build-bls - *build-harmony - *checkout-harmony-test + - *setup-docker-buildx - name: Run pyhmy checker run: | diff --git a/Makefile b/Makefile index 844f6c5099..2efc9f241c 100644 --- a/Makefile +++ b/Makefile @@ -99,24 +99,21 @@ debug-ext: # add VERBOSE=true before bash or run `export VERBOSE=true` on the shell level for have max logging # add LEGACY_SYNC=true before bash or run `export LEGACY_SYNC=true` on the shell level to switch to the legacy sync ./test/debug.sh ./test/configs/local-resharding-with-external.txt 64 64 & - echo sleep 10s before creating the external validator - sleep 10 + ./test/wait_rpc_ready.sh http://localhost:9500 60 1 bash ./test/build-localnet-validator.sh debug-multi-bls: # add VERBOSE=true before bash or run `export VERBOSE=true` on the shell level for have max logging # add LEGACY_SYNC=true before bash or run `export LEGACY_SYNC=true` on the shell level to switch to the legacy sync ./test/debug.sh ./test/configs/local-multi-bls.txt 64 64 & - echo sleep 10s before creating the external validator - sleep 10 + ./test/wait_rpc_ready.sh http://localhost:9500 60 1 bash ./test/build-localnet-validator.sh debug-multi-bls-with-terminal: # add VERBOSE=true before bash or run `export VERBOSE=true` on the shell level for have max logging # add LEGACY_SYNC=true before bash or run `export LEGACY_SYNC=true` on the shell level to switch to the legacy sync screen -L -Logfile ./tmp_log/localnet_terminal.log -dmS localnet bash -c './test/debug.sh ./test/configs/local-multi-bls.txt 64 64; echo "Press any key to exit..."; read -n 1' - echo sleep 10s before creating the external validator - sleep 10 + ./test/wait_rpc_ready.sh http://localhost:9500 60 1 bash ./test/build-localnet-validator.sh screen -r localnet @@ -129,8 +126,7 @@ debug-multi-bls-multi-ext-node: # add VERBOSE=true before bash or run `export VERBOSE=true` on the shell level for have max logging # add LEGACY_SYNC=true before bash or run `export LEGACY_SYNC=true` on the shell level to switch to the legacy sync ./test/debug.sh ./test/configs/local-multi-bls-multi-ext-node.txt & - echo sleep 10s before creating the external validator - sleep 10 + ./test/wait_rpc_ready.sh http://localhost:9500 60 1 bash ./test/build-localnet-validator.sh clean: @@ -271,4 +267,4 @@ debug-delete-log: docker-go-test: - docker run --rm -it -v "$PWD":/go/src/github.com/harmony-one/harmony frozen621/harmony-test bash -c 'make go-test' \ No newline at end of file + docker run --rm -it -v "$PWD":/go/src/github.com/harmony-one/harmony frozen621/harmony-test bash -c 'make go-test' diff --git a/internal/configs/sharding/localnet.go b/internal/configs/sharding/localnet.go index 9c647c414f..6d556f00a9 100644 --- a/internal/configs/sharding/localnet.go +++ b/internal/configs/sharding/localnet.go @@ -46,6 +46,9 @@ const ( localnetEpochBlock1 = 5 + localnetBootstrapEpochBlocks = 4 + localnetBootstrapEpochs = 3 + localnetVdfDifficulty = 5000 // This takes about 10s to finish the vdf ) @@ -80,70 +83,79 @@ func (ls localnetSchedule) BlocksPerEpoch() uint64 { return localnetConfig.BlocksPerEpochV2 } +func (ls localnetSchedule) blocksInEpoch(epochNum uint64) uint64 { + if epochNum > 0 && + localnetBootstrapEpochBlocks > 0 && + localnetBootstrapEpochs > 0 && + epochNum <= localnetBootstrapEpochs { + return localnetBootstrapEpochBlocks + } + if params.LocalnetChainConfig.IsTwoSeconds(big.NewInt(int64(epochNum))) { + return ls.BlocksPerEpoch() + } + return ls.BlocksPerEpochOld() +} + func (ls localnetSchedule) twoSecondsFirstBlock() uint64 { if params.LocalnetChainConfig.TwoSecondsEpoch.Uint64() == 0 { return 0 } - return (params.LocalnetChainConfig.TwoSecondsEpoch.Uint64()-1)*ls.BlocksPerEpochOld() + localnetEpochBlock1 + return ls.EpochLastBlock(params.LocalnetChainConfig.TwoSecondsEpoch.Uint64()-1) + 1 } func (ls localnetSchedule) CalcEpochNumber(blockNum uint64) *big.Int { - firstBlock2s := ls.twoSecondsFirstBlock() - switch { - case blockNum < localnetEpochBlock1: + if blockNum < localnetEpochBlock1 { return big.NewInt(0) - case blockNum < firstBlock2s: - return big.NewInt(int64((blockNum-localnetEpochBlock1)/ls.BlocksPerEpochOld() + 1)) - default: - extra := uint64(0) - if firstBlock2s == 0 { - blockNum -= localnetEpochBlock1 - extra = 1 + } + low, high := uint64(1), uint64(1) + for ls.EpochLastBlock(high) < blockNum { + low = high + 1 + high *= 2 + } + for low < high { + mid := low + (high-low)/2 + if ls.EpochLastBlock(mid) < blockNum { + low = mid + 1 + } else { + high = mid } - return big.NewInt(int64(extra + (blockNum-firstBlock2s)/ls.BlocksPerEpoch() + params.LocalnetChainConfig.TwoSecondsEpoch.Uint64())) } + return big.NewInt(int64(low)) } func (ls localnetSchedule) IsLastBlock(blockNum uint64) bool { - switch { - case blockNum < localnetEpochBlock1-1: - return false - case blockNum == localnetEpochBlock1-1: - return true - default: - firstBlock2s := ls.twoSecondsFirstBlock() - switch { - case blockNum >= firstBlock2s: - if firstBlock2s == 0 { - blockNum -= localnetEpochBlock1 - } - return ((blockNum-firstBlock2s)%ls.BlocksPerEpoch() == ls.BlocksPerEpoch()-1) - default: // genesis - blocks := ls.BlocksPerEpochOld() - return ((blockNum-localnetEpochBlock1)%blocks == blocks-1) - } - } + epoch := ls.CalcEpochNumber(blockNum).Uint64() + return blockNum == ls.EpochLastBlock(epoch) } func (ls localnetSchedule) EpochLastBlock(epochNum uint64) uint64 { - switch { - case epochNum == 0: + if epochNum == 0 { return localnetEpochBlock1 - 1 - default: - switch { - case params.LocalnetChainConfig.IsTwoSeconds(big.NewInt(int64(epochNum))): - blocks := ls.BlocksPerEpoch() - firstBlock2s := ls.twoSecondsFirstBlock() - block2s := (1 + epochNum - params.LocalnetChainConfig.TwoSecondsEpoch.Uint64()) * blocks - if firstBlock2s == 0 { - return block2s - blocks + localnetEpochBlock1 - 1 - } - return firstBlock2s + block2s - 1 - default: // genesis - blocks := ls.BlocksPerEpochOld() - return localnetEpochBlock1 + blocks*epochNum - 1 + } + + bootstrapEpochs := uint64(0) + if localnetBootstrapEpochBlocks > 0 && localnetBootstrapEpochs > 0 { + bootstrapEpochs = localnetBootstrapEpochs + if bootstrapEpochs > epochNum { + bootstrapEpochs = epochNum } } + + blocks := bootstrapEpochs * localnetBootstrapEpochBlocks + regularEpochs := epochNum - bootstrapEpochs + twoSecondsEpoch := params.LocalnetChainConfig.TwoSecondsEpoch.Uint64() + oldEpochs := uint64(0) + if regularEpochs > 0 && twoSecondsEpoch > bootstrapEpochs+1 { + oldEpochs = twoSecondsEpoch - bootstrapEpochs - 1 + if oldEpochs > regularEpochs { + oldEpochs = regularEpochs + } + } + v2Epochs := regularEpochs - oldEpochs + + blocks += oldEpochs * ls.BlocksPerEpochOld() + blocks += v2Epochs * ls.BlocksPerEpoch() + return localnetEpochBlock1 + blocks - 1 } func (ls localnetSchedule) VdfDifficulty() int { diff --git a/internal/configs/sharding/localnet_test.go b/internal/configs/sharding/localnet_test.go index bf4fa6c7c8..d5a8f242d6 100644 --- a/internal/configs/sharding/localnet_test.go +++ b/internal/configs/sharding/localnet_test.go @@ -12,7 +12,6 @@ func TestLocalnetEpochCalculation(t *testing.T) { //test config init lnConfig := GetLocalnetConfig() - localnetBlocksPerEpoch := lnConfig.BlocksPerEpoch localnetBlocksPerEpochV2 := lnConfig.BlocksPerEpochV2 //test epoch calculations @@ -40,19 +39,59 @@ func TestLocalnetEpochCalculation(t *testing.T) { backup := params.LocalnetChainConfig.TwoSecondsEpoch params.LocalnetChainConfig.TwoSecondsEpoch = big.NewInt(0) check(0, localnetEpochBlock1-1) - check(1, localnetEpochBlock1+localnetBlocksPerEpochV2-1) - check(2, localnetEpochBlock1+localnetBlocksPerEpochV2*2-1) + check(1, localnetEpochBlock1+localnetBootstrapEpochBlocks-1) + check(2, localnetEpochBlock1+localnetBootstrapEpochBlocks*2-1) + check(3, localnetEpochBlock1+localnetBootstrapEpochBlocks*3-1) + check(4, localnetEpochBlock1+localnetBootstrapEpochBlocks*3+localnetBlocksPerEpochV2-1) params.LocalnetChainConfig.TwoSecondsEpoch = big.NewInt(1) check(0, localnetEpochBlock1-1) - check(1, localnetEpochBlock1+localnetBlocksPerEpochV2-1) - check(2, localnetEpochBlock1+localnetBlocksPerEpochV2*2-1) + check(1, localnetEpochBlock1+localnetBootstrapEpochBlocks-1) + check(2, localnetEpochBlock1+localnetBootstrapEpochBlocks*2-1) + check(3, localnetEpochBlock1+localnetBootstrapEpochBlocks*3-1) + check(4, localnetEpochBlock1+localnetBootstrapEpochBlocks*3+localnetBlocksPerEpochV2-1) params.LocalnetChainConfig.TwoSecondsEpoch = big.NewInt(2) check(0, localnetEpochBlock1-1) - check(1, localnetEpochBlock1+localnetBlocksPerEpoch-1) - check(2, localnetEpochBlock1+localnetBlocksPerEpoch+localnetBlocksPerEpochV2-1) - check(3, localnetEpochBlock1+localnetBlocksPerEpoch+localnetBlocksPerEpochV2*2-1) + check(1, localnetEpochBlock1+localnetBootstrapEpochBlocks-1) + check(2, localnetEpochBlock1+localnetBootstrapEpochBlocks*2-1) + check(3, localnetEpochBlock1+localnetBootstrapEpochBlocks*3-1) + check(4, localnetEpochBlock1+localnetBootstrapEpochBlocks*3+localnetBlocksPerEpochV2-1) params.LocalnetChainConfig.TwoSecondsEpoch = backup } + +func TestLocalnetBootstrapEpochCalculation(t *testing.T) { + InitLocalnetConfig(16, 16) + + backupTwoSecondsEpoch := params.LocalnetChainConfig.TwoSecondsEpoch + params.LocalnetChainConfig.TwoSecondsEpoch = big.NewInt(2) + defer func() { params.LocalnetChainConfig.TwoSecondsEpoch = backupTwoSecondsEpoch }() + + check := func(epoch, expected uint64) { + if got := LocalnetSchedule.EpochLastBlock(epoch); got != expected { + t.Fatalf("wrong EpochLastBlock at epoch %d. expected: %d got: %d.", epoch, expected, got) + } + if !LocalnetSchedule.IsLastBlock(expected) { + t.Fatalf("%d is not LastBlock", expected) + } + epochStart := uint64(0) + if epoch > 0 { + epochStart = LocalnetSchedule.EpochLastBlock(epoch-1) + 1 + } + for blockNo := epochStart; blockNo <= expected; blockNo++ { + if isLastBlock := LocalnetSchedule.IsLastBlock(blockNo); isLastBlock != (blockNo == expected) { + t.Fatalf("IsLastBlock for %d is wrong. expected %v got %v", blockNo, blockNo == expected, isLastBlock) + } + if got := LocalnetSchedule.CalcEpochNumber(blockNo).Uint64(); got != epoch { + t.Fatalf("CalcEpochNumber for %d is wrong. expected %d got %d", blockNo, epoch, got) + } + } + } + + check(0, localnetEpochBlock1-1) + check(1, localnetEpochBlock1+localnetBootstrapEpochBlocks-1) + check(2, localnetEpochBlock1+localnetBootstrapEpochBlocks*2-1) + check(3, localnetEpochBlock1+localnetBootstrapEpochBlocks*3-1) + check(4, localnetEpochBlock1+localnetBootstrapEpochBlocks*3+16-1) +} diff --git a/internal/params/config.go b/internal/params/config.go index b98f43b834..b5a1a19cbd 100644 --- a/internal/params/config.go +++ b/internal/params/config.go @@ -382,7 +382,7 @@ var ( DevnetExternalEpoch: EpochTBD, TestnetExternalEpoch: EpochTBD, TimestampValidationEpoch: big.NewInt(0), - IsOneSecondEpoch: big.NewInt(4), + IsOneSecondEpoch: big.NewInt(0), EIP2537PrecompileEpoch: EpochTBD, EIP1153TransientStorageEpoch: EpochTBD, EIP7939CLZEpoch: EpochTBD, diff --git a/scripts/api_test.sh b/scripts/api_test.sh index 895bd0e94c..28c744d714 100755 --- a/scripts/api_test.sh +++ b/scripts/api_test.sh @@ -69,10 +69,7 @@ while getopts "lbvp" OPTION; do --data "{\"jsonrpc\":\"2.0\",\"method\":\"hmy_sendRawTransaction\",\"params\":[\""$SIGNED_RAW_TRANSACTION"\"],\"id\":1}" | jq -r '.result') echo "TRANSACTION_HASH:" echo $TRANSACTION_HASH - sleep 20s - TRANSACTION=$(curl --location --request POST "http://l0.b.hmny.io:9500" \ - --header "Content-Type: application/json" \ - --data "{\"jsonrpc\":\"2.0\",\"method\":\"hmy_getTransactionByHash\",\"params\":[\"$TRANSACTION_HASH\"],\"id\":1}") + TRANSACTION=$(./test/wait_tx_receipt.sh "http://l0.b.hmny.io:9500" "$TRANSACTION_HASH" 60 1) echo "TRANSACTION:" echo "$TRANSACTION" @@ -113,10 +110,7 @@ while getopts "lbvp" OPTION; do --data "{\"jsonrpc\":\"2.0\",\"method\":\"hmy_sendRawTransaction\",\"params\":[\""$SIGNED_RAW_TRANSACTION"\"],\"id\":1}" | jq -r '.result') echo "TRANSACTION_HASH:" echo $TRANSACTION_HASH - sleep 20s - TRANSACTION=$(curl --location --request POST "http://localhost:9500" \ - --header "Content-Type: application/json" \ - --data "{\"jsonrpc\":\"2.0\",\"method\":\"hmy_getTransactionByHash\",\"params\":[\"$TRANSACTION_HASH\"],\"id\":1}") + TRANSACTION=$(./test/wait_tx_receipt.sh "http://localhost:9500" "$TRANSACTION_HASH" 60 1) echo "TRANSACTION:" echo "$TRANSACTION" diff --git a/scripts/travis_pyhmy_checker.sh b/scripts/travis_pyhmy_checker.sh index f93b8679da..a2f5e1f1a9 100755 --- a/scripts/travis_pyhmy_checker.sh +++ b/scripts/travis_pyhmy_checker.sh @@ -32,6 +32,37 @@ echo "[harmony repo] - working on '${MAIN_REPO_BRANCH}' branch" DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" echo "Working dir is ${DIR}" echo "GOPATH is ${GOPATH}" + +function timestamp() { + date -u +"%Y-%m-%dT%H:%M:%SZ" +} + +function timed() { + local label=$1 + shift + local start end elapsed + start=$(date +%s) + echo "[TIMING] $(timestamp) START ${label}" + "$@" + end=$(date +%s) + elapsed=$((end - start)) + echo "[TIMING] $(timestamp) END ${label}: ${elapsed}s" +} + +function build_localnet_test_image() { + local cache_scope + cache_scope="localnet-test-${TEST_REPO_BRANCH//[^a-zA-Z0-9_.-]/-}" + if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then + docker buildx build --load --build-arg MAIN_REPO_BRANCH="${MAIN_REPO_BRANCH}" --progress plain \ + --build-arg MAIN_REPO_ORG="${MAIN_REPO_ORG}" -t harmonyone/localnet-test \ + --cache-from "type=gha,scope=${cache_scope}" \ + --cache-to "type=gha,mode=max,scope=${cache_scope}" . + else + docker build --build-arg MAIN_REPO_BRANCH="${MAIN_REPO_BRANCH}" --progress plain \ + --build-arg MAIN_REPO_ORG="${MAIN_REPO_ORG}" -t harmonyone/localnet-test . + fi +} + cd "${GOPATH}/src/github.com/harmony-one/harmony-test" # Current solution expects that your harmony-test repo branch with the same name exists # or it will use master by default @@ -41,11 +72,10 @@ TEST_REPO_BRANCH=$(git ls-remote --exit-code --heads origin "${TEST_REPO_BRANCH} && echo "${TEST_REPO_BRANCH}" || echo "master") echo "[harmony-test repo] - working on '${TEST_REPO_BRANCH}' branch" # cover possible force pushes to remote branches - just rebase local on top of origin -git fetch origin "${TEST_REPO_BRANCH}" -git checkout "${TEST_REPO_BRANCH}" -git pull --rebase=true +timed "harmony-test fetch" git fetch origin "${TEST_REPO_BRANCH}" +timed "harmony-test checkout" git checkout "${TEST_REPO_BRANCH}" +timed "harmony-test pull" git pull --rebase=true cd localnet -docker build --build-arg MAIN_REPO_BRANCH="${MAIN_REPO_BRANCH}" --progress plain \ - --build-arg MAIN_REPO_ORG="${MAIN_REPO_ORG}" -t harmonyone/localnet-test . +timed "docker build localnet-test" build_localnet_test_image # WARN: this is the place where LOCAL repository is provided to the harmony-tests repo -docker run -v "$DIR/../:/go/src/github.com/harmony-one/harmony" harmonyone/localnet-test -p +timed "docker run pyhmy tests" docker run -v "$DIR/../:/go/src/github.com/harmony-one/harmony" harmonyone/localnet-test -p diff --git a/scripts/travis_rosetta_checker.sh b/scripts/travis_rosetta_checker.sh index bd96ad2fc7..fa2f8fbcf6 100755 --- a/scripts/travis_rosetta_checker.sh +++ b/scripts/travis_rosetta_checker.sh @@ -32,6 +32,37 @@ echo "[harmony repo] - working on '${MAIN_REPO_BRANCH}' branch" DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" echo "Working dir is ${DIR}" echo "GOPATH is ${GOPATH}" + +function timestamp() { + date -u +"%Y-%m-%dT%H:%M:%SZ" +} + +function timed() { + local label=$1 + shift + local start end elapsed + start=$(date +%s) + echo "[TIMING] $(timestamp) START ${label}" + "$@" + end=$(date +%s) + elapsed=$((end - start)) + echo "[TIMING] $(timestamp) END ${label}: ${elapsed}s" +} + +function build_localnet_test_image() { + local cache_scope + cache_scope="localnet-test-${TEST_REPO_BRANCH//[^a-zA-Z0-9_.-]/-}" + if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then + docker buildx build --load --build-arg MAIN_REPO_BRANCH="${MAIN_REPO_BRANCH}" --progress plain \ + --build-arg MAIN_REPO_ORG="${MAIN_REPO_ORG}" -t harmonyone/localnet-test \ + --cache-from "type=gha,scope=${cache_scope}" \ + --cache-to "type=gha,mode=max,scope=${cache_scope}" . + else + docker build --build-arg MAIN_REPO_BRANCH="${MAIN_REPO_BRANCH}" --progress plain \ + --build-arg MAIN_REPO_ORG="${MAIN_REPO_ORG}" -t harmonyone/localnet-test . + fi +} + cd "${GOPATH}/src/github.com/harmony-one/harmony-test" # fallback to master if branch is not on remote # Current solution expects that your harmony-test repo branch with the same name exists @@ -41,11 +72,10 @@ TEST_REPO_BRANCH=$(git ls-remote --exit-code --heads origin "${TEST_REPO_BRANCH} && echo "${TEST_REPO_BRANCH}" || echo "master") echo "[harmony-test repo] - working on '${TEST_REPO_BRANCH}' branch" # cover possible force pushes to remote branches - just rebase local on top of origin -git fetch origin "${TEST_REPO_BRANCH}" -git checkout "${TEST_REPO_BRANCH}" -git pull --rebase=true +timed "harmony-test fetch" git fetch origin "${TEST_REPO_BRANCH}" +timed "harmony-test checkout" git checkout "${TEST_REPO_BRANCH}" +timed "harmony-test pull" git pull --rebase=true cd localnet -docker build --build-arg MAIN_REPO_BRANCH="${MAIN_REPO_BRANCH}" --progress plain \ - --build-arg MAIN_REPO_ORG="${MAIN_REPO_ORG}" -t harmonyone/localnet-test . +timed "docker build localnet-test" build_localnet_test_image # WARN: this is the place where LOCAL repository is provided to the harmony-tests repo -docker run -v "$DIR/../:/go/src/github.com/harmony-one/harmony" harmonyone/localnet-test -r +timed "docker run rosetta tests" docker run -v "$DIR/../:/go/src/github.com/harmony-one/harmony" harmonyone/localnet-test -r diff --git a/scripts/travis_rpc_checker.sh b/scripts/travis_rpc_checker.sh index 5cc4900100..55c804de5a 100755 --- a/scripts/travis_rpc_checker.sh +++ b/scripts/travis_rpc_checker.sh @@ -32,6 +32,37 @@ echo "[harmony repo] - working on '${MAIN_REPO_BRANCH}' branch" DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" echo "Working dir is ${DIR}" echo "GOPATH is ${GOPATH}" + +function timestamp() { + date -u +"%Y-%m-%dT%H:%M:%SZ" +} + +function timed() { + local label=$1 + shift + local start end elapsed + start=$(date +%s) + echo "[TIMING] $(timestamp) START ${label}" + "$@" + end=$(date +%s) + elapsed=$((end - start)) + echo "[TIMING] $(timestamp) END ${label}: ${elapsed}s" +} + +function build_localnet_test_image() { + local cache_scope + cache_scope="localnet-test-${TEST_REPO_BRANCH//[^a-zA-Z0-9_.-]/-}" + if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then + docker buildx build --load --build-arg MAIN_REPO_BRANCH="${MAIN_REPO_BRANCH}" --progress plain \ + --build-arg MAIN_REPO_ORG="${MAIN_REPO_ORG}" -t harmonyone/localnet-test \ + --cache-from "type=gha,scope=${cache_scope}" \ + --cache-to "type=gha,mode=max,scope=${cache_scope}" . + else + docker build --build-arg MAIN_REPO_BRANCH="${MAIN_REPO_BRANCH}" --progress plain \ + --build-arg MAIN_REPO_ORG="${MAIN_REPO_ORG}" -t harmonyone/localnet-test . + fi +} + cd "${GOPATH}/src/github.com/harmony-one/harmony-test" # Current solution expects that your harmony-test repo branch with the same name exists # or it will use master by default @@ -41,11 +72,12 @@ TEST_REPO_BRANCH=$(git ls-remote --exit-code --heads origin "${TEST_REPO_BRANCH} && echo "${TEST_REPO_BRANCH}" || echo "master") echo "[harmony-test repo] - working on '${TEST_REPO_BRANCH}' branch" # cover possible force pushes to remote branches - just rebase local on top of origin -git fetch origin "${TEST_REPO_BRANCH}" -git checkout "${TEST_REPO_BRANCH}" -git pull --rebase=true +timed "harmony-test fetch" git fetch origin "${TEST_REPO_BRANCH}" +timed "harmony-test checkout" git checkout "${TEST_REPO_BRANCH}" +timed "harmony-test pull" git pull --rebase=true cd localnet -docker build --build-arg MAIN_REPO_BRANCH="${MAIN_REPO_BRANCH}" --progress plain \ - --build-arg MAIN_REPO_ORG="${MAIN_REPO_ORG}" -t harmonyone/localnet-test . +timed "docker build localnet-test" build_localnet_test_image # WARN: this is the place where LOCAL repository is provided to the harmony-tests repo -docker run -v "$DIR/../:/go/src/github.com/harmony-one/harmony" harmonyone/localnet-test -n +timed "docker run rpc tests" docker run \ + -e PYTEST_ADDOPTS="${PYTEST_ADDOPTS:---durations=25 --durations-min=1}" \ + -v "$DIR/../:/go/src/github.com/harmony-one/harmony" harmonyone/localnet-test -n diff --git a/test/build-localnet-validator.sh b/test/build-localnet-validator.sh index 52100165a9..0f86d83e0d 100755 --- a/test/build-localnet-validator.sh +++ b/test/build-localnet-validator.sh @@ -39,13 +39,7 @@ hmy --node=http://127.0.0.1:9500 transfer --from $FAUCET_ADDRESS --to one19z hmy --node=http://127.0.0.1:9500 transfer --from $FAUCET_ADDRESS --to one1lctumupg2y009pjmnhnmn4nqjk0zf0dspjanf7 --from-shard 0 --to-shard 0 --amount 110000 -#wait for epoch 2 -epoch=$(hmy blockchain latest-headers --node="http://localhost:9500" | jq -r '.["result"]["beacon-chain-header"]["epoch"]') -while (( epoch < 1 )); do - echo "Not yet on epoch 1 .. waiting 30s" - epoch=$(hmy blockchain latest-headers --node="http://localhost:9500" | jq -r '.["result"]["beacon-chain-header"]["epoch"]') - sleep 30 -done +./test/wait_till_n_epoch.sh 1 echo "Now in epoch 1, we'll create the external validators" @@ -89,4 +83,3 @@ hmy blockchain validator information one1auqndgthqu5lznsn7tuma8s5333cq0y07cwc6x hmy blockchain validator information one19aw2wcr5y4lxeuwt0ajgt5aw3a3qkjdgg67ygj --node="http://localhost:9500" hmy blockchain validator information one1eenp9ujcrmyaq22ef6jrpry2k97tjz4xs6ppcf --node="http://localhost:9500" ''' - diff --git a/test/wait_till_n_epoch.sh b/test/wait_till_n_epoch.sh old mode 100644 new mode 100755 index 99771a404a..7909d248ea --- a/test/wait_till_n_epoch.sh +++ b/test/wait_till_n_epoch.sh @@ -1,10 +1,28 @@ #! /bin/bash +set -euo pipefail -#wait for epoch N -epoch=$(hmy blockchain latest-headers --node="http://localhost:9500" | jq -r '.["result"]["beacon-chain-header"]["epoch"]') -while (( epoch < "${1}" )); do - echo "Not yet on epoch ${1} .. waiting 30s" - epoch=$(hmy blockchain latest-headers --node="http://localhost:9500" | jq -r '.["result"]["beacon-chain-header"]["epoch"]') - sleep 30 +TARGET_EPOCH=${1:?target epoch is required} +NODE_URL=${NODE_URL:-http://localhost:9500} +TIMEOUT_SECONDS=${TIMEOUT_SECONDS:-180} +INTERVAL_SECONDS=${INTERVAL_SECONDS:-1} + +if [[ "${NODE_URL}" != http://* && "${NODE_URL}" != https://* ]]; then + NODE_URL="http://${NODE_URL}" +fi + +deadline=$((SECONDS + TIMEOUT_SECONDS)) +while ((SECONDS < deadline)); do + response=$(curl -fsS -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"hmyv2_getLatestChainHeaders","params":[],"id":1}' \ + "${NODE_URL}" 2>/dev/null || true) + epoch=$(echo "${response}" | jq -r '.result["beacon-chain-header"].epoch // empty' 2>/dev/null || true) + if [[ -n "${epoch}" && "${epoch}" != "null" ]] && ((epoch >= TARGET_EPOCH)); then + echo "we are on the epoch ${epoch}, let's proceed" + exit 0 + fi + echo "Not yet on epoch ${TARGET_EPOCH}; current=${epoch:-unknown}; waiting ${INTERVAL_SECONDS}s" + sleep "${INTERVAL_SECONDS}" done -echo "we are on the epoch ${1}, let's proceed" + +echo "Timed out waiting ${TIMEOUT_SECONDS}s for epoch ${TARGET_EPOCH} at ${NODE_URL}" >&2 +exit 1