From b8c8f95c4d4e4011a8079b1d6efd07d8d76d1a34 Mon Sep 17 00:00:00 2001 From: Arkadiusz Osowski Date: Tue, 31 Dec 2024 10:11:41 +0100 Subject: [PATCH] test: add e2e tests for hybrid communication --- Makefile | 6 + docker-compose-mcast.yaml | 333 ++++++++++++++++++++++++++++++++++ docker-compose.yaml | 4 + test/config/config_mcast.yaml | 179 ++++++++++++++++++ test/init_test.go | 8 +- test/submit_02_batch_test.go | 5 + test/utils.go | 2 +- 7 files changed, 533 insertions(+), 4 deletions(-) create mode 100644 docker-compose-mcast.yaml create mode 100644 test/config/config_mcast.yaml diff --git a/Makefile b/Makefile index 4020840c1..468821d8c 100644 --- a/Makefile +++ b/Makefile @@ -39,6 +39,12 @@ run_e2e_tests_with_tracing: docker compose down --remove-orphans ARC_TRACING_ENABLED=TRUE docker compose up --build blocktx callbacker metamorph api tests jaeger --scale blocktx=4 --scale metamorph=2 --no-attach jaeger +.PHONY: run_e2e_mcast_tests +run_e2e_mcast_tests: + docker compose -f docker-compose-mcast.yaml down --remove-orphans + docker compose -f docker-compose-mcast.yaml up --build mcast_sidecar blocktx metamorph api tests --scale blocktx=6 --exit-code-from tests + docker compose -f docker-compose-mcast.yaml down + .PHONY: test test: go test -race -count=1 ./... diff --git a/docker-compose-mcast.yaml b/docker-compose-mcast.yaml new file mode 100644 index 000000000..fb4cde97b --- /dev/null +++ b/docker-compose-mcast.yaml @@ -0,0 +1,333 @@ +version: '3' +services: + node1: + container_name: node1 + image: bitcoinsv/bitcoin-sv:1.1.0 + ports: + - "18332:18332" + expose: + - "18332" + - "18333" + - "28332" + healthcheck: + test: [ "CMD", "/entrypoint.sh", "bitcoin-cli", "getinfo" ] + volumes: + - ./test/config/bitcoin.conf:/data/bitcoin.conf + - node1-data:/data + command: [ "/entrypoint.sh", "bitcoind", "-connect=node2:18333", "-connect=node3:18333" ] + networks: + - multicast_bridge + + node2: + container_name: node2 + image: bitcoinsv/bitcoin-sv:1.1.0 + expose: + - "18332" + - "18333" + healthcheck: + test: [ "CMD", "/entrypoint.sh", "bitcoin-cli", "getinfo" ] + volumes: + - ./test/config/bitcoin.conf:/data/bitcoin.conf + - node2-data:/data + command: [ "/entrypoint.sh", "bitcoind", "-connect=node1:18333", "-connect=node3:18333" ] + networks: + - multicast_bridge + + node3: + container_name: node3 + image: bitcoinsv/bitcoin-sv:1.1.0 + expose: + - "18332" + - "18333" + healthcheck: + test: [ "CMD", "/entrypoint.sh", "bitcoin-cli", "getinfo" ] + volumes: + - ./test/config/bitcoin.conf:/data/bitcoin.conf + - node3-data:/data + command: [ "/entrypoint.sh", "bitcoind", "-connect=node1:18333", "-connect=node2:18333" ] + networks: + - multicast_bridge + + db: + image: postgres:15.4 + restart: always + environment: + - POSTGRES_USER=arcuser + - POSTGRES_PASSWORD=arcpass + - POSTGRES_DB=main + healthcheck: + test: [ "CMD-SHELL", "pg_isready", "-d blocktx", "-U arcuser" ] + interval: 5s + timeout: 5s + retries: 5 + ports: + - '5432:5432' + expose: + - "5432" + networks: + - multicast_bridge + + migrate-blocktx: + container_name: migrate-blocktx + image: migrate/migrate:v4.16.2 + entrypoint: + [ + "migrate", + "-path", + "/migrations", + "-database", + "postgres://arcuser:arcpass@db:5432/main?sslmode=disable&x-migrations-table=blocktx", + ] + command: [ "up" ] + volumes: + - ./internal/blocktx/store/postgresql/migrations:/migrations + depends_on: + db: + condition: service_healthy + restart: on-failure + networks: + - multicast_bridge + + migrate-metamorph: + container_name: migrate-metamorph + image: migrate/migrate:v4.16.2 + entrypoint: + [ + "migrate", + "-path", + "/migrations", + "-database", + "postgres://arcuser:arcpass@db:5432/main?sslmode=disable&x-migrations-table=metamorph", + ] + command: [ "up" ] + volumes: + - ./internal/metamorph/store/postgresql/migrations:/migrations + depends_on: + db: + condition: service_healthy + restart: on-failure + networks: + - multicast_bridge + + migrate-callbacker: + container_name: migrate-callbacker + image: migrate/migrate:v4.16.2 + entrypoint: + [ + "migrate", + "-path", + "/migrations", + "-database", + "postgres://arcuser:arcpass@db:5432/main?sslmode=disable&x-migrations-table=callbacker", + ] + command: [ "up" ] + volumes: + - ./internal/callbacker/store/postgresql/migrations:/migrations + depends_on: + db: + condition: service_healthy + restart: on-failure + networks: + - multicast_bridge + + nats-1: + image: nats:2.10.18-alpine3.20 + container_name: nats-server-1 + restart: on-failure + ports: + - "4222:4222" + hostname: nats-server + volumes: + - nats1-data:/data + - ./test/config/nats-server-host-1.conf:/etc/nats/nats-server.conf + healthcheck: + test: wget http://localhost:8222/healthz -q -S -O - + interval: 5s + timeout: 5s + retries: 5 + networks: + - multicast_bridge + + nats-2: + image: nats:2.10.18-alpine3.20 + container_name: nats-server-2 + restart: on-failure + ports: + - "4223:4222" + hostname: nats-server + volumes: + - nats2-data:/data + - ./test/config/nats-server-host-2.conf:/etc/nats/nats-server.conf + healthcheck: + test: wget http://localhost:8222/healthz -q -S -O - + interval: 5s + timeout: 5s + retries: 5 + networks: + - multicast_bridge + + cache: + image: redis + hostname: redis + ports: + - "6379:6379" + volumes: + - redis-data:/data + healthcheck: + test: [ "CMD", "redis-cli", "ping" ] + networks: + - multicast_bridge + + mcast_sidecar: + build: + context: ./ + dockerfile: ./cmd/mcast/node_sidecar/Dockerfile + volumes: + - ./test/config/config_mcast.yaml:/service/config.yaml + command: [ "./sidecar", "-config=." ] + depends_on: + node1: + condition: service_healthy + node2: + condition: service_healthy + node3: + condition: service_healthy + networks: + - multicast_bridge + + blocktx: + build: ./ + expose: + - "8011" + volumes: + - ./test/config/config_mcast.yaml:/service/config.yaml + command: [ "./arc", "-blocktx=true", "-config=." ] + environment: + - ARC_TRACING_ENABLED + depends_on: + nats-1: + condition: service_healthy + nats-2: + condition: service_healthy + node1: + condition: service_healthy + node2: + condition: service_healthy + node3: + condition: service_healthy + migrate-blocktx: + condition: service_completed_successfully + + healthcheck: + test: ["CMD", "/bin/grpc_health_probe", "-addr=:8006", "-service=liveness", "-rpc-timeout=5s"] + interval: 10s + timeout: 5s + retries: 3 + networks: + - multicast_bridge + + callbacker: + build: ./ + expose: + - "8021" + command: [ "./arc", "-callbacker=true", "-config=." ] + environment: + - ARC_TRACING_ENABLED + volumes: + - ./test/config/config_mcast.yaml:/service/config.yaml + depends_on: + nats-1: + condition: service_healthy + nats-2: + condition: service_healthy + migrate-callbacker: + condition: service_completed_successfully + healthcheck: + test: ["CMD", "/bin/grpc_health_probe", "-addr=:8022", "-service=liveness", "-rpc-timeout=5s"] + interval: 10s + timeout: 5s + retries: 3 + networks: + - multicast_bridge + + metamorph: + build: ./ + expose: + - "8001" + command: [ "./arc", "-metamorph=true", "-config=." ] + environment: + - ARC_TRACING_ENABLED + volumes: + - ./test/config/config_mcast.yaml:/service/config.yaml + depends_on: + blocktx: + condition: service_healthy + callbacker: + condition: service_healthy + cache: + condition: service_healthy + migrate-metamorph: + condition: service_completed_successfully + healthcheck: + test: ["CMD", "/bin/grpc_health_probe", "-addr=:8005", "-service=liveness", "-rpc-timeout=5s"] + interval: 10s + timeout: 5s + retries: 3 + networks: + - multicast_bridge + + api: + build: ./ + ports: + - "8011:8011" + - "9090:9090" + - "9999:9999" + - "2112:2112" + expose: + - "9090" + - "2112" + command: [ "./arc", "-api=true", "-config=." ] + environment: + - ARC_TRACING_ENABLED + volumes: + - ./test/config/config.yaml:/service/config.yaml + depends_on: + metamorph: + condition: service_healthy + networks: + - multicast_bridge + + tests: + build: + context: ./ + dockerfile: ./test/Dockerfile + environment: + - TEST_LOCAL_MCAST=TRUE + depends_on: + - api + networks: + - multicast_bridge + +volumes: + node1-data: + external: false + node2-data: + external: false + node3-data: + external: false + nats1-data: + external: false + nats2-data: + external: false + redis-data: + external: false + +networks: + multicast_bridge: + driver: bridge + enable_ipv6: true + ipam: + driver: default + config: + - subnet: "2001:db8:9::/64" + gateway: "2001:db8:9::1" diff --git a/docker-compose.yaml b/docker-compose.yaml index 6990ce3fd..e135323ef 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -197,6 +197,10 @@ services: volumes: - ./test/config/config.yaml:/service/config.yaml depends_on: + nats-1: + condition: service_healthy + nats-2: + condition: service_healthy migrate-callbacker: condition: service_completed_successfully healthcheck: diff --git a/test/config/config_mcast.yaml b/test/config/config_mcast.yaml new file mode 100644 index 000000000..9a6e8f8ef --- /dev/null +++ b/test/config/config_mcast.yaml @@ -0,0 +1,179 @@ +--- +logFormat: tint +logLevel: INFO +profilerAddr: localhost:9999 +prometheus: + enabled: true + endpoint: /metrics + addr: :2112 +grpcMessageSize: 100000000 +messageQueue: + streaming: + enabled: true + fileStorage: false + URL: nats://nats-1:4222,nats://nats-2:4223 +tracing: + enabled: false + sample: 100 + dialAddr: http://jaeger:4317 + +peerRpc: + password: bitcoin + user: bitcoin + host: node1 + port: 18332 + +cache: + engine: redis + redis: + addr: cache:6379 + password: "" + db: 1 + +metamorph: + listenAddr: "[::]:8001" + dialAddr: metamorph:8001 + db: + mode: postgres + postgres: + host: db + port: 5432 + name: main + user: arcuser + password: arcpass + maxIdleConns: 10 + maxOpenConns: 80 + sslMode: disable + processorCacheExpiryTime: 24h + maxRetries: 1000 + processStatusUpdateInterval: 50ms + monitorPeers: true + checkUtxos: false + profilerAddr: "[::]:9992" + health: + serverDialAddr: "[::]:8005" + minimumHealthyConnections: 2 + rejectCallbackContaining: [ "http://localhost", "https://localhost" ] + stats: + notSeenTimeLimit: 10m + notFinalTimeLimit: 20m + bcnet: + mode: hybrid + network: regtest + peers: + - host: node1 + port: + p2p: 18333 + zmq: 28332 + - host: node2 + port: + p2p: 18333 + zmq: 28332 + - host: node3 + port: + p2p: 18333 + zmq: 28332 + mcast: + tx: + address: "[ff05::1]:9999" + reject: + address: "[ff05::2]:9989" + +blocktx: + listenAddr: "[::]:8011" + dialAddr: blocktx:8011 + healthServerDialAddr: "[::]:8006" + db: + mode: postgres + postgres: + host: db + port: 5432 + name: main + user: arcuser + password: arcpass + maxIdleConns: 10 + maxOpenConns: 80 + sslMode: disable + recordRetentionDays: 28 + profilerAddr: "[::]:9993" + registerTxsInterval: 200ms + fillGaps: + enabled: true + interval: 120s + maxAllowedBlockHeightMismatch: 3 + bcnet: + mode: hybrid + network: regtest + peers: + - host: node1 + port: + p2p: 18333 + zmq: 28332 + - host: node2 + port: + p2p: 18333 + zmq: 28332 + - host: node3 + port: + p2p: 18333 + zmq: 28332 + mcast: + block: + address: "[ff05::3]:9979" + +api: + address: "[::]:9090" + wocApiKey: "mainnet_XXXXXXXXXXXXXXXXXXXX" + wocMainnet: false + requestExtendedLogs: true + processorCacheExpiryTime: 24h + defaultPolicy: + excessiveblocksize: 2000000000 + blockmaxsize: 512000000 + maxtxsizepolicy: 100000000 + maxorphantxsize: 1000000000 + datacarriersize: 4294967295 + maxscriptsizepolicy: 100000000 + maxopsperscriptpolicy: 4294967295 + maxscriptnumlengthpolicy: 10000 + maxpubkeyspermultisigpolicy: 4294967295 + maxtxsigopscountspolicy: 4294967295 + maxstackmemoryusagepolicy: 100000000 + maxstackmemoryusageconsensus: 200000000 + limitancestorcount: 10000 + limitcpfpgroupmemberscount: 25 + maxmempool: 2000000000 + maxmempoolsizedisk: 0 + mempoolmaxpercentcpfp: 10 + acceptnonstdoutputs: true + datacarrier: true + minminingtxfee: 1e-8 + maxstdtxvalidationduration: 3 + maxnonstdtxvalidationduration: 1000 + maxtxchainvalidationbudget: 50 + validationclockcpu: true + minconsolidationfactor: 20 + maxconsolidationinputscriptsize: 150 + minconfconsolidationinput: 6 + minconsolidationinputmaturity: 6 + acceptnonstdconsolidationinput: false + +callbacker: + listenAddr: "[::]:8021" + dialAddr: callbacker:8021 + health: + serverDialAddr: "[::]:8022" + db: + mode: postgres + postgres: + host: db + port: 5432 + name: main + user: arcuser + password: arcpass + maxIdleConns: 10 + maxOpenConns: 80 + sslMode: disable + failedCallbackCheckInterval: 1m + delayDuration: 5s + expiration: 24h diff --git a/test/init_test.go b/test/init_test.go index 061bbab8c..f2b40aa61 100644 --- a/test/init_test.go +++ b/test/init_test.go @@ -20,7 +20,6 @@ func TestMain(m *testing.M) { } log.Printf("current block height: %d", info.Blocks) - os.Exit(m.Run()) } @@ -50,7 +49,10 @@ func setupSut() { if info.Blocks < minNumbeOfBlocks { // generate blocks in part to ensure blocktx is able to process all blocks - const blockBatch = 20 // should be less or equal n*10 where n is number of blocktx instances + blockBatch := float64(20) + if os.Getenv("TEST_LOCAL_MCAST") != "" { + blockBatch = float64(4) + } for { _, err = bitcoind.Generate(blockBatch) @@ -72,6 +74,6 @@ func setupSut() { } } - time.Sleep(5 * time.Second) // wait for fillGaps to fill eventual gaps + time.Sleep(15 * time.Second) // wait for fillGaps to fill eventual gaps } } diff --git a/test/submit_02_batch_test.go b/test/submit_02_batch_test.go index e65b49b15..c43a88866 100644 --- a/test/submit_02_batch_test.go +++ b/test/submit_02_batch_test.go @@ -5,6 +5,7 @@ package test import ( "fmt" "net/http" + "os" "testing" "time" @@ -15,6 +16,10 @@ import ( ) func TestBatchChainedTxs(t *testing.T) { + if os.Getenv("TEST_LOCAL_MCAST") != "" { + t.Skip("Multicasting does't support chained txs yet") + } + t.Run("submit batch of chained transactions", func(t *testing.T) { address, privateKey := node_client.FundNewWallet(t, bitcoind) diff --git a/test/utils.go b/test/utils.go index 76da39afa..17b593964 100644 --- a/test/utils.go +++ b/test/utils.go @@ -301,7 +301,7 @@ func respondToCallback(w http.ResponseWriter, success bool) error { func testTxSubmission(t *testing.T, callbackURL string, token string, callbackBatch bool, tx *sdkTx.Transaction) { t.Helper() - + time.Sleep(100 * time.Millisecond) rawTx, err := tx.EFHex() require.NoError(t, err)