Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions config/provider_examples/sonic_provider_with_addons.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
endpoints:
- api-interface: jsonrpc
chain-id: SONIC
network-address:
address: "127.0.0.1:2221"
node-urls:
# Sonic public RPC with trace support
# Note: Public endpoints typically don't support debug APIs (too resource-intensive)
- url: https://rpc.soniclabs.com/
addons:
- trace
# Sonic public WebSocket RPC with trace support
- url: wss://sonic-rpc.publicnode.com/
addons:
- trace
36 changes: 36 additions & 0 deletions cookbook/projects/policy_sonic_with_addons.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Policy configuration for Sonic with debug and trace add-on support
#
# Note: Debug add-on requires a dedicated/private RPC node with debug APIs enabled.
# Public RPC endpoints typically don't support debug APIs (too resource-intensive).
# The trace add-on works with most public Sonic RPC endpoints.
#
# selected_providers_mode:
# ALLOWED = 0; // no providers restrictions
# MIXED = 1; // use the selected providers mixed with randomly chosen providers
# EXCLUSIVE = 2; // use only the selected providers
# DISABLED = 3; // selected providers feature is disabled

Policy:
geolocation_profile: 1 # USC
total_cu_limit: 9223372036854775807
epoch_cu_limit: 9223372036854775807
max_providers_to_pair: 9223372036854775807
selected_providers_mode: ALLOWED
chain_policies:
- chain_id: SONIC
requirements:
- collection:
api_interface: "jsonrpc"
type: "POST"
add_on: "debug"
- collection:
api_interface: "jsonrpc"
type: "POST"
add_on: "trace"
- collection:
api_interface: "jsonrpc"
type: "POST"
extensions:
- "archive"
mixed: true
- chain_id: "*" # allows all other chains without specifying
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ func TestGRPCParseBlock(t *testing.T) {
input: "0x26D",
expected: 621,
},
{
name: "Ripple validated block param",
input: "validated",
expected: -6,
},
}

for _, testCase := range testTable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ func TestJsonrpcMessage_ParseBlock(t *testing.T) {
input: "0x26D",
expected: 621,
},
{
name: "Ripple validated block param",
input: "validated",
expected: -6,
},
}

for _, testCase := range testTable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ func TestRestParseBlock(t *testing.T) {
input: "0x26D",
expected: 621,
},
{
name: "Ripple validated block param",
input: "validated",
expected: -6,
},
}

for _, testCase := range testTable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ func TestTendermintrpcMessage_ParseBlock(t *testing.T) {
input: "0x26D",
expected: 621,
},
{
name: "Ripple validated block param",
input: "validated",
expected: -6,
},
}

for _, testCase := range testTable {
Expand Down
14 changes: 14 additions & 0 deletions protocol/chainlib/node_error_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,20 @@ func (geh *genericErrorHandler) ValidateRequestAndResponseIds(nodeMessageID json
if idErr != nil {
return fmt.Errorf("failed parsing ID %s", idErr.Error())
}

// Allow empty/missing response ID for non-standard JSON-RPC implementations (e.g., XRPL/Ripple)
// Some chains don't follow JSON-RPC 2.0 spec strictly and omit the ID field in responses
//
// TODO: In the future, add a spec-level parameter (e.g., in api_collection or as an add-on flag)
// to explicitly declare when a chain allows non-standard JSON-RPC responses. This validation
// function should check that parameter instead of auto-detecting missing IDs.
// Example: "allow_missing_response_id": true in the spec's collection_data
// Not implemented now because it requires a software upgrade on-chain (spec schema change)
// and governance approval to update existing specs.
if len(replyMsgID) == 0 || string(replyMsgID) == "null" || string(replyMsgID) == "[]" {
return nil // Skip ID validation when response has no ID
}

respId, idErr := rpcInterfaceMessages.IdFromRawMessage(replyMsgID)
if idErr != nil {
return fmt.Errorf("failed parsing ID %s", idErr.Error())
Expand Down
3 changes: 3 additions & 0 deletions protocol/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ func ParseDefaultBlockParameter(block string) (int64, error) {
return spectypes.SAFE_BLOCK, nil
case "finalized":
return spectypes.FINALIZED_BLOCK, nil
case "validated":
// Ripple uses "validated" for validated ledgers (similar to finalized)
return spectypes.FINALIZED_BLOCK, nil
default:
// try to parse a number
}
Expand Down
67 changes: 67 additions & 0 deletions scripts/pre_setups/init_fantom_main.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/bin/bash
__dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
source "$__dir"/../useful_commands.sh
. "${__dir}"/../vars/variables.sh

LOGS_DIR=${__dir}/../../testutil/debugging/logs
mkdir -p $LOGS_DIR
rm $LOGS_DIR/*.log

killall screen
screen -wipe

echo "[Test Setup] installing all binaries"
make install-all

echo "[Test Setup] setting up a new lava node"
screen -d -m -S node bash -c "./scripts/start_env_dev.sh"
screen -ls
echo "[Test Setup] sleeping 20 seconds for node to finish setup (if its not enough increase timeout)"
sleep 5
wait_for_lava_node_to_start

GASPRICE="0.00002ulava"
# IMPORTANT: Ethereum MUST come before Fantom because Fantom imports ETH1
# NOTE: Using fantom_mainnet_only.json to avoid circular dependency with testnet spec in same proposal
specs="specs/mainnet-1/specs/ibc.json,specs/mainnet-1/specs/cosmoswasm.json,specs/mainnet-1/specs/tendermint.json,specs/mainnet-1/specs/cosmossdk.json,specs/testnet-2/specs/lava.json,specs/mainnet-1/specs/ethereum.json,specs/mainnet-1/specs/stellar.json,specs/mainnet-1/specs/fantom.json"

echo "[Test Setup] Submitting spec-add proposal..."
lavad tx gov submit-legacy-proposal spec-add $specs --lava-dev-test -y --from alice --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE
wait_next_block
wait_next_block
echo "[Test Setup] Voting on spec proposal #1..."
lavad tx gov vote 1 yes -y --from alice --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE
wait_next_block

# Plans proposal
echo "[Test Setup] Submitting plans-add proposal..."
lavad tx gov submit-legacy-proposal plans-add ./cookbook/plans/test_plans/default.json,./cookbook/plans/test_plans/temporary-add.json -y --from alice --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE
wait_next_block
wait_next_block
echo "[Test Setup] Voting on plan proposal #2..."
lavad tx gov vote 2 yes -y --from alice --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE
wait_next_block

sleep 4

CLIENTSTAKE="500000000000ulava"
PROVIDERSTAKE="500000000000ulava"

PROVIDER1_LISTENER="127.0.0.1:2220"

lavad tx subscription buy DefaultPlan $(lavad keys show user1 -a) -y --from user1 --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE
wait_next_block
lavad tx pairing stake-provider "FTM250" $PROVIDERSTAKE "$PROVIDER1_LISTENER,1,jsonrpc" 1 $(operator_address) -y --from servicer1 --provider-moniker "dummyMoniker" --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE

sleep_until_next_epoch

screen -d -m -S provider1 bash -c "source ~/.bashrc; lavap rpcprovider \
$PROVIDER1_LISTENER FTM250 jsonrpc 'https://rpcapi.fantom.network/,wss://fantom.drpc.org' \
$EXTRA_PROVIDER_FLAGS --geolocation 1 --log_level debug --from servicer1 --chain-id lava --metrics-listen-address ":7776" 2>&1 | tee $LOGS_DIR/PROVIDER1.log" && sleep 0.25

screen -d -m -S consumers bash -c "source ~/.bashrc; lavap rpcconsumer \
127.0.0.1:3360 FTM250 jsonrpc \
$EXTRA_PORTAL_FLAGS --geolocation 1 --log_level debug --from user1 --chain-id lava --allow-insecure-provider-dialing --metrics-listen-address ":7779" 2>&1 | tee $LOGS_DIR/CONSUMERS.log" && sleep 0.25

echo "--- setting up screens done ---"
screen -ls
141 changes: 141 additions & 0 deletions scripts/pre_setups/init_ripple_main.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#!/bin/bash
# init_stellar_main.sh - Setup Lava with Stellar provider using JSON-RPC interface
# This script tests the JSON-RPC parameters fix with Stellar using JSON-RPC protocol
#
# Purpose: Verify that the fix correctly omits params field for no-parameter JSON-RPC methods
# Expected: Stellar-RPC accepts requests from Lava provider with correct parameter format
#
# Usage: bash scripts/pre_setups/init_stellar_main.sh

__dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
source "$__dir"/../useful_commands.sh
. "${__dir}"/../vars/variables.sh

LOGS_DIR=${__dir}/../../testutil/debugging/logs
mkdir -p $LOGS_DIR
rm -f $LOGS_DIR/*.log

killall screen
screen -wipe

echo "[Test Setup] Installing binaries..."
make install-all

echo "[Test Setup] Setting up a new lava node"
screen -d -m -S node bash -c "./scripts/start_env_dev.sh"
screen -ls
echo "[Test Setup] Waiting for node to finish setup..."
sleep 5
wait_for_lava_node_to_start
echo "[Test Setup] Lava node started successfully"

GASPRICE="0.00002ulava"

echo "[Test Setup] Adding Stellar spec (with JSON-RPC support)..."
# Use only essential specs to avoid validation issues with uncommitted code changes
# Including: Lava chain spec + Cosmos base specs + Stellar
specs="specs/mainnet-1/specs/ibc.json,specs/mainnet-1/specs/cosmoswasm.json,specs/mainnet-1/specs/tendermint.json,specs/mainnet-1/specs/cosmossdk.json,specs/testnet-2/specs/lava.json,specs/mainnet-1/specs/stellar.json,specs/mainnet-1/specs/ripple.json"
echo "[Test Setup] Submitting spec-add proposal (Lava + Stellar specs)..."
lavad tx gov submit-legacy-proposal spec-add $specs --lava-dev-test -y --from alice --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE
if [ $? -ne 0 ]; then
echo "ERROR: Failed to submit spec-add proposal"
exit 1
fi
echo "[Test Setup] Spec proposal submitted successfully, waiting for blocks..."
wait_next_block
wait_next_block
echo "[Test Setup] Voting on spec proposal #1..."
lavad tx gov vote 1 yes -y --from alice --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE
if [ $? -ne 0 ]; then
echo "ERROR: Failed to vote on spec proposal"
exit 1
fi
wait_next_block

echo "[Test Setup] Adding default plan..."
lavad tx gov submit-legacy-proposal plans-add ./cookbook/plans/test_plans/default.json -y --from alice --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE
if [ $? -ne 0 ]; then
echo "ERROR: Failed to submit plans-add proposal"
exit 1
fi
wait_next_block
wait_next_block
echo "[Test Setup] Voting on plan proposal #2..."
lavad tx gov vote 2 yes -y --from alice --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE
if [ $? -ne 0 ]; then
echo "ERROR: Failed to vote on plan proposal"
exit 1
fi

sleep 4

CLIENTSTAKE="500000000000ulava"
PROVIDERSTAKE="500000000000ulava"

PROVIDER1_LISTENER="127.0.0.1:2220"

echo "[Test Setup] Setting up subscription and provider stake..."
lavad tx subscription buy DefaultPlan $(lavad keys show user1 -a) -y --from user1 --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE
wait_next_block

lavad tx pairing stake-provider "XRP" $PROVIDERSTAKE "$PROVIDER1_LISTENER,1,jsonrpc" 1 $(operator_address) -y --from servicer1 --provider-moniker "Ripple-JSON-RPC-Provider" --gas-adjustment "1.5" --gas "auto" --gas-prices $GASPRICE

sleep_until_next_epoch
wait_next_block

echo "[Test Setup] Starting Ripple JSON-RPC Provider..."
echo " Using public Ripple JSON-RPC endpoint: https://ripple.drpc.org"
echo " Testing JSON-RPC interface (exercises the parameters fix)"
screen -d -m -S provider1 bash -c "source ~/.bashrc; lavap rpcprovider \
$PROVIDER1_LISTENER XRP jsonrpc 'https://s2.ripple.com:51234/,wss://s1.ripple.com/' \
$EXTRA_PROVIDER_FLAGS --geolocation 1 --log_level debug --from servicer1 2>&1 | tee $LOGS_DIR/PROVIDER1_RIPPLE_JSONRPC.log" && sleep 2

wait_next_block

echo "[Test Setup] Starting Ripple Consumer..."
screen -d -m -S consumers bash -c "source ~/.bashrc; lavap rpcconsumer \
127.0.0.1:3360 XRP jsonrpc \
$EXTRA_PORTAL_FLAGS --geolocation 1 --log_level trace --from user1 --allow-insecure-provider-dialing 2>&1 | tee $LOGS_DIR/CONSUMERS_RIPPLE.log" && sleep 0.25

echo ""
echo "==================================================================="
echo "✅ Setup complete - Ripple JSON-RPC Test Environment Ready"
echo "==================================================================="
echo ""
echo "Active screens:"
screen -ls
echo ""
echo "Provider logs:"
echo " tail -f $LOGS_DIR/PROVIDER1_RIPPLE_JSONRPC.log"
echo ""
echo "Consumer logs:"
echo " tail -f $LOGS_DIR/CONSUMERS_RIPPLE.log"
echo ""
echo "Testing the JSON-RPC parameters fix:"
echo "======================================"
echo ""
echo "The fix is in the JSON-RPC layer (client.go:301):"
echo " - Converts nil params → passes nil (not [])"
echo " - omitempty tag omits 'params' field from JSON"
echo " - Ripple-RPC accepts requests without 'params' field"
echo ""
echo "Example test request (no parameters):"
echo " curl -X POST http://127.0.0.1:3360 \\"
echo " -H 'Content-Type: application/json' \\"
echo " -d '{\"jsonrpc\":\"2.0\",\"method\":\"getLatestLedger\",\"id\":1}'"
echo ""
echo "Success indicators:"
echo " ✅ Request succeeds (no 'params' related errors)"
echo " ✅ Provider shows successful relay"
echo " ✅ Ripple-RPC accepts the request"
echo " ✅ Logs show JSON-RPC requests handled correctly"
echo ""
echo "To monitor parameter handling:"
echo " - Check provider logs for JSON-RPC requests"
echo " - Requests should NOT have 'params' field (for no-param methods)"
echo " - OR should have 'params' exactly as sent by client"
echo " - Should NOT have 'params':null"
echo ""
echo "To stop everything:"
echo " killall screen"
echo ""
Loading
Loading