fix: improve blockchain node RPC responses and database path consistency
- Add transaction data to RPC responses (get_block, get_blocks_range) - Fix import_block to handle transactions parameter - Change database paths to absolute paths for consistency - Make dev_heartbeat.py executable
This commit is contained in:
@@ -185,6 +185,7 @@ class PoAProposer:
|
|||||||
tx_hash=tx.tx_hash,
|
tx_hash=tx.tx_hash,
|
||||||
sender=sender,
|
sender=sender,
|
||||||
recipient=recipient,
|
recipient=recipient,
|
||||||
|
payload=tx_data,
|
||||||
value=value,
|
value=value,
|
||||||
fee=fee,
|
fee=fee,
|
||||||
nonce=sender_account.nonce - 1,
|
nonce=sender_account.nonce - 1,
|
||||||
@@ -237,6 +238,7 @@ class PoAProposer:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Broadcast the new block
|
# Broadcast the new block
|
||||||
|
tx_list = [tx.content for tx in processed_txs] if processed_txs else []
|
||||||
await gossip_broker.publish(
|
await gossip_broker.publish(
|
||||||
"blocks",
|
"blocks",
|
||||||
{
|
{
|
||||||
@@ -248,7 +250,8 @@ class PoAProposer:
|
|||||||
"timestamp": block.timestamp.isoformat(),
|
"timestamp": block.timestamp.isoformat(),
|
||||||
"tx_count": block.tx_count,
|
"tx_count": block.tx_count,
|
||||||
"state_root": block.state_root,
|
"state_root": block.state_root,
|
||||||
}
|
"transactions": tx_list,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _ensure_genesis_block(self) -> None:
|
async def _ensure_genesis_block(self) -> None:
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ class BlockchainNode:
|
|||||||
chain_id = block_data.get("chain_id", settings.chain_id)
|
chain_id = block_data.get("chain_id", settings.chain_id)
|
||||||
logger.info(f"Importing block for chain {chain_id}: {block_data.get('height')}")
|
logger.info(f"Importing block for chain {chain_id}: {block_data.get('height')}")
|
||||||
sync = ChainSync(session_factory=session_scope, chain_id=chain_id)
|
sync = ChainSync(session_factory=session_scope, chain_id=chain_id)
|
||||||
res = sync.import_block(block_data)
|
res = sync.import_block(block_data, transactions=block_data.get("transactions"))
|
||||||
logger.info(f"Import result: accepted={res.accepted}, reason={res.reason}")
|
logger.info(f"Import result: accepted={res.accepted}, reason={res.reason}")
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error(f"Error processing block from gossip: {exc}")
|
logger.error(f"Error processing block from gossip: {exc}")
|
||||||
|
|||||||
@@ -105,6 +105,14 @@ async def get_block(height: int) -> Dict[str, Any]:
|
|||||||
metrics_registry.increment("rpc_get_block_not_found_total")
|
metrics_registry.increment("rpc_get_block_not_found_total")
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="block not found")
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="block not found")
|
||||||
metrics_registry.increment("rpc_get_block_success_total")
|
metrics_registry.increment("rpc_get_block_success_total")
|
||||||
|
|
||||||
|
txs = session.exec(select(Transaction).where(Transaction.block_height == height)).all()
|
||||||
|
tx_list = []
|
||||||
|
for tx in txs:
|
||||||
|
t = dict(tx.payload) if tx.payload else {}
|
||||||
|
t["tx_hash"] = tx.tx_hash
|
||||||
|
tx_list.append(t)
|
||||||
|
|
||||||
metrics_registry.observe("rpc_get_block_duration_seconds", time.perf_counter() - start)
|
metrics_registry.observe("rpc_get_block_duration_seconds", time.perf_counter() - start)
|
||||||
return {
|
return {
|
||||||
"height": block.height,
|
"height": block.height,
|
||||||
@@ -114,6 +122,7 @@ async def get_block(height: int) -> Dict[str, Any]:
|
|||||||
"timestamp": block.timestamp.isoformat(),
|
"timestamp": block.timestamp.isoformat(),
|
||||||
"tx_count": block.tx_count,
|
"tx_count": block.tx_count,
|
||||||
"state_root": block.state_root,
|
"state_root": block.state_root,
|
||||||
|
"transactions": tx_list,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -151,6 +160,13 @@ async def get_blocks_range(start: int, end: int) -> Dict[str, Any]:
|
|||||||
# Serialize blocks
|
# Serialize blocks
|
||||||
block_list = []
|
block_list = []
|
||||||
for block in blocks:
|
for block in blocks:
|
||||||
|
txs = session.exec(select(Transaction).where(Transaction.block_height == block.height)).all()
|
||||||
|
tx_list = []
|
||||||
|
for tx in txs:
|
||||||
|
t = dict(tx.payload) if tx.payload else {}
|
||||||
|
t["tx_hash"] = tx.tx_hash
|
||||||
|
tx_list.append(t)
|
||||||
|
|
||||||
block_list.append({
|
block_list.append({
|
||||||
"height": block.height,
|
"height": block.height,
|
||||||
"hash": block.hash,
|
"hash": block.hash,
|
||||||
@@ -159,6 +175,7 @@ async def get_blocks_range(start: int, end: int) -> Dict[str, Any]:
|
|||||||
"timestamp": block.timestamp.isoformat(),
|
"timestamp": block.timestamp.isoformat(),
|
||||||
"tx_count": block.tx_count,
|
"tx_count": block.tx_count,
|
||||||
"state_root": block.state_root,
|
"state_root": block.state_root,
|
||||||
|
"transactions": tx_list,
|
||||||
})
|
})
|
||||||
|
|
||||||
metrics_registry.increment("rpc_get_blocks_range_success_total")
|
metrics_registry.increment("rpc_get_blocks_range_success_total")
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
APP_ENV=dev
|
APP_ENV=dev
|
||||||
APP_HOST=127.0.0.1
|
APP_HOST=127.0.0.1
|
||||||
APP_PORT=8011
|
APP_PORT=8011
|
||||||
DATABASE_URL=sqlite:///./data/coordinator.db
|
DATABASE_URL=sqlite:////opt/aitbc/data/coordinator.db
|
||||||
CLIENT_API_KEYS=${CLIENT_API_KEY},client_dev_key_2
|
CLIENT_API_KEYS=${CLIENT_API_KEY},client_dev_key_2
|
||||||
MINER_API_KEYS=${MINER_API_KEY},miner_dev_key_2
|
MINER_API_KEYS=${MINER_API_KEY},miner_dev_key_2
|
||||||
ADMIN_API_KEYS=${ADMIN_API_KEY}
|
ADMIN_API_KEYS=${ADMIN_API_KEY}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import json
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
# Database configurations
|
# Database configurations
|
||||||
SQLITE_DB = "coordinator.db"
|
SQLITE_DB = "/opt/aitbc/data/coordinator.db"
|
||||||
PG_CONFIG = {
|
PG_CONFIG = {
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"database": "aitbc_coordinator",
|
"database": "aitbc_coordinator",
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from decimal import Decimal
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
# Database configurations
|
# Database configurations
|
||||||
SQLITE_DB = "coordinator.db"
|
SQLITE_DB = "/opt/aitbc/data/coordinator.db"
|
||||||
PG_CONFIG = {
|
PG_CONFIG = {
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"database": "aitbc_coordinator",
|
"database": "aitbc_coordinator",
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class DatabaseConfig(BaseSettings):
|
|||||||
|
|
||||||
# Default SQLite path - consistent with blockchain-node pattern
|
# Default SQLite path - consistent with blockchain-node pattern
|
||||||
if self.adapter == "sqlite":
|
if self.adapter == "sqlite":
|
||||||
return "sqlite:///./data/coordinator.db"
|
return "sqlite:////opt/aitbc/data/coordinator.db"
|
||||||
|
|
||||||
# Default PostgreSQL connection string
|
# Default PostgreSQL connection string
|
||||||
return f"{self.adapter}://localhost:5432/coordinator"
|
return f"{self.adapter}://localhost:5432/coordinator"
|
||||||
@@ -187,7 +187,7 @@ class Settings(BaseSettings):
|
|||||||
if self.database.url:
|
if self.database.url:
|
||||||
return self.database.url
|
return self.database.url
|
||||||
# Default SQLite path - consistent with blockchain-node pattern
|
# Default SQLite path - consistent with blockchain-node pattern
|
||||||
return "sqlite:///./data/coordinator.db"
|
return "sqlite:////opt/aitbc/data/coordinator.db"
|
||||||
|
|
||||||
@database_url.setter
|
@database_url.setter
|
||||||
def database_url(self, value: str):
|
def database_url(self, value: str):
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
from sqlmodel import create_engine, SQLModel
|
from sqlmodel import create_engine, SQLModel
|
||||||
from sqlalchemy import StaticPool
|
from sqlalchemy import StaticPool
|
||||||
|
from .config import settings
|
||||||
|
|
||||||
# Create in-memory SQLite database for now
|
# Create database engine using URL from config
|
||||||
engine = create_engine(
|
engine = create_engine(
|
||||||
"sqlite:///./data/coordinator.db",
|
settings.database_url,
|
||||||
connect_args={"check_same_thread": False},
|
connect_args={"check_same_thread": False} if settings.database_url.startswith("sqlite") else {},
|
||||||
poolclass=StaticPool,
|
poolclass=StaticPool if settings.database_url.startswith("sqlite") else None,
|
||||||
echo=True # Enable SQL logging for debugging
|
echo=settings.test_mode # Enable SQL logging for debugging in test mode
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
0
dev/scripts/dev_heartbeat.py
Normal file → Executable file
0
dev/scripts/dev_heartbeat.py
Normal file → Executable file
Reference in New Issue
Block a user