mirror of
https://github.com/logos-blockchain/logos-blockchain-block-explorer-template.git
synced 2026-08-08 15:13:13 +00:00
Handle unknown operations in explorer
This commit is contained in:
parent
44043b8c1a
commit
527873c8c6
@ -85,6 +85,20 @@ class LeaderClaim(NbeContent):
|
||||
mantle_tx_hash: HexBytes
|
||||
|
||||
|
||||
class UnknownOp(NbeContent):
|
||||
type: Literal["UnknownOp"] = "UnknownOp"
|
||||
opcode: int | str
|
||||
raw_payload: dict | str
|
||||
|
||||
|
||||
OperationContent = (
|
||||
LedgerTransfer | ChannelInscribe | ChannelBlob | ChannelSetKeys | SDPDeclare | SDPWithdraw | SDPActive | LeaderClaim
|
||||
LedgerTransfer
|
||||
| ChannelInscribe
|
||||
| ChannelBlob
|
||||
| ChannelSetKeys
|
||||
| SDPDeclare
|
||||
| SDPWithdraw
|
||||
| SDPActive
|
||||
| LeaderClaim
|
||||
| UnknownOp
|
||||
)
|
||||
|
||||
@ -31,4 +31,9 @@ class ZkAndEd25519Signature(NbeSignature):
|
||||
ed25519_signature: HexBytes
|
||||
|
||||
|
||||
OperationProof = Ed25519Signature | ZkSignature | ZkAndEd25519Signature
|
||||
class UnknownSignature(NbeSignature):
|
||||
type: Literal["Unknown"] = "Unknown"
|
||||
signature: HexBytes
|
||||
|
||||
|
||||
OperationProof = Ed25519Signature | ZkSignature | ZkAndEd25519Signature | UnknownSignature
|
||||
|
||||
@ -51,6 +51,11 @@ class ChannelInscribeOpSerializer(NbeSerializer, FromRandom):
|
||||
}
|
||||
)
|
||||
|
||||
class UnknownOpSerializer(NbeSerializer):
|
||||
"""Fallback serializer for unrecognized opcodes."""
|
||||
opcode: int
|
||||
payload: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
OPCODE_TO_SERIALIZER: dict[int, type] = {
|
||||
OPCODE_LEDGER: LedgerOpSerializer,
|
||||
@ -58,19 +63,17 @@ OPCODE_TO_SERIALIZER: dict[int, type] = {
|
||||
}
|
||||
|
||||
|
||||
def _parse_mantle_op(data: Any) -> Union[LedgerOpSerializer, ChannelInscribeOpSerializer]:
|
||||
if isinstance(data, (LedgerOpSerializer, ChannelInscribeOpSerializer)):
|
||||
def _parse_mantle_op(data: Any) -> Any:
|
||||
if isinstance(data, (LedgerOpSerializer, ChannelInscribeOpSerializer, UnknownOpSerializer)):
|
||||
return data
|
||||
if isinstance(data, dict) and "opcode" in data:
|
||||
opcode = data["opcode"]
|
||||
serializer_class = OPCODE_TO_SERIALIZER.get(opcode)
|
||||
if serializer_class is None:
|
||||
raise ValueError(
|
||||
f"Unsupported mantle op opcode {opcode}; known opcodes: {sorted(OPCODE_TO_SERIALIZER)}."
|
||||
)
|
||||
return UnknownOpSerializer(opcode=opcode, payload=data.get("payload", {}))
|
||||
return serializer_class.model_validate(data["payload"])
|
||||
raise ValueError(f"Cannot parse mantle op from {type(data).__name__}.")
|
||||
|
||||
|
||||
MantleOpSerializerVariants = Union[LedgerOpSerializer, ChannelInscribeOpSerializer]
|
||||
MantleOpSerializerVariants = Union[LedgerOpSerializer, ChannelInscribeOpSerializer, UnknownOpSerializer]
|
||||
MantleOpSerializerField = Annotated[MantleOpSerializerVariants, BeforeValidator(_parse_mantle_op)]
|
||||
|
||||
@ -80,7 +80,18 @@ class SignedTransactionSerializer(NbeSerializer, FromRandom):
|
||||
}
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Unsupported mantle op type: {type(op).__name__}")
|
||||
# Gracefully handle unknown ops. We assume that whatever comes from the node is correct.
|
||||
operations.append({
|
||||
"content": {
|
||||
"type": "UnknownOp",
|
||||
"opcode": getattr(op, "opcode", "unknown"),
|
||||
"raw_payload": op.model_dump() if hasattr(op, "model_dump") else str(op),
|
||||
},
|
||||
"proof": {
|
||||
"type": "Unknown",
|
||||
"signature": proof.to_bytes() if hasattr(proof, "to_bytes") else getattr(proof, "root", b""),
|
||||
},
|
||||
})
|
||||
|
||||
return Transaction.model_validate(
|
||||
{
|
||||
|
||||
37
tests/test_transaction_models.py
Normal file
37
tests/test_transaction_models.py
Normal file
@ -0,0 +1,37 @@
|
||||
import pytest
|
||||
from models.transactions.transaction import Transaction
|
||||
from core.types import HexBytes
|
||||
|
||||
def test_transaction_validation_with_unknown_types():
|
||||
# This data simulates what is produced by SignedTransactionSerializer.into_transaction()
|
||||
# when it encounters unknown opcodes or proofs.
|
||||
transaction_data = {
|
||||
"hash": HexBytes(b"\x01" * 32),
|
||||
"operations": [
|
||||
{
|
||||
"content": {
|
||||
"type": "UnknownOp",
|
||||
"opcode": 123,
|
||||
"raw_payload": {"some": "data"}
|
||||
},
|
||||
"proof": {
|
||||
"type": "Unknown",
|
||||
"signature": HexBytes(b"\x02" * 64)
|
||||
}
|
||||
}
|
||||
],
|
||||
"execution_gas_price": 100,
|
||||
"storage_gas_price": 200
|
||||
}
|
||||
|
||||
tx = Transaction.model_validate(transaction_data)
|
||||
|
||||
assert tx.hash == HexBytes(b"\x01" * 32)
|
||||
assert tx.operations[0].content.type == "UnknownOp"
|
||||
assert tx.operations[0].content.opcode == 123
|
||||
assert tx.operations[0].proof.type == "Unknown"
|
||||
assert tx.operations[0].proof.signature == HexBytes(b"\x02" * 64)
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_transaction_validation_with_unknown_types()
|
||||
print("Test passed!")
|
||||
Loading…
x
Reference in New Issue
Block a user