├── src ├── xian │ ├── __init__.py │ ├── utils │ │ ├── __init__.py │ │ ├── hash.py │ │ ├── cometbft.py │ │ └── encoding.py │ ├── tools │ │ ├── .gitignore │ │ ├── genesis │ │ │ └── contracts │ │ │ │ ├── __init__.py │ │ │ │ ├── stamp_cost.s.py │ │ │ │ ├── foundation.s.py │ │ │ │ ├── rewards.s.py │ │ │ │ ├── contracts_local.json │ │ │ │ ├── contracts_devnet.json │ │ │ │ ├── contracts_stagenet.json │ │ │ │ ├── contracts_testnet.json │ │ │ │ ├── dao.s.py │ │ │ │ └── contracts_rcnet.json │ │ ├── state_patches │ │ │ ├── state_patches_example.json │ │ │ └── state_patches.json │ │ ├── update_abci_json.py │ │ ├── validator_gen.py │ │ ├── export_state.py │ │ └── genesis_upgrades │ │ │ └── approvals_upgrade.py │ ├── exceptions.py │ ├── services │ │ └── bds │ │ │ ├── config.json │ │ │ ├── config.py │ │ │ └── database.py │ ├── methods │ │ ├── echo.py │ │ ├── prepare_proposal.py │ │ ├── process_proposal.py │ │ ├── info.py │ │ ├── init_chain.py │ │ ├── commit.py │ │ └── check_tx.py │ ├── constants.py │ ├── validators.py │ ├── formatting.py │ └── nonce.py ├── gogoproto │ └── __init__.py ├── tendermint │ ├── __init__.py │ ├── abci │ │ └── __init__.py │ ├── crypto │ │ ├── __init__.py │ │ └── keys_pb2.py │ ├── types │ │ └── __init__.py │ └── version │ │ └── __init__.py ├── abci │ ├── __init__.py │ └── utils.py └── cometbft │ ├── services │ ├── version │ │ └── v1 │ │ │ └── version_service_pb2.py │ ├── block_results │ │ └── v1 │ │ │ └── block_results_service_pb2.py │ └── block │ │ └── v1 │ │ └── block_service_pb2.py │ ├── libs │ └── bits │ │ └── v1 │ │ └── types_pb2.py │ ├── store │ └── v1 │ │ └── types_pb2.py │ ├── types │ ├── v1 │ │ └── events_pb2.py │ └── v1beta1 │ │ └── events_pb2.py │ ├── crypto │ └── v1 │ │ └── keys_pb2.py │ └── mempool │ └── v1 │ └── types_pb2.py ├── setup.py ├── tests ├── abci_methods │ ├── fixtures │ │ ├── .cometbft-fixture │ │ │ ├── data │ │ │ │ └── priv_validator_state.json │ │ │ └── config │ │ │ │ ├── node_key.json │ │ │ │ ├── priv_validator_key.json │ │ │ │ └── config.toml │ │ └── mock_constants.py │ ├── utils.py │ ├── test_commit.py │ └── test_info.py ├── governance │ ├── fixtures │ │ ├── .cometbft-fixture │ │ │ ├── data │ │ │ │ └── priv_validator_state.json │ │ │ └── config │ │ │ │ ├── node_key.json │ │ │ │ ├── priv_validator_key.json │ │ │ │ └── config.toml │ │ └── mock_constants.py │ └── utils.py ├── integration │ ├── fixtures │ │ ├── .cometbft-fixture │ │ │ ├── data │ │ │ │ └── priv_validator_state.json │ │ │ └── config │ │ │ │ ├── node_key.json │ │ │ │ ├── priv_validator_key.json │ │ │ │ └── config.toml │ │ └── mock_constants.py │ ├── contracts │ │ ├── proxy.py │ │ ├── rollback │ │ │ ├── con_mutator.py │ │ │ ├── con_mutator_fail.py │ │ │ ├── con_overdraw_fail.py │ │ │ ├── con_mutable_map.py │ │ │ └── currency_1.py │ │ └── token_contract.py │ └── utils.py └── xian-tests.md ├── pyproject.toml ├── protos ├── cometbft │ ├── libs │ │ └── bits │ │ │ └── v1 │ │ │ └── types.proto │ ├── store │ │ └── v1 │ │ │ └── types.proto │ ├── types │ │ ├── v1 │ │ │ ├── events.proto │ │ │ ├── block.proto │ │ │ ├── evidence.proto │ │ │ ├── validator.proto │ │ │ └── canonical.proto │ │ ├── v1beta1 │ │ │ ├── events.proto │ │ │ ├── block.proto │ │ │ ├── evidence.proto │ │ │ ├── validator.proto │ │ │ ├── canonical.proto │ │ │ └── params.proto │ │ └── v1beta2 │ │ │ └── params.proto │ ├── mempool │ │ └── v1 │ │ │ └── types.proto │ ├── crypto │ │ └── v1 │ │ │ ├── keys.proto │ │ │ └── proof.proto │ ├── services │ │ ├── block_results │ │ │ └── v1 │ │ │ │ ├── block_results_service.proto │ │ │ │ └── block_results.proto │ │ ├── version │ │ │ └── v1 │ │ │ │ ├── version.proto │ │ │ │ └── version_service.proto │ │ ├── block │ │ │ └── v1 │ │ │ │ ├── block_service.proto │ │ │ │ └── block.proto │ │ └── pruning │ │ │ └── v1 │ │ │ ├── pruning.proto │ │ │ └── service.proto │ ├── p2p │ │ └── v1 │ │ │ ├── pex.proto │ │ │ ├── conn.proto │ │ │ └── types.proto │ ├── version │ │ └── v1 │ │ │ └── types.proto │ ├── rpc │ │ └── grpc │ │ │ ├── v1beta2 │ │ │ └── types.proto │ │ │ ├── v1beta3 │ │ │ └── types.proto │ │ │ └── v1beta1 │ │ │ └── types.proto │ ├── statesync │ │ └── v1 │ │ │ └── types.proto │ ├── blocksync │ │ ├── v1beta1 │ │ │ └── types.proto │ │ └── v1 │ │ │ └── types.proto │ ├── consensus │ │ ├── v1beta1 │ │ │ ├── wal.proto │ │ │ └── types.proto │ │ └── v1 │ │ │ ├── wal.proto │ │ │ └── types.proto │ ├── abci │ │ └── v1 │ │ │ └── service.proto │ ├── privval │ │ ├── v1 │ │ │ └── types.proto │ │ ├── v1beta2 │ │ │ └── types.proto │ │ └── v1beta1 │ │ │ └── types.proto │ └── state │ │ ├── v1beta2 │ │ └── types.proto │ │ └── v1beta1 │ │ └── types.proto ├── buf.lock ├── tendermint │ ├── crypto │ │ ├── keys.proto │ │ └── proof.proto │ ├── version │ │ └── types.proto │ └── types │ │ ├── validator.proto │ │ └── params.proto ├── buf.yaml └── README.md ├── .github ├── dependabot.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── main.yml ├── README.md ├── Makefile ├── setup.cfg └── .gitignore /src/xian/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/gogoproto/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tendermint/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/xian/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tendermint/abci/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tendermint/crypto/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tendermint/types/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tendermint/version/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/xian/tools/.gitignore: -------------------------------------------------------------------------------- 1 | priv_validator_key.json -------------------------------------------------------------------------------- /src/xian/tools/genesis/contracts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup() 4 | -------------------------------------------------------------------------------- /src/abci/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ABCI 3 | """ 4 | __version__ = "0.8.4" 5 | -------------------------------------------------------------------------------- /src/xian/exceptions.py: -------------------------------------------------------------------------------- 1 | class TransactionException(Exception): 2 | pass 3 | -------------------------------------------------------------------------------- /tests/abci_methods/fixtures/.cometbft-fixture/data/priv_validator_state.json: -------------------------------------------------------------------------------- 1 | { 2 | "height": "0", 3 | "round": 0, 4 | "step": 0 5 | } -------------------------------------------------------------------------------- /tests/governance/fixtures/.cometbft-fixture/data/priv_validator_state.json: -------------------------------------------------------------------------------- 1 | { 2 | "height": "0", 3 | "round": 0, 4 | "step": 0 5 | } -------------------------------------------------------------------------------- /tests/integration/fixtures/.cometbft-fixture/data/priv_validator_state.json: -------------------------------------------------------------------------------- 1 | { 2 | "height": "0", 3 | "round": 0, 4 | "step": 0 5 | } -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [tool.black] 6 | line-length = 80 7 | -------------------------------------------------------------------------------- /src/xian/services/bds/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "db_host": "postgres", 3 | "db_name": "xian", 4 | "db_pass": "1234", 5 | "db_port": 5432, 6 | "db_user": "postgres" 7 | } -------------------------------------------------------------------------------- /src/xian/methods/echo.py: -------------------------------------------------------------------------------- 1 | from cometbft.abci.v1beta1.types_pb2 import ResponseEcho 2 | 3 | 4 | async def echo(self, req) -> ResponseEcho: 5 | r = ResponseEcho() 6 | return r 7 | -------------------------------------------------------------------------------- /tests/governance/fixtures/.cometbft-fixture/config/node_key.json: -------------------------------------------------------------------------------- 1 | {"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"LkU6GdFIIRx0OZwahaoYbbtL88C7NYdz+d25LXFiLYgvFgxO8SRiJIBhhfv+7ErL2yrG68h2UzONt87R7XgHCw=="}} -------------------------------------------------------------------------------- /tests/integration/fixtures/.cometbft-fixture/config/node_key.json: -------------------------------------------------------------------------------- 1 | {"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"LkU6GdFIIRx0OZwahaoYbbtL88C7NYdz+d25LXFiLYgvFgxO8SRiJIBhhfv+7ErL2yrG68h2UzONt87R7XgHCw=="}} -------------------------------------------------------------------------------- /tests/abci_methods/fixtures/.cometbft-fixture/config/node_key.json: -------------------------------------------------------------------------------- 1 | {"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"LkU6GdFIIRx0OZwahaoYbbtL88C7NYdz+d25LXFiLYgvFgxO8SRiJIBhhfv+7ErL2yrG68h2UzONt87R7XgHCw=="}} -------------------------------------------------------------------------------- /src/xian/methods/prepare_proposal.py: -------------------------------------------------------------------------------- 1 | from cometbft.abci.v1beta2.types_pb2 import ResponsePrepareProposal 2 | 3 | 4 | async def prepare_proposal(self, req) -> ResponsePrepareProposal: 5 | response = ResponsePrepareProposal(txs=req.txs) 6 | return response 7 | -------------------------------------------------------------------------------- /tests/integration/contracts/proxy.py: -------------------------------------------------------------------------------- 1 | import currency_1 2 | 3 | def transfer(amount: float, to: str): 4 | return currency_1.transfer(amount, to) 5 | 6 | @export 7 | def send_multiple(amount: float, to: list): 8 | for t in to: 9 | currency_1.transfer(amount, t) 10 | -------------------------------------------------------------------------------- /protos/cometbft/libs/bits/v1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.libs.bits.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/libs/bits/v1"; 5 | 6 | // BitArray is an array of bits. 7 | message BitArray { 8 | int64 bits = 1; 9 | repeated uint64 elems = 2; 10 | } 11 | -------------------------------------------------------------------------------- /src/xian/methods/process_proposal.py: -------------------------------------------------------------------------------- 1 | from cometbft.abci.v1beta2.types_pb2 import ResponseProcessProposal 2 | 3 | 4 | async def process_proposal(self, req) -> ResponseProcessProposal: 5 | response = ResponseProcessProposal() 6 | response.status = ResponseProcessProposal.ProposalStatus.ACCEPT 7 | return response 8 | -------------------------------------------------------------------------------- /protos/cometbft/store/v1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.store.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/store/v1"; 5 | 6 | // BlockStoreState represents the state of the block store. 7 | message BlockStoreState { 8 | int64 base = 1; 9 | int64 height = 2; 10 | } 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "pip" # Type of package ecosystem (e.g., "npm", "maven") 4 | directory: "/" # Location of package manifests 5 | schedule: 6 | interval: "daily" # How often to check for updates 7 | open-pull-requests-limit: 10 # Maximum number of open pull requests Dependabot should have -------------------------------------------------------------------------------- /protos/buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: cosmos 6 | repository: gogo-proto 7 | commit: 5e5b9fdd01804356895f8f79a6f1ddc1 8 | digest: shake256:0b85da49e2e5f9ebc4806eae058e2f56096ff3b1c59d1fb7c190413dd15f45dd456f0b69ced9059341c80795d2b6c943de15b120a9e0308b499e43e4b5fc2952 9 | -------------------------------------------------------------------------------- /protos/cometbft/types/v1/events.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.types.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1"; 5 | 6 | // EventDataRoundState is emitted with each new round step. 7 | message EventDataRoundState { 8 | int64 height = 1; 9 | int32 round = 2; 10 | string step = 3; 11 | } 12 | -------------------------------------------------------------------------------- /protos/cometbft/types/v1beta1/events.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.types.v1beta1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; 5 | 6 | // EventDataRoundState is emitted with each new round step. 7 | message EventDataRoundState { 8 | int64 height = 1; 9 | int32 round = 2; 10 | string step = 3; 11 | } 12 | -------------------------------------------------------------------------------- /src/xian/tools/genesis/contracts/stamp_cost.s.py: -------------------------------------------------------------------------------- 1 | S = Hash() 2 | 3 | @construct 4 | def seed(initial_rate: int=100): 5 | S['value'] = initial_rate 6 | 7 | @export 8 | def current_value(): 9 | return S['value'] 10 | 11 | @export 12 | def set_value(new_value: int): 13 | assert new_value > 0, 'New value must be greater than 0' 14 | S['value'] = new_value 15 | -------------------------------------------------------------------------------- /tests/integration/contracts/rollback/con_mutator.py: -------------------------------------------------------------------------------- 1 | target_nested = ForeignHash(foreign_contract="con_mutable_map", foreign_name="nested") 2 | 3 | @export 4 | def mutate_target(key: str, target_contract: str): 5 | t = importlib.import_module(target_contract) 6 | d = t.nested[key] 7 | d["count"] = d.get("count", 0) + 1 8 | d["items"].append(99) 9 | 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CI](https://github.com/xian-network/xian-core/actions/workflows/main.yml/badge.svg)](https://github.com/xian-network/xian-core/actions/workflows/main.yml) 2 | 3 | # Xian 4 | 5 | ABCI application to be used with CometBFT 0.38.12 6 | 7 | ## Installation and Usage 8 | 9 | The installation guide is available at [xian-stack repository](https://github.com/xian-network/xian-stack). 10 | -------------------------------------------------------------------------------- /protos/tendermint/crypto/keys.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.crypto; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | // PublicKey defines the keys available for use with Validators 7 | message PublicKey { 8 | option (gogoproto.compare) = true; 9 | option (gogoproto.equal) = true; 10 | 11 | oneof sum { 12 | bytes ed25519 = 1; 13 | bytes secp256k1 = 2; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/integration/contracts/rollback/con_mutator_fail.py: -------------------------------------------------------------------------------- 1 | target_nested = ForeignHash(foreign_contract="con_mutable_map", foreign_name="nested") 2 | 3 | @export 4 | def mutate_then_fail_in_callee(key: str, target_contract: str): 5 | t = importlib.import_module(target_contract) 6 | d = t.nested[key] 7 | d["count"] = d.get("count", 0) + 1 8 | d["items"].append(123) 9 | assert False, "Failure in callee after mutation" 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/abci_methods/fixtures/.cometbft-fixture/config/priv_validator_key.json: -------------------------------------------------------------------------------- 1 | { 2 | "address": "04B2902DC78F80496FFC45B45742C4F11231CFC6", 3 | "pub_key": { 4 | "type": "tendermint/PubKeyEd25519", 5 | "value": "wnHaJU60JjUVoC+3kBOeKChFARKP/YO1kUOYc4vZ9RM=" 6 | }, 7 | "priv_key": { 8 | "type": "tendermint/PrivKeyEd25519", 9 | "value": "q6m57ITMdLPjdGjkVJh3jCheTsWzel+9yq8/U4NoexXCcdolTrQmNRWgL7eQE54oKEUBEo/9g7WRQ5hzi9n1Ew==" 10 | } 11 | } -------------------------------------------------------------------------------- /tests/governance/fixtures/.cometbft-fixture/config/priv_validator_key.json: -------------------------------------------------------------------------------- 1 | { 2 | "address": "04B2902DC78F80496FFC45B45742C4F11231CFC6", 3 | "pub_key": { 4 | "type": "tendermint/PubKeyEd25519", 5 | "value": "wnHaJU60JjUVoC+3kBOeKChFARKP/YO1kUOYc4vZ9RM=" 6 | }, 7 | "priv_key": { 8 | "type": "tendermint/PrivKeyEd25519", 9 | "value": "q6m57ITMdLPjdGjkVJh3jCheTsWzel+9yq8/U4NoexXCcdolTrQmNRWgL7eQE54oKEUBEo/9g7WRQ5hzi9n1Ew==" 10 | } 11 | } -------------------------------------------------------------------------------- /tests/integration/fixtures/.cometbft-fixture/config/priv_validator_key.json: -------------------------------------------------------------------------------- 1 | { 2 | "address": "04B2902DC78F80496FFC45B45742C4F11231CFC6", 3 | "pub_key": { 4 | "type": "tendermint/PubKeyEd25519", 5 | "value": "wnHaJU60JjUVoC+3kBOeKChFARKP/YO1kUOYc4vZ9RM=" 6 | }, 7 | "priv_key": { 8 | "type": "tendermint/PrivKeyEd25519", 9 | "value": "q6m57ITMdLPjdGjkVJh3jCheTsWzel+9yq8/U4NoexXCcdolTrQmNRWgL7eQE54oKEUBEo/9g7WRQ5hzi9n1Ew==" 10 | } 11 | } -------------------------------------------------------------------------------- /tests/xian-tests.md: -------------------------------------------------------------------------------- 1 | Xian Tests 2 | 3 | Motivation : 4 | 5 | All tests should run in a standardised environment, where all variables are controlled & predictable. 6 | 7 | - `.cometbft` to be a fixture in tests which is copied to a tmp directory at start of each test 8 | - should be a 'vanilla', blank state, necessary state for tests is to be added to the tmp state at the beginning of each test as needed. 9 | - xian.constants to be overridden with test values. -------------------------------------------------------------------------------- /protos/cometbft/mempool/v1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.mempool.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/mempool/v1"; 5 | 6 | // Txs contains a list of transaction from the mempool. 7 | message Txs { 8 | repeated bytes txs = 1; 9 | } 10 | 11 | // Message is an abstract mempool message. 12 | message Message { 13 | // Sum of all possible messages. 14 | oneof sum { 15 | Txs txs = 1; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/xian/methods/info.py: -------------------------------------------------------------------------------- 1 | from cometbft.abci.v1beta1.types_pb2 import ResponseInfo 2 | from xian.utils.block import ( 3 | get_latest_block_hash, 4 | get_latest_block_height, 5 | ) 6 | 7 | 8 | async def info(self, req) -> ResponseInfo: 9 | res = ResponseInfo() 10 | res.app_version = self.app_version 11 | res.version = req.version 12 | res.last_block_height = get_latest_block_height() 13 | res.last_block_app_hash = get_latest_block_hash() 14 | return res 15 | -------------------------------------------------------------------------------- /src/xian/tools/genesis/contracts/foundation.s.py: -------------------------------------------------------------------------------- 1 | import currency 2 | 3 | owner = Variable() 4 | 5 | @construct 6 | def seed(vk: str): 7 | owner.set(vk) 8 | 9 | @export 10 | def withdraw(amount: float): 11 | assert amount > 0, 'Cannot send negative balances!' 12 | assert ctx.caller == owner.get(), 'Not owner!' 13 | currency.transfer(amount, ctx.caller) 14 | 15 | @export 16 | def change_owner(vk: str): 17 | assert ctx.caller == owner.get(), 'Not owner!' 18 | owner.set(vk) 19 | -------------------------------------------------------------------------------- /protos/cometbft/crypto/v1/keys.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.crypto.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/crypto/v1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | 8 | // PublicKey is a ED25519 or a secp256k1 public key. 9 | message PublicKey { 10 | option (gogoproto.compare) = true; 11 | option (gogoproto.equal) = true; 12 | 13 | // The type of key. 14 | oneof sum { 15 | bytes ed25519 = 1; 16 | bytes secp256k1 = 2; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/xian/utils/hash.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | from contracting.storage.encoder import encode 3 | 4 | def hash_list(obj: list) -> bytes: 5 | encoded_tx = encode("".join(obj)).encode() 6 | hash_sha3 = hashlib.sha3_256() 7 | hash_sha3.update(encoded_tx) 8 | return hash_sha3.hexdigest().encode("utf-8") 9 | 10 | 11 | def hash_from_rewards(rewards): 12 | h = hashlib.sha3_256() 13 | encoded_rewards = encode(rewards).encode() 14 | h.update(encoded_rewards) 15 | return h.hexdigest() 16 | -------------------------------------------------------------------------------- /tests/integration/contracts/rollback/con_overdraw_fail.py: -------------------------------------------------------------------------------- 1 | @export 2 | def mutate_then_overdraw(key: str, token: str = "currency_1", to: str = "bob", amount: float = 1): 3 | m = importlib.import_module("con_mutable_map") 4 | # assign a new value to ensure a write occurs before failure 5 | m.nested[key] = {"count": 2, "items": [1, 2]} 6 | t = importlib.import_module(token) 7 | # This should fail since this contract has zero balance 8 | t.transfer(amount=amount, to=to) 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/xian/methods/init_chain.py: -------------------------------------------------------------------------------- 1 | from cometbft.abci.v1beta3.types_pb2 import ResponseInitChain 2 | from xian.utils.block import set_latest_block_hash, store_genesis_block 3 | 4 | import asyncio 5 | 6 | 7 | async def init_chain(self, req) -> ResponseInitChain: 8 | abci_genesis_state = self.genesis["abci_genesis"] 9 | set_latest_block_hash(bytes.fromhex(abci_genesis_state["hash"])) 10 | asyncio.ensure_future(store_genesis_block(self.client, self.nonce_storage, abci_genesis_state)) 11 | 12 | return ResponseInitChain() 13 | -------------------------------------------------------------------------------- /src/xian/tools/genesis/contracts/rewards.s.py: -------------------------------------------------------------------------------- 1 | S = Hash() 2 | 3 | @construct 4 | def seed(initial_split: list = [0.30, 0.01, 0.01, 0.68]): 5 | S['value'] = initial_split 6 | 7 | @export 8 | def current_value(): 9 | return S['value'] 10 | 11 | @export 12 | def set_value(new_value: list): 13 | assert len(new_value) == 4, 'New value must be a list of 4 elements' 14 | assert sum(new_value) == 1, 'Sum of new value must be 1' 15 | assert all([x > 0 for x in new_value]), 'There must be no 0 values in the list' 16 | S['value'] = new_value -------------------------------------------------------------------------------- /protos/cometbft/services/block_results/v1/block_results_service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.services.block_results.v1; 3 | 4 | import "cometbft/services/block_results/v1/block_results.proto"; 5 | 6 | option go_package = "github.com/cometbft/cometbft/api/cometbft/services/block_results/v1"; 7 | 8 | /* 9 | BlockResultService provides the block results of a given or latestheight. 10 | */ 11 | service BlockResultsService { 12 | // GetBlockResults returns the BlockResults of the requested height. 13 | rpc GetBlockResults(GetBlockResultsRequest) returns (GetBlockResultsResponse); 14 | } 15 | -------------------------------------------------------------------------------- /protos/cometbft/types/v1/block.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.types.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1"; 5 | 6 | import "cometbft/types/v1/types.proto"; 7 | import "cometbft/types/v1/evidence.proto"; 8 | import "gogoproto/gogo.proto"; 9 | 10 | // Block defines the structure of a block in the CometBFT blockchain. 11 | message Block { 12 | Header header = 1 [(gogoproto.nullable) = false]; 13 | Data data = 2 [(gogoproto.nullable) = false]; 14 | EvidenceList evidence = 3 [(gogoproto.nullable) = false]; 15 | Commit last_commit = 4; 16 | } 17 | -------------------------------------------------------------------------------- /src/xian/constants.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | class Constants: 4 | COMETBFT_HOME = Path.home() / Path(".cometbft/") 5 | COMETBFT_CONFIG = COMETBFT_HOME / Path("config/config.toml") 6 | COMETBFT_GENESIS = COMETBFT_HOME / Path("config/genesis.json") 7 | STORAGE_HOME = COMETBFT_HOME / Path('xian/') 8 | SIMULATOR_SOCKET = '/tmp/simulator_socket.sock' 9 | 10 | NONCE_FILENAME = '__n' 11 | PENDING_NONCE_FILENAME = '__pn' 12 | 13 | LATEST_BLOCK_HASH_KEY = "__latest_block.hash" 14 | LATEST_BLOCK_HEIGHT_KEY = "__latest_block.height" 15 | DUST_EXPONENT = 8 16 | 17 | OkCode = 0 18 | ErrorCode = 1 -------------------------------------------------------------------------------- /src/xian/tools/state_patches/state_patches_example.json: -------------------------------------------------------------------------------- 1 | { 2 | "100000000": [ 3 | { 4 | "key": "con_token.balances:some_address", 5 | "value": 1000000, 6 | "comment": "Fixing incorrect account balance after transaction X" 7 | }, 8 | { 9 | "key": "con_dao.proposals:5", 10 | "value": {"status": "completed", "votes": 120}, 11 | "comment": "Correcting proposal status that was incorrectly set" 12 | } 13 | ], 14 | "150000000": [ 15 | { 16 | "key": "con_exchange.trades:last_id", 17 | "value": 10034, 18 | "comment": "Resetting ID counter after overflow bug" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /protos/cometbft/services/version/v1/version.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.services.version.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/services/version/v1"; 5 | 6 | // GetVersionRequest is the request for the ABCI version. 7 | message GetVersionRequest {} 8 | 9 | // GetVersionResponse contains the ABCI application version info. 10 | message GetVersionResponse { 11 | string node = 1; // The semantic version of the node software. 12 | string abci = 2; // The version of ABCI used by the node. 13 | uint64 p2p = 3; // The version of the P2P protocol. 14 | uint64 block = 4; // The version of the block protocol. 15 | } 16 | -------------------------------------------------------------------------------- /tests/abci_methods/fixtures/mock_constants.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from xian.constants import Constants 3 | 4 | class MockConstants(Constants): 5 | COMETBFT_HOME = Path.home() / Path('/tmp/cometbft/') 6 | COMETBFT_CONFIG = COMETBFT_HOME / Path("config/config.toml") 7 | COMETBFT_GENESIS = COMETBFT_HOME / Path("config/genesis.json") 8 | 9 | # NONCE_FILENAME = '__n' 10 | # PENDING_NONCE_FILENAME = '__pn' 11 | STORAGE_HOME = COMETBFT_HOME / Path('xian/') 12 | 13 | # LATEST_BLOCK_HASH_KEY = "__latest_block.hash" 14 | # LATEST_BLOCK_HEIGHT_KEY = "__latest_block.height" 15 | # DUST_EXPONENT = 8 16 | 17 | # OkCode = 0 18 | # ErrorCode = 1 -------------------------------------------------------------------------------- /tests/governance/fixtures/mock_constants.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from xian.constants import Constants 3 | 4 | class MockConstants(Constants): 5 | COMETBFT_HOME = Path.home() / Path('/tmp/cometbft/') 6 | COMETBFT_CONFIG = COMETBFT_HOME / Path("config/config.toml") 7 | COMETBFT_GENESIS = COMETBFT_HOME / Path("config/genesis.json") 8 | 9 | # NONCE_FILENAME = '__n' 10 | # PENDING_NONCE_FILENAME = '__pn' 11 | STORAGE_HOME = COMETBFT_HOME / Path('xian/') 12 | 13 | # LATEST_BLOCK_HASH_KEY = "__latest_block.hash" 14 | # LATEST_BLOCK_HEIGHT_KEY = "__latest_block.height" 15 | # DUST_EXPONENT = 8 16 | 17 | # OkCode = 0 18 | # ErrorCode = 1 -------------------------------------------------------------------------------- /tests/integration/fixtures/mock_constants.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from xian.constants import Constants 3 | 4 | class MockConstants(Constants): 5 | COMETBFT_HOME = Path.home() / Path('/tmp/cometbft/') 6 | COMETBFT_CONFIG = COMETBFT_HOME / Path("config/config.toml") 7 | COMETBFT_GENESIS = COMETBFT_HOME / Path("config/genesis.json") 8 | 9 | # NONCE_FILENAME = '__n' 10 | # PENDING_NONCE_FILENAME = '__pn' 11 | STORAGE_HOME = COMETBFT_HOME / Path('xian/') 12 | 13 | # LATEST_BLOCK_HASH_KEY = "__latest_block.hash" 14 | # LATEST_BLOCK_HEIGHT_KEY = "__latest_block.height" 15 | # DUST_EXPONENT = 8 16 | 17 | # OkCode = 0 18 | # ErrorCode = 1 -------------------------------------------------------------------------------- /protos/cometbft/p2p/v1/pex.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.p2p.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/p2p/v1"; 5 | 6 | import "cometbft/p2p/v1/types.proto"; 7 | import "gogoproto/gogo.proto"; 8 | 9 | // PexRequest is a request for peer addresses. 10 | message PexRequest {} 11 | 12 | // PexAddrs is a response with peer addresses. 13 | message PexAddrs { 14 | repeated NetAddress addrs = 1 [(gogoproto.nullable) = false]; 15 | } 16 | 17 | // Message is an abstract PEX message. 18 | message Message { 19 | // Sum of all possible messages. 20 | oneof sum { 21 | PexRequest pex_request = 1; 22 | PexAddrs pex_addrs = 2; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /protos/tendermint/version/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.version; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | // App includes the protocol and software version for the application. 7 | // This information is included in ResponseInfo. The App.Protocol can be 8 | // updated in ResponseEndBlock. 9 | message App { 10 | uint64 protocol = 1; 11 | string software = 2; 12 | } 13 | 14 | // Consensus captures the consensus rules for processing a block in the blockchain, 15 | // including all blockchain data structures and the rules of the application's 16 | // state transition machine. 17 | message Consensus { 18 | option (gogoproto.equal) = true; 19 | 20 | uint64 block = 1; 21 | uint64 app = 2; 22 | } 23 | -------------------------------------------------------------------------------- /protos/cometbft/types/v1beta1/block.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.types.v1beta1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cometbft/types/v1beta1/types.proto"; 8 | import "cometbft/types/v1beta1/evidence.proto"; 9 | 10 | // Block defines the structure of a block in the CometBFT blockchain. 11 | message Block { 12 | Header header = 1 [(gogoproto.nullable) = false]; 13 | Data data = 2 [(gogoproto.nullable) = false]; 14 | cometbft.types.v1beta1.EvidenceList evidence = 3 [(gogoproto.nullable) = false]; 15 | Commit last_commit = 4; 16 | } 17 | -------------------------------------------------------------------------------- /src/xian/tools/update_abci_json.py: -------------------------------------------------------------------------------- 1 | import json 2 | import sys 3 | 4 | 5 | def update_json(genesis_file_path, json_data_file_path): 6 | with open(genesis_file_path, 'r') as file: 7 | cometbft_genesis = json.load(file) 8 | 9 | with open(json_data_file_path, 'r') as file: 10 | abci_genesis = json.load(file) 11 | 12 | cometbft_genesis['abci_genesis'] = abci_genesis 13 | cometbft_genesis['initial_height'] = str(abci_genesis["number"]) 14 | 15 | with open(genesis_file_path, 'w') as file: 16 | json.dump(cometbft_genesis, file, indent=4) 17 | 18 | 19 | if __name__ == "__main__": 20 | genesis_file_path = sys.argv[1] 21 | json_data_file_path = sys.argv[2] 22 | update_json(genesis_file_path, json_data_file_path) 23 | -------------------------------------------------------------------------------- /protos/cometbft/version/v1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.version.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/version/v1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | 8 | // App includes the protocol and software version for the application. 9 | // This information is included in ResponseInfo. The App.Protocol can be 10 | // updated in ResponseEndBlock. 11 | message App { 12 | uint64 protocol = 1; 13 | string software = 2; 14 | } 15 | 16 | // Consensus captures the consensus rules for processing a block in the blockchain, 17 | // including all blockchain data structures and the rules of the application's 18 | // state transition machine. 19 | message Consensus { 20 | option (gogoproto.equal) = true; 21 | 22 | uint64 block = 1; 23 | uint64 app = 2; 24 | } 25 | -------------------------------------------------------------------------------- /src/xian/utils/cometbft.py: -------------------------------------------------------------------------------- 1 | import json 2 | import toml 3 | from xian.constants import Constants 4 | 5 | def load_tendermint_config(config: Constants): 6 | if not (config.COMETBFT_HOME.exists() and config.COMETBFT_HOME.is_dir()): 7 | raise FileNotFoundError("You must initialize CometBFT first") 8 | if not (config.COMETBFT_CONFIG.exists() and config.COMETBFT_CONFIG.is_file()): 9 | raise FileNotFoundError(f"File not found: {config.COMETBFT_CONFIG}") 10 | 11 | return toml.load(config.COMETBFT_CONFIG) 12 | 13 | 14 | def load_genesis_data(config: Constants): 15 | if not (config.COMETBFT_GENESIS.exists() and config.COMETBFT_GENESIS.is_file()): 16 | raise FileNotFoundError(f"File not found: {config.COMETBFT_GENESIS}") 17 | 18 | with open(config.COMETBFT_GENESIS, "r") as file: 19 | return json.load(file) -------------------------------------------------------------------------------- /protos/cometbft/rpc/grpc/v1beta2/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.rpc.grpc.v1beta2; 3 | option go_package = "github.com/cometbft/cometbft/api/cometbft/rpc/grpc/v1beta2"; 4 | 5 | import "cometbft/rpc/grpc/v1beta1/types.proto"; 6 | import "cometbft/abci/v1beta2/types.proto"; 7 | 8 | // ResponseBroadcastTx is a response of broadcasting the transaction. 9 | message ResponseBroadcastTx { 10 | cometbft.abci.v1beta2.ResponseCheckTx check_tx = 1; 11 | cometbft.abci.v1beta2.ResponseDeliverTx deliver_tx = 2; 12 | } 13 | 14 | // BroadcastAPI is an API for broadcasting transactions. 15 | service BroadcastAPI { 16 | // Ping the connection. 17 | rpc Ping(v1beta1.RequestPing) returns (v1beta1.ResponsePing); 18 | // BroadcastTx broadcasts the transaction. 19 | rpc BroadcastTx(v1beta1.RequestBroadcastTx) returns (ResponseBroadcastTx); 20 | } 21 | -------------------------------------------------------------------------------- /protos/cometbft/services/version/v1/version_service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.services.version.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/services/version/v1"; 5 | 6 | import "cometbft/services/version/v1/version.proto"; 7 | 8 | // VersionService simply provides version information about the node and the 9 | // protocols it uses. 10 | // 11 | // The intention with this service is to offer a stable interface through which 12 | // clients can access version information. This means that the version of the 13 | // service should be kept stable at v1, with GetVersionResponse evolving only 14 | // in non-breaking ways. 15 | service VersionService { 16 | // GetVersion retrieves version information about the node and the protocols 17 | // it implements. 18 | rpc GetVersion(GetVersionRequest) returns (GetVersionResponse); 19 | } 20 | -------------------------------------------------------------------------------- /protos/cometbft/services/block/v1/block_service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.services.block.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/services/block/v1"; 5 | 6 | import "cometbft/services/block/v1/block.proto"; 7 | 8 | // BlockService provides information about blocks 9 | service BlockService { 10 | // GetBlock retrieves the block information at a particular height. 11 | rpc GetByHeight(GetByHeightRequest) returns (GetByHeightResponse); 12 | 13 | // GetLatestHeight returns a stream of the latest block heights committed by 14 | // the network. This is a long-lived stream that is only terminated by the 15 | // server if an error occurs. The caller is expected to handle such 16 | // disconnections and automatically reconnect. 17 | rpc GetLatestHeight(GetLatestHeightRequest) returns (stream GetLatestHeightResponse); 18 | } 19 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Please add a brief description of the feature / change / bug-fix you want to merge. 4 | 5 | ## Type of change 6 | 7 | Please delete options that are not relevant. 8 | 9 | - [ ] Enhancement (simplifying, beautifying, better performance, etc.) 10 | - [ ] Bug fix (non-breaking change which fixes an issue) 11 | - [ ] New feature (non-breaking change which adds functionality) 12 | - [ ] Breaking change (change that requires code adjustments in other places) 13 | - [ ] Fork needed (fix or feature that requires a resync of blockchain state) 14 | 15 | ## Checklist 16 | 17 | - [ ] I have performed a self-review of my own code 18 | - [ ] I have tested this change in my development environment. 19 | - [ ] I have added tests to prove that this change works 20 | - [ ] All existing tests pass after this change 21 | - [ ] I have added / updated documentation related to this change 22 | -------------------------------------------------------------------------------- /src/xian/methods/commit.py: -------------------------------------------------------------------------------- 1 | from cometbft.abci.v1beta3.types_pb2 import ResponseCommit 2 | from xian.utils.block import ( 3 | set_latest_block_hash, 4 | set_latest_block_height 5 | ) 6 | 7 | 8 | async def commit(self) -> ResponseCommit: 9 | set_latest_block_hash(self.merkle_root_hash) 10 | set_latest_block_height(self.current_block_meta["height"]) 11 | 12 | self.client.raw_driver.hard_apply(str(self.current_block_meta["nanos"])) 13 | 14 | # unset current_block_meta & cleanup 15 | self.fingerprint_hashes = [] 16 | self.merkle_root_hash = None 17 | self.current_block_rewards = {} 18 | 19 | retain_height = 0 20 | if self.pruning_enabled: 21 | if self.current_block_meta["height"] > self.blocks_to_keep: 22 | retain_height = self.current_block_meta["height"] - self.blocks_to_keep 23 | 24 | self.current_block_meta = None 25 | 26 | return ResponseCommit(retain_height=retain_height) 27 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | wipe: 2 | rm -rf ~/.cometbft/xian 3 | ../cometbft unsafe-reset-all 4 | 5 | up: 6 | cd ./src/xian && pm2 start xian_abci.py --name xian -f 7 | pm2 start "../cometbft node --rpc.laddr tcp://0.0.0.0:26657" --name cometbft -f 8 | 9 | up-bds: 10 | cd ./src/xian/services/ && pm2 start simulator.py --name simulator -f --wait-ready 11 | cd ./src/xian && pm2 start xian_abci.py --name xian -f 12 | pm2 start "../cometbft node --rpc.laddr tcp://0.0.0.0:26657" --name cometbft -f 13 | 14 | logs: 15 | pm2 logs --lines 1000 16 | 17 | down: 18 | pm2 stop all 19 | sleep 5 # Give Loguru time to handle any final cleanup 20 | pm2 delete all 21 | 22 | restart: 23 | make down 24 | make up 25 | 26 | init: 27 | ../cometbft init 28 | 29 | node-id: 30 | ../cometbft show-node-id 31 | 32 | dwu: 33 | make down 34 | make wipe 35 | make init 36 | make up 37 | 38 | pull-and-install: 39 | make pull 40 | make install 41 | 42 | ex-state: 43 | python ./src/xian/tools/export_state.py -------------------------------------------------------------------------------- /src/xian/services/bds/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | class Config: 5 | 6 | _cfg_data = None 7 | _cfg_file = None 8 | 9 | def __init__(self, *cfg_path: str): 10 | # Ensure the path is relative to the directory of this file 11 | base_path = os.path.dirname(os.path.abspath(__file__)) 12 | self._cfg_file = os.path.join(base_path, *cfg_path) 13 | self.load() 14 | 15 | def load(self): 16 | with open(self._cfg_file, encoding='utf-8') as f: 17 | self._cfg_data = json.load(f) 18 | 19 | def dump(self): 20 | with open(self._cfg_file, 'w', encoding='utf-8') as f: 21 | json.dump(self._cfg_data, f, ensure_ascii=False, sort_keys=True, indent=4) 22 | 23 | def get(self, key, reload=False): 24 | if reload: self.load() 25 | return self._cfg_data[key] if key in self._cfg_data else None 26 | 27 | def set(self, key, value, dump=True): 28 | self._cfg_data[key] = value 29 | if dump: self.dump() -------------------------------------------------------------------------------- /protos/tendermint/crypto/proof.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.crypto; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | message Proof { 7 | int64 total = 1; 8 | int64 index = 2; 9 | bytes leaf_hash = 3; 10 | repeated bytes aunts = 4; 11 | } 12 | 13 | message ValueOp { 14 | // Encoded in ProofOp.Key. 15 | bytes key = 1; 16 | 17 | // To encode in ProofOp.Data 18 | Proof proof = 2; 19 | } 20 | 21 | message DominoOp { 22 | string key = 1; 23 | string input = 2; 24 | string output = 3; 25 | } 26 | 27 | // ProofOp defines an operation used for calculating Merkle root 28 | // The data could be arbitrary format, providing necessary data 29 | // for example neighbouring node hash 30 | message ProofOp { 31 | string type = 1; 32 | bytes key = 2; 33 | bytes data = 3; 34 | } 35 | 36 | // ProofOps is Merkle proof defined by the list of ProofOps 37 | message ProofOps { 38 | repeated ProofOp ops = 1 [(gogoproto.nullable) = false]; 39 | } 40 | -------------------------------------------------------------------------------- /protos/cometbft/rpc/grpc/v1beta3/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.rpc.grpc.v1beta3; 3 | option go_package = "github.com/cometbft/cometbft/api/cometbft/rpc/grpc/v1beta3"; 4 | 5 | import "cometbft/rpc/grpc/v1beta1/types.proto"; 6 | 7 | import "cometbft/abci/v1beta3/types.proto"; 8 | 9 | // ResponseBroadcastTx is a response of broadcasting the transaction. 10 | message ResponseBroadcastTx { 11 | cometbft.abci.v1beta3.ResponseCheckTx check_tx = 1; 12 | cometbft.abci.v1beta3.ExecTxResult tx_result = 2; 13 | } 14 | 15 | // BroadcastAPI is an API for broadcasting transactions. 16 | // 17 | // Deprecated: This API will be superseded by a more comprehensive gRPC-based 18 | // broadcast API, and is scheduled for removal after v0.38. 19 | service BroadcastAPI { 20 | // Ping the connection. 21 | rpc Ping(v1beta1.RequestPing) returns (v1beta1.ResponsePing); 22 | // BroadcastTx broadcasts a transaction. 23 | rpc BroadcastTx(v1beta1.RequestBroadcastTx) returns (v1beta3.ResponseBroadcastTx); 24 | } 25 | -------------------------------------------------------------------------------- /protos/cometbft/types/v1beta2/params.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.types.v1beta2; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta2"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cometbft/types/v1beta1/params.proto"; 8 | 9 | option (gogoproto.equal_all) = true; 10 | 11 | // ConsensusParams contains consensus critical parameters that determine the 12 | // validity of blocks. 13 | message ConsensusParams { 14 | BlockParams block = 1; 15 | v1beta1.EvidenceParams evidence = 2; 16 | v1beta1.ValidatorParams validator = 3; 17 | v1beta1.VersionParams version = 4; 18 | } 19 | 20 | // BlockParams contains limits on the block size. 21 | message BlockParams { 22 | // Max block size, in bytes. 23 | // Note: must be greater than 0 24 | int64 max_bytes = 1; 25 | // Max gas per block. 26 | // Note: must be greater or equal to -1 27 | int64 max_gas = 2; 28 | 29 | reserved 3; // was TimeIotaMs see https://github.com/tendermint/tendermint/pull/5792 30 | } 31 | -------------------------------------------------------------------------------- /protos/cometbft/services/block_results/v1/block_results.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.services.block_results.v1; 3 | 4 | import "cometbft/abci/v1/types.proto"; 5 | import "cometbft/types/v1/params.proto"; 6 | 7 | option go_package = "github.com/cometbft/cometbft/api/cometbft/services/block_results/v1"; 8 | 9 | // GetBlockResults is a request for the BlockResults of a given height. 10 | message GetBlockResultsRequest { 11 | int64 height = 1; 12 | } 13 | 14 | // GetBlockResultsResponse contains the block results for the given height. 15 | message GetBlockResultsResponse { 16 | int64 height = 1; 17 | repeated cometbft.abci.v1.ExecTxResult tx_results = 2; 18 | repeated cometbft.abci.v1.Event finalize_block_events = 3; 19 | repeated cometbft.abci.v1.ValidatorUpdate validator_updates = 4; 20 | cometbft.types.v1.ConsensusParams consensus_param_updates = 5; 21 | bytes app_hash = 6; 22 | } 23 | -------------------------------------------------------------------------------- /protos/cometbft/services/block/v1/block.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.services.block.v1; 3 | 4 | import "cometbft/types/v1/types.proto"; 5 | import "cometbft/types/v1/block.proto"; 6 | 7 | option go_package = "github.com/cometbft/cometbft/api/cometbft/services/block/v1"; 8 | 9 | // GetByHeightRequest is a request for a block at the specified height. 10 | message GetByHeightRequest { 11 | // The height of the block requested. 12 | int64 height = 1; 13 | } 14 | 15 | // GetByHeightResponse contains the block ID and the block at the specified height. 16 | message GetByHeightResponse { 17 | cometbft.types.v1.BlockID block_id = 1; 18 | cometbft.types.v1.Block block = 2; 19 | } 20 | 21 | // GetLatestHeightRequest - empty message since no parameter is required 22 | message GetLatestHeightRequest {} 23 | 24 | // GetLatestHeightResponse provides the height of the latest committed block. 25 | message GetLatestHeightResponse { 26 | // The height of the latest committed block. Will be 0 if no data has been 27 | // committed yet. 28 | int64 height = 1; 29 | } 30 | -------------------------------------------------------------------------------- /src/xian/methods/check_tx.py: -------------------------------------------------------------------------------- 1 | from cometbft.abci.v1beta3.types_pb2 import ResponseCheckTx 2 | from xian.utils.tx import ( 3 | validate_transaction 4 | ) 5 | from xian.utils.tx import ( 6 | verify, 7 | unpack_transaction 8 | ) 9 | from xian.utils.encoding import decode_transaction_bytes 10 | from xian.constants import Constants as c 11 | 12 | import json 13 | 14 | 15 | async def check_tx(self, raw_tx) -> ResponseCheckTx: 16 | try: 17 | tx, payload_str = decode_transaction_bytes(raw_tx) 18 | validate_transaction(self.client,self.nonce_storage,tx) 19 | sender, signature, payload = unpack_transaction(tx) 20 | if not verify(sender, payload_str, signature): 21 | return ResponseCheckTx(code=c.ErrorCode, log="Bad signature") 22 | payload_json = json.loads(payload) 23 | if payload_json["chain_id"] != self.chain_id: 24 | return ResponseCheckTx(code=c.ErrorCode, log="Wrong chain_id") 25 | return ResponseCheckTx(code=c.OkCode) 26 | except Exception as e: 27 | return ResponseCheckTx(code=c.ErrorCode, log=f"{type(e).__name__}: {e}") 28 | -------------------------------------------------------------------------------- /protos/cometbft/rpc/grpc/v1beta1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.rpc.grpc.v1beta1; 3 | option go_package = "github.com/cometbft/cometbft/api/cometbft/rpc/grpc/v1beta1"; 4 | 5 | import "cometbft/abci/v1beta1/types.proto"; 6 | 7 | // PingRequest is a request to confirm that the connection is alive. 8 | message RequestPing {} 9 | 10 | // RequestBroadcastTx is a request to broadcast the transaction. 11 | message RequestBroadcastTx { 12 | bytes tx = 1; 13 | } 14 | 15 | // PingResponse is a response to confirm that the connection is alive. 16 | message ResponsePing {} 17 | 18 | // ResponseBroadcastTx is a response of broadcasting the transaction. 19 | message ResponseBroadcastTx { 20 | cometbft.abci.v1beta1.ResponseCheckTx check_tx = 1; 21 | cometbft.abci.v1beta1.ResponseDeliverTx deliver_tx = 2; 22 | } 23 | 24 | // BroadcastAPI is an API for broadcasting transactions. 25 | service BroadcastAPI { 26 | // Ping the connection. 27 | rpc Ping(RequestPing) returns (ResponsePing); 28 | // BroadcastTx broadcasts the transaction. 29 | rpc BroadcastTx(RequestBroadcastTx) returns (ResponseBroadcastTx); 30 | } 31 | -------------------------------------------------------------------------------- /src/xian/tools/genesis/contracts/contracts_local.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension": ".s.py", 3 | "contracts": [ 4 | { 5 | "name": "currency", 6 | "owner": null, 7 | "constructor_args": { 8 | "vk": "ee06a34cf08bf72ce592d26d36b90c79daba2829ba9634992d034318160d49f9" 9 | } 10 | }, 11 | { 12 | "name": "stamp_cost", 13 | "owner": "masternodes", 14 | "constructor_args": { 15 | "initial_rate": 20 16 | } 17 | }, 18 | { 19 | "name": "rewards", 20 | "owner": "masternodes", 21 | "constructor_args": null 22 | }, 23 | { 24 | "name": "foundation", 25 | "owner": null, 26 | "constructor_args": { 27 | "vk": "ee06a34cf08bf72ce592d26d36b90c79daba2829ba9634992d034318160d49f9" 28 | } 29 | }, 30 | { 31 | "name": "dao", 32 | "owner": "masternodes", 33 | "constructor_args": null 34 | }, 35 | { 36 | "name": "members", 37 | "submit_as": "masternodes", 38 | "owner": null, 39 | "constructor_args": { 40 | "genesis_nodes": ["ee06a34cf08bf72ce592d26d36b90c79daba2829ba9634992d034318160d49f9"], 41 | "genesis_registration_fee": 100000 42 | } 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /protos/cometbft/crypto/v1/proof.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.crypto.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/crypto/v1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | 8 | // Proof is a Merkle proof. 9 | message Proof { 10 | int64 total = 1; 11 | int64 index = 2; 12 | bytes leaf_hash = 3; 13 | repeated bytes aunts = 4; 14 | } 15 | 16 | // ValueOp is a Merkle proof for a single key. 17 | message ValueOp { 18 | // Encoded in ProofOp.Key. 19 | bytes key = 1; 20 | 21 | // To encode in ProofOp.Data 22 | Proof proof = 2; 23 | } 24 | 25 | // DominoOp always returns the given output. 26 | message DominoOp { 27 | string key = 1; 28 | string input = 2; 29 | string output = 3; 30 | } 31 | 32 | // ProofOp defines an operation used for calculating Merkle root 33 | // The data could be arbitrary format, providing necessary data 34 | // for example neighbouring node hash 35 | message ProofOp { 36 | string type = 1; 37 | bytes key = 2; 38 | bytes data = 3; 39 | } 40 | 41 | // ProofOps is Merkle proof defined by the list of ProofOps 42 | message ProofOps { 43 | repeated ProofOp ops = 1 [(gogoproto.nullable) = false]; 44 | } 45 | -------------------------------------------------------------------------------- /src/xian/tools/genesis/contracts/contracts_devnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension": ".s.py", 3 | "contracts": [ 4 | { 5 | "name": "currency", 6 | "owner": null, 7 | "constructor_args": { 8 | "vk": "7fa496ca2438e487cc45a8a27fd95b2efe373223f7b72868fbab205d686be48e" 9 | } 10 | }, 11 | { 12 | "name": "stamp_cost", 13 | "owner": "masternodes", 14 | "constructor_args": { 15 | "initial_rate": 20 16 | } 17 | }, 18 | { 19 | "name": "rewards", 20 | "owner": "masternodes", 21 | "constructor_args": null 22 | }, 23 | { 24 | "name": "foundation", 25 | "owner": null, 26 | "constructor_args": { 27 | "vk": "7fa496ca2438e487cc45a8a27fd95b2efe373223f7b72868fbab205d686be48e" 28 | } 29 | }, 30 | { 31 | "name": "dao", 32 | "owner": "masternodes", 33 | "constructor_args": null 34 | }, 35 | { 36 | "name": "members", 37 | "submit_as": "masternodes", 38 | "owner": null, 39 | "constructor_args": { 40 | "genesis_nodes": ["7fa496ca2438e487cc45a8a27fd95b2efe373223f7b72868fbab205d686be48e","dff5d54d9c3cdb04d279c3c0a123d6a73a94e0725d7eac955fdf87298dbe45a6"], 41 | "genesis_registration_fee": 100000 42 | } 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = xian 3 | version = attr: abci.__version__ 4 | description = Python based ABCI Server for Tendermint 5 | long_description = file: README.md 6 | long_description_content_type = text/markdown 7 | url = https://github.com/XianChain/xian 8 | author = Xian Core Team 9 | license = Apache 2.0 10 | license_file = LICENSE 11 | platforms = unix, linux, osx, cygwin, win32 12 | classifiers= 13 | Development Status :: 3 - Alpha 14 | Intended Audience :: Developers 15 | License :: OSI Approved :: Apache Software License 16 | Programming Language :: Python :: 3.11 17 | keywords = blockchain, tendermint, abci, python 18 | project_urls = 19 | Source = https://github.com/XianChain/xian 20 | 21 | [options] 22 | packages = find: 23 | package_dir = 24 | = src 25 | include_package_data = true 26 | python_requires = ~=3.11.0 27 | install_requires = 28 | protobuf == 3.20.3 29 | colorlog >= 3.1.4 30 | certifi >= 2022.12.7 31 | pyflakes 32 | toml 33 | pynacl 34 | requests 35 | xian-py 36 | loguru 37 | urwid 38 | asyncpg 39 | parameterized 40 | 41 | [options.packages.find] 42 | where = src 43 | 44 | [options.extras_require] 45 | dev = 46 | twine 47 | black 48 | build 49 | -------------------------------------------------------------------------------- /src/xian/tools/genesis/contracts/contracts_stagenet.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension": ".s.py", 3 | "contracts": [ 4 | { 5 | "name": "currency", 6 | "owner": null, 7 | "constructor_args": { 8 | "vk": "b4d1967e6264bbcd61fd487caf3cafaffdc34be31d0994bf02afdcc2056c053c" 9 | } 10 | }, 11 | { 12 | "name": "stamp_cost", 13 | "owner": "masternodes", 14 | "constructor_args": { 15 | "initial_rate": 20 16 | } 17 | }, 18 | { 19 | "name": "rewards", 20 | "owner": "masternodes", 21 | "constructor_args": null 22 | }, 23 | { 24 | "name": "foundation", 25 | "owner": null, 26 | "constructor_args": { 27 | "vk": "b4d1967e6264bbcd61fd487caf3cafaffdc34be31d0994bf02afdcc2056c053c" 28 | } 29 | }, 30 | { 31 | "name": "dao", 32 | "owner": "masternodes", 33 | "constructor_args": null 34 | }, 35 | { 36 | "name": "members", 37 | "submit_as": "masternodes", 38 | "owner": null, 39 | "constructor_args": { 40 | "genesis_nodes": ["b4d1967e6264bbcd61fd487caf3cafaffdc34be31d0994bf02afdcc2056c053c","db21a73137672f075f9a8ee142a1aa4839a5deb28ef03a10f3e7e16c87db8f24"], 41 | "genesis_registration_fee": 100000 42 | } 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /protos/cometbft/statesync/v1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.statesync.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/statesync/v1"; 5 | 6 | // Message is the top-level message type for the statesync service. 7 | message Message { 8 | // The message type. 9 | oneof sum { 10 | SnapshotsRequest snapshots_request = 1; 11 | SnapshotsResponse snapshots_response = 2; 12 | ChunkRequest chunk_request = 3; 13 | ChunkResponse chunk_response = 4; 14 | } 15 | } 16 | 17 | // SnapshotsRequest is sent to request a snapshot. 18 | message SnapshotsRequest {} 19 | 20 | // SnapshotsResponse contains the snapshot metadata. 21 | message SnapshotsResponse { 22 | uint64 height = 1; 23 | uint32 format = 2; 24 | uint32 chunks = 3; 25 | bytes hash = 4; 26 | bytes metadata = 5; 27 | } 28 | 29 | // ChunkRequest is sent to request a chunk. 30 | message ChunkRequest { 31 | uint64 height = 1; 32 | uint32 format = 2; 33 | uint32 index = 3; 34 | } 35 | 36 | // ChunkResponse contains a chunk of the snapshot. 37 | message ChunkResponse { 38 | uint64 height = 1; 39 | uint32 format = 2; 40 | uint32 index = 3; 41 | bytes chunk = 4; 42 | bool missing = 5; 43 | } 44 | -------------------------------------------------------------------------------- /protos/cometbft/p2p/v1/conn.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.p2p.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/p2p/v1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cometbft/crypto/v1/keys.proto"; 8 | 9 | // PacketPing is a request to confirm that the connection is alive. 10 | message PacketPing {} 11 | 12 | // PacketPong is a response to confirm that the connection is alive. 13 | message PacketPong {} 14 | 15 | // PacketMsg contains data for the specified channel ID. EOF means the message 16 | // is fully received. 17 | message PacketMsg { 18 | int32 channel_id = 1 [(gogoproto.customname) = "ChannelID"]; 19 | bool eof = 2 [(gogoproto.customname) = "EOF"]; 20 | bytes data = 3; 21 | } 22 | 23 | // Packet is an abstract p2p message. 24 | message Packet { 25 | // Sum of all possible messages. 26 | oneof sum { 27 | PacketPing packet_ping = 1; 28 | PacketPong packet_pong = 2; 29 | PacketMsg packet_msg = 3; 30 | } 31 | } 32 | 33 | // AuthSigMessage is sent during the authentication and contains our/remote's 34 | // signature along with the public key. 35 | message AuthSigMessage { 36 | cometbft.crypto.v1.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; 37 | bytes sig = 2; 38 | } 39 | -------------------------------------------------------------------------------- /protos/cometbft/blocksync/v1beta1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.blocksync.v1beta1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/blocksync/v1beta1"; 5 | 6 | import "cometbft/types/v1beta1/block.proto"; 7 | 8 | // BlockRequest requests a block for a specific height 9 | message BlockRequest { 10 | int64 height = 1; 11 | } 12 | 13 | // NoBlockResponse informs the node that the peer does not have block at the requested height 14 | message NoBlockResponse { 15 | int64 height = 1; 16 | } 17 | 18 | // BlockResponse returns block to the requested 19 | message BlockResponse { 20 | cometbft.types.v1beta1.Block block = 1; 21 | } 22 | 23 | // StatusRequest requests the status of a peer. 24 | message StatusRequest { 25 | } 26 | 27 | // StatusResponse is a peer response to inform their status. 28 | message StatusResponse { 29 | int64 height = 1; 30 | int64 base = 2; 31 | } 32 | 33 | // Message is an abstract blocksync message. 34 | message Message { 35 | // Sum of all possible messages. 36 | oneof sum { 37 | BlockRequest block_request = 1; 38 | NoBlockResponse no_block_response = 2; 39 | BlockResponse block_response = 3; 40 | StatusRequest status_request = 4; 41 | StatusResponse status_response = 5; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /protos/cometbft/blocksync/v1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.blocksync.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/blocksync/v1"; 5 | 6 | import "cometbft/types/v1/block.proto"; 7 | import "cometbft/types/v1/types.proto"; 8 | 9 | // BlockRequest requests a block for a specific height 10 | message BlockRequest { 11 | int64 height = 1; 12 | } 13 | 14 | // NoBlockResponse informs the node that the peer does not have block at the requested height 15 | message NoBlockResponse { 16 | int64 height = 1; 17 | } 18 | 19 | // StatusRequest requests the status of a peer. 20 | message StatusRequest { 21 | } 22 | 23 | // StatusResponse is a peer response to inform their status. 24 | message StatusResponse { 25 | int64 height = 1; 26 | int64 base = 2; 27 | } 28 | 29 | // BlockResponse returns block to the requested 30 | message BlockResponse { 31 | cometbft.types.v1.Block block = 1; 32 | cometbft.types.v1.ExtendedCommit ext_commit = 2; 33 | } 34 | 35 | // Message is an abstract blocksync message. 36 | message Message { 37 | // Sum of all possible messages. 38 | oneof sum { 39 | BlockRequest block_request = 1; 40 | NoBlockResponse no_block_response = 2; 41 | BlockResponse block_response = 3; 42 | StatusRequest status_request = 4; 43 | StatusResponse status_response = 5; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/xian/tools/genesis/contracts/contracts_testnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension": ".s.py", 3 | "contracts": [ 4 | { 5 | "name": "currency", 6 | "owner": null, 7 | "constructor_args": { 8 | "vk": "7fa496ca2438e487cc45a8a27fd95b2efe373223f7b72868fbab205d686be48e" 9 | } 10 | }, 11 | { 12 | "name": "stamp_cost", 13 | "owner": "masternodes", 14 | "constructor_args": { 15 | "initial_rate": 20 16 | } 17 | }, 18 | { 19 | "name": "rewards", 20 | "owner": "masternodes", 21 | "constructor_args": null 22 | }, 23 | { 24 | "name": "foundation", 25 | "owner": null, 26 | "constructor_args": { 27 | "vk": "7fa496ca2438e487cc45a8a27fd95b2efe373223f7b72868fbab205d686be48e" 28 | } 29 | }, 30 | { 31 | "name": "dao", 32 | "owner": "masternodes", 33 | "constructor_args": null 34 | }, 35 | { 36 | "name": "members", 37 | "submit_as": "masternodes", 38 | "owner": null, 39 | "constructor_args": { 40 | "genesis_nodes": ["7fa496ca2438e487cc45a8a27fd95b2efe373223f7b72868fbab205d686be48e","dff5d54d9c3cdb04d279c3c0a123d6a73a94e0725d7eac955fdf87298dbe45a6","6d2476cd66fa277b6077c76cdcd92733040dada2e12a28c3ebb08af44e12be76","b4d1967e6264bbcd61fd487caf3cafaffdc34be31d0994bf02afdcc2056c053c","db21a73137672f075f9a8ee142a1aa4839a5deb28ef03a10f3e7e16c87db8f24"], 41 | "genesis_registration_fee": 100000 42 | } 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /protos/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | name: buf.build/cometbft/cometbft 3 | deps: 4 | - buf.build/cosmos/gogo-proto 5 | breaking: 6 | use: 7 | - FILE 8 | build: 9 | excludes: 10 | - tendermint 11 | lint: 12 | use: 13 | - DEFAULT 14 | - COMMENTS 15 | - FILE_LOWER_SNAKE_CASE 16 | except: 17 | - COMMENT_FIELD 18 | ignore_only: 19 | ENUM_VALUE_PREFIX: 20 | - cometbft/abci/v1beta1 21 | - cometbft/abci/v1beta2 22 | - cometbft/abci/v1beta3 23 | ENUM_ZERO_VALUE_SUFFIX: 24 | - cometbft/abci/v1beta1 25 | - cometbft/abci/v1beta2 26 | - cometbft/abci/v1beta3 27 | PACKAGE_VERSION_SUFFIX: 28 | - cometbft/abci/v1beta1 29 | - cometbft/abci/v1beta2 30 | - cometbft/abci/v1beta3 31 | RPC_REQUEST_RESPONSE_UNIQUE: 32 | - cometbft/abci/v1beta1 33 | - cometbft/abci/v1beta2 34 | - cometbft/abci/v1beta3 35 | - cometbft/rpc/grpc 36 | RPC_REQUEST_STANDARD_NAME: 37 | - cometbft/abci/v1beta1 38 | - cometbft/abci/v1beta2 39 | - cometbft/abci/v1beta3 40 | - cometbft/rpc/grpc 41 | RPC_RESPONSE_STANDARD_NAME: 42 | - cometbft/abci/v1beta1 43 | - cometbft/abci/v1beta2 44 | - cometbft/abci/v1beta3 45 | - cometbft/rpc/grpc 46 | SERVICE_SUFFIX: 47 | - cometbft/abci/v1beta1 48 | - cometbft/abci/v1beta2 49 | - cometbft/abci/v1beta3 50 | - cometbft/rpc/grpc 51 | enum_zero_value_suffix: _UNKNOWN 52 | -------------------------------------------------------------------------------- /protos/cometbft/p2p/v1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.p2p.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/p2p/v1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | 8 | // NetAddress represents a peer's network address. 9 | message NetAddress { 10 | string id = 1 [(gogoproto.customname) = "ID"]; 11 | string ip = 2 [(gogoproto.customname) = "IP"]; 12 | uint32 port = 3; 13 | } 14 | 15 | // ProtocolVersion represents the current p2p protocol version. 16 | message ProtocolVersion { 17 | uint64 p2p = 1 [(gogoproto.customname) = "P2P"]; 18 | uint64 block = 2; 19 | uint64 app = 3; 20 | } 21 | 22 | // DefaultNodeInfo is a basic node's information sent to other peers during the 23 | // p2p handshake. 24 | message DefaultNodeInfo { 25 | ProtocolVersion protocol_version = 1 [(gogoproto.nullable) = false]; 26 | string default_node_id = 2 [(gogoproto.customname) = "DefaultNodeID"]; 27 | string listen_addr = 3; 28 | string network = 4; 29 | string version = 5; 30 | bytes channels = 6; 31 | string moniker = 7; 32 | DefaultNodeInfoOther other = 8 [(gogoproto.nullable) = false]; 33 | } 34 | 35 | // DefaultNodeInfoOther is the misc. application specific data. 36 | message DefaultNodeInfoOther { 37 | string tx_index = 1; 38 | string rpc_address = 2 [(gogoproto.customname) = "RPCAddress"]; 39 | } 40 | -------------------------------------------------------------------------------- /protos/tendermint/types/validator.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.types; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "tendermint/crypto/keys.proto"; 6 | 7 | // BlockIdFlag indicates which BlockID the signature is for 8 | enum BlockIDFlag { 9 | option (gogoproto.goproto_enum_stringer) = true; 10 | option (gogoproto.goproto_enum_prefix) = false; 11 | 12 | // Indicates an error condition 13 | BLOCK_ID_FLAG_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "BlockIDFlagUnknown"]; 14 | // The vote was not received 15 | BLOCK_ID_FLAG_ABSENT = 1 [(gogoproto.enumvalue_customname) = "BlockIDFlagAbsent"]; 16 | // Voted for the block that received the majority 17 | BLOCK_ID_FLAG_COMMIT = 2 [(gogoproto.enumvalue_customname) = "BlockIDFlagCommit"]; 18 | // Voted for nil 19 | BLOCK_ID_FLAG_NIL = 3 [(gogoproto.enumvalue_customname) = "BlockIDFlagNil"]; 20 | } 21 | 22 | message ValidatorSet { 23 | repeated Validator validators = 1; 24 | Validator proposer = 2; 25 | int64 total_voting_power = 3; 26 | } 27 | 28 | message Validator { 29 | bytes address = 1; 30 | tendermint.crypto.PublicKey pub_key = 2 [(gogoproto.nullable) = false]; 31 | int64 voting_power = 3; 32 | int64 proposer_priority = 4; 33 | } 34 | 35 | message SimpleValidator { 36 | tendermint.crypto.PublicKey pub_key = 1; 37 | int64 voting_power = 2; 38 | } 39 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - "*" 7 | pull_request: 8 | branches: 9 | - "*" 10 | 11 | jobs: 12 | test: 13 | runs-on: ubuntu-latest 14 | 15 | services: 16 | postgres: 17 | image: postgres:13 18 | env: 19 | POSTGRES_USER: postgres 20 | POSTGRES_PASSWORD: 1234 21 | POSTGRES_DB: xian 22 | ports: 23 | - 5432:5432 24 | options: >- 25 | --health-cmd pg_isready 26 | --health-interval 10s 27 | --health-timeout 5s 28 | --health-retries 5 29 | 30 | steps: 31 | - name: Checkout repository 32 | uses: actions/checkout@v3 33 | 34 | - name: Set up Python 3.11.8 35 | uses: actions/setup-python@v4 36 | with: 37 | python-version: '3.11.8' 38 | 39 | - name: Install system dependencies 40 | run: sudo apt-get update && sudo apt-get install -y pkg-config libhdf5-dev build-essential 41 | 42 | - name: Clone xian-contracting repository 43 | run: git clone https://github.com/xian-network/xian-contracting.git 44 | 45 | - name: Set up Python environment 46 | run: python3.11 -m venv xian_venv 47 | 48 | - name: Activate virtual environment and install dependencies 49 | run: | 50 | source xian_venv/bin/activate 51 | pip install -e xian-contracting/ -e . 52 | pip install pytest # Install pytest explicitly 53 | 54 | - name: Run tests 55 | env: 56 | DATABASE_URL: postgres://postgres:1234@localhost:5432/xian 57 | run: | 58 | source xian_venv/bin/activate 59 | pytest tests 60 | -------------------------------------------------------------------------------- /src/xian/tools/genesis/contracts/dao.s.py: -------------------------------------------------------------------------------- 1 | import currency 2 | 3 | @export 4 | def transfer_from_dao(args: dict): 5 | contract_name = args.get('contract_name') 6 | amount = args.get('amount') 7 | to = args.get('to') 8 | 9 | assert contract_name is not None, 'Contract name is required' 10 | assert amount > 0, 'Amount must be greater than 0' 11 | assert to is not None, 'To is required' 12 | 13 | contract = importlib.import_module(contract_name) 14 | contract.transfer(amount=amount, to=to) 15 | 16 | @export 17 | def balance_stream(stream_id: str): 18 | currency.balance_stream(stream_id=stream_id) 19 | 20 | @export 21 | def create_stream(args: dict): 22 | receiver = args.get('receiver') 23 | rate = args.get('rate') 24 | begins = args.get('begins') 25 | closes = args.get('closes') 26 | currency.create_stream(receiver=receiver, rate=rate, begins=begins, closes=closes) 27 | 28 | @export 29 | def change_close_time(args: dict): 30 | stream_id = args.get('stream_id') 31 | new_close_time = args.get('new_close_time') 32 | assert stream_id is not None, 'Stream ID is required' 33 | assert new_close_time is not None, 'New close time is required' 34 | currency.change_close_time(stream_id=stream_id, new_close_time=new_close_time) 35 | 36 | @export 37 | def finalize_stream(args: dict): 38 | stream_id = args.get('stream_id') 39 | currency.finalize_stream(stream_id=stream_id) 40 | 41 | @export 42 | def close_balance_finalize(args: dict): 43 | stream_id = args.get('stream_id') 44 | assert stream_id is not None, 'Stream ID is required' 45 | currency.close_balance_finalize(stream_id=stream_id) 46 | -------------------------------------------------------------------------------- /protos/cometbft/types/v1/evidence.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.types.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1"; 5 | 6 | import "cometbft/types/v1/types.proto"; 7 | import "cometbft/types/v1/validator.proto"; 8 | import "gogoproto/gogo.proto"; 9 | import "google/protobuf/timestamp.proto"; 10 | 11 | // Evidence is a generic type for wrapping evidence of misbehavior by a validator. 12 | message Evidence { 13 | // The type of evidence. 14 | oneof sum { 15 | DuplicateVoteEvidence duplicate_vote_evidence = 1; 16 | LightClientAttackEvidence light_client_attack_evidence = 2; 17 | } 18 | } 19 | 20 | // DuplicateVoteEvidence contains evidence of a validator signed two conflicting votes. 21 | message DuplicateVoteEvidence { 22 | Vote vote_a = 1; 23 | Vote vote_b = 2; 24 | int64 total_voting_power = 3; 25 | int64 validator_power = 4; 26 | google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 27 | } 28 | 29 | // LightClientAttackEvidence contains evidence of a set of validators attempting to mislead a light client. 30 | message LightClientAttackEvidence { 31 | LightBlock conflicting_block = 1; 32 | int64 common_height = 2; 33 | repeated Validator byzantine_validators = 3; 34 | int64 total_voting_power = 4; 35 | google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 36 | } 37 | 38 | // EvidenceList is a list of evidence. 39 | message EvidenceList { 40 | repeated Evidence evidence = 1 [(gogoproto.nullable) = false]; 41 | } 42 | -------------------------------------------------------------------------------- /tests/abci_methods/utils.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import shutil 3 | import os 4 | 5 | def setup_cometbft_tmp(): 6 | # Copy the contents of the fixture folder to the temporary directory. 7 | # ensure that the temporary directory, /tmp/cometbft/ is empty before copying. 8 | teardown_cometbft_tmp() 9 | copy_fixture_to_cometbft_tmp() 10 | 11 | def copy_fixture_to_cometbft_tmp(): 12 | # Copy the contents of the fixture folder to the temporary directory. 13 | # ensure that the temporary directory, /tmp/cometbft/ is empty before copying. 14 | fixture_ = Path('./fixtures/.cometbft-fixture') 15 | cometbft_tmp_ = Path('/tmp/cometbft/') 16 | shutil.copytree(fixture_, cometbft_tmp_) 17 | 18 | def teardown_cometbft_tmp(): 19 | # Remove the temporary directory /tmp/cometbft/ and all its contents. 20 | cometbft_tmp_ = Path('/tmp/cometbft/') 21 | if cometbft_tmp_.exists() and cometbft_tmp_.is_dir(): 22 | shutil.rmtree(cometbft_tmp_) 23 | 24 | def setup_fixtures(): 25 | # Set the working directory to the directory containing this file 26 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 27 | # Ensure the fixtures directory exists 28 | fixtures_dir = Path("./fixtures/.cometbft-fixture") 29 | if not fixtures_dir.exists(): 30 | raise FileNotFoundError(f"Fixture directory {fixtures_dir} does not exist.") 31 | 32 | # Ensure the temporary directory is set up 33 | cometbft_tmp_dir = Path("/tmp/cometbft/") 34 | if cometbft_tmp_dir.exists(): 35 | shutil.rmtree(cometbft_tmp_dir) 36 | shutil.copytree(fixtures_dir, cometbft_tmp_dir) 37 | 38 | 39 | # Cleanup after tests 40 | 41 | def teardown_fixtures(): 42 | cometbft_tmp_dir = Path("/tmp/cometbft/") 43 | if cometbft_tmp_dir.exists(): 44 | shutil.rmtree(cometbft_tmp_dir) -------------------------------------------------------------------------------- /tests/governance/utils.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import shutil 3 | import os 4 | 5 | def setup_cometbft_tmp(): 6 | # Copy the contents of the fixture folder to the temporary directory. 7 | # ensure that the temporary directory, /tmp/cometbft/ is empty before copying. 8 | teardown_cometbft_tmp() 9 | copy_fixture_to_cometbft_tmp() 10 | 11 | def copy_fixture_to_cometbft_tmp(): 12 | # Copy the contents of the fixture folder to the temporary directory. 13 | # ensure that the temporary directory, /tmp/cometbft/ is empty before copying. 14 | fixture_ = Path('./fixtures/.cometbft-fixture') 15 | cometbft_tmp_ = Path('/tmp/cometbft/') 16 | shutil.copytree(fixture_, cometbft_tmp_) 17 | 18 | def teardown_cometbft_tmp(): 19 | # Remove the temporary directory /tmp/cometbft/ and all its contents. 20 | cometbft_tmp_ = Path('/tmp/cometbft/') 21 | if cometbft_tmp_.exists() and cometbft_tmp_.is_dir(): 22 | shutil.rmtree(cometbft_tmp_) 23 | 24 | def setup_fixtures(): 25 | # Set the working directory to the directory containing this file 26 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 27 | # Ensure the fixtures directory exists 28 | fixtures_dir = Path("./fixtures/.cometbft-fixture") 29 | if not fixtures_dir.exists(): 30 | raise FileNotFoundError(f"Fixture directory {fixtures_dir} does not exist.") 31 | 32 | # Ensure the temporary directory is set up 33 | cometbft_tmp_dir = Path("/tmp/cometbft/") 34 | if cometbft_tmp_dir.exists(): 35 | shutil.rmtree(cometbft_tmp_dir) 36 | shutil.copytree(fixtures_dir, cometbft_tmp_dir) 37 | 38 | 39 | # Cleanup after tests 40 | 41 | def teardown_fixtures(): 42 | cometbft_tmp_dir = Path("/tmp/cometbft/") 43 | if cometbft_tmp_dir.exists(): 44 | shutil.rmtree(cometbft_tmp_dir) -------------------------------------------------------------------------------- /tests/integration/utils.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import shutil 3 | import os 4 | 5 | def setup_cometbft_tmp(): 6 | # Copy the contents of the fixture folder to the temporary directory. 7 | # ensure that the temporary directory, /tmp/cometbft/ is empty before copying. 8 | teardown_cometbft_tmp() 9 | copy_fixture_to_cometbft_tmp() 10 | 11 | def copy_fixture_to_cometbft_tmp(): 12 | # Copy the contents of the fixture folder to the temporary directory. 13 | # ensure that the temporary directory, /tmp/cometbft/ is empty before copying. 14 | fixture_ = Path('./fixtures/.cometbft-fixture') 15 | cometbft_tmp_ = Path('/tmp/cometbft/') 16 | shutil.copytree(fixture_, cometbft_tmp_) 17 | 18 | def teardown_cometbft_tmp(): 19 | # Remove the temporary directory /tmp/cometbft/ and all its contents. 20 | cometbft_tmp_ = Path('/tmp/cometbft/') 21 | if cometbft_tmp_.exists() and cometbft_tmp_.is_dir(): 22 | shutil.rmtree(cometbft_tmp_) 23 | 24 | def setup_fixtures(): 25 | # Set the working directory to the directory containing this file 26 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 27 | # Ensure the fixtures directory exists 28 | fixtures_dir = Path("./fixtures/.cometbft-fixture") 29 | if not fixtures_dir.exists(): 30 | raise FileNotFoundError(f"Fixture directory {fixtures_dir} does not exist.") 31 | 32 | # Ensure the temporary directory is set up 33 | cometbft_tmp_dir = Path("/tmp/cometbft/") 34 | if cometbft_tmp_dir.exists(): 35 | shutil.rmtree(cometbft_tmp_dir) 36 | shutil.copytree(fixtures_dir, cometbft_tmp_dir) 37 | 38 | 39 | # Cleanup after tests 40 | 41 | def teardown_fixtures(): 42 | cometbft_tmp_dir = Path("/tmp/cometbft/") 43 | if cometbft_tmp_dir.exists(): 44 | shutil.rmtree(cometbft_tmp_dir) -------------------------------------------------------------------------------- /protos/cometbft/consensus/v1beta1/wal.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.consensus.v1beta1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/consensus/v1beta1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cometbft/consensus/v1beta1/types.proto"; 8 | import "cometbft/types/v1beta1/events.proto"; 9 | import "google/protobuf/duration.proto"; 10 | import "google/protobuf/timestamp.proto"; 11 | 12 | // MsgInfo are msgs from the reactor which may update the state 13 | message MsgInfo { 14 | Message msg = 1 [(gogoproto.nullable) = false]; 15 | string peer_id = 2 [(gogoproto.customname) = "PeerID"]; 16 | } 17 | 18 | // TimeoutInfo internally generated messages which may update the state 19 | message TimeoutInfo { 20 | google.protobuf.Duration duration = 1 21 | [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; 22 | int64 height = 2; 23 | int32 round = 3; 24 | uint32 step = 4; 25 | } 26 | 27 | // EndHeight marks the end of the given height inside WAL. 28 | // @internal used by scripts/wal2json util. 29 | message EndHeight { 30 | int64 height = 1; 31 | } 32 | 33 | // WALMessage describes a consensus WAL (Write Ahead Log) entry. 34 | message WALMessage { 35 | // Sum of all possible messages. 36 | oneof sum { 37 | cometbft.types.v1beta1.EventDataRoundState event_data_round_state = 1; 38 | MsgInfo msg_info = 2; 39 | TimeoutInfo timeout_info = 3; 40 | EndHeight end_height = 4; 41 | } 42 | } 43 | 44 | // TimedWALMessage wraps WALMessage and adds Time for debugging purposes. 45 | message TimedWALMessage { 46 | google.protobuf.Timestamp time = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 47 | WALMessage msg = 2; 48 | } 49 | -------------------------------------------------------------------------------- /src/xian/tools/genesis/contracts/contracts_rcnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension": ".s.py", 3 | "contracts": [ 4 | { 5 | "name": "currency", 6 | "owner": null, 7 | "constructor_args": { 8 | "vk": "13ca9a62d10cbc28d55408e0a85d31f5c059fe3bb49316538e1d03064f3f2c8e" 9 | } 10 | }, 11 | { 12 | "name": "stamp_cost", 13 | "owner": "masternodes", 14 | "constructor_args": { 15 | "initial_rate": 20 16 | } 17 | }, 18 | { 19 | "name": "rewards", 20 | "owner": "masternodes", 21 | "constructor_args": null 22 | }, 23 | { 24 | "name": "foundation", 25 | "owner": null, 26 | "constructor_args": { 27 | "vk": "13ca9a62d10cbc28d55408e0a85d31f5c059fe3bb49316538e1d03064f3f2c8e" 28 | } 29 | }, 30 | { 31 | "name": "dao", 32 | "owner": "masternodes", 33 | "constructor_args": null 34 | }, 35 | { 36 | "name": "members", 37 | "submit_as": "masternodes", 38 | "owner": null, 39 | "constructor_args": { 40 | "genesis_nodes": ["13ca9a62d10cbc28d55408e0a85d31f5c059fe3bb49316538e1d03064f3f2c8e","d37ddb28488fe1bae65279934d6800fae11b26f7c01511b76ca6e602bbc2398d", "40447f46cea1260dd7487833cff630a65b7868f19aafdfd6465b989c9a6dba0e","8e73052eed03e60d4f27e4e422c0742cd2a755ac034122bd504a87afad746f8a","ca9aeee192854dc55a6d3e211bf858cc3ecd41e8b86a55c07740ece29f349597"], 41 | "genesis_registration_fee": 100000 42 | } 43 | }, 44 | { 45 | "name": "vault", 46 | "submit_as": "team_lock", 47 | "owner": null, 48 | "constructor_args": { 49 | "initial_owners":"6ebd8090a80e5fc629f38fceefd05d66035a5a4d4ba2c223319ec8f9b83cb48a,081e233f4e122a5fd79ff3c44f9d58848c3214f7110130936661394403100a9a,503ccb3dc04eaaed7c72c3ee6d22368e48a7f7e52b8577f4a4a9989eec51a0be", 50 | "initial_required_signatures": 2, 51 | "stream": "team_vesting" 52 | } 53 | } 54 | ] 55 | } 56 | -------------------------------------------------------------------------------- /protos/cometbft/types/v1beta1/evidence.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.types.v1beta1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "google/protobuf/timestamp.proto"; 8 | import "cometbft/types/v1beta1/types.proto"; 9 | import "cometbft/types/v1beta1/validator.proto"; 10 | 11 | // Evidence is a generic type for wrapping evidence of misbehavior by a validator. 12 | message Evidence { 13 | // The type of evidence. 14 | oneof sum { 15 | DuplicateVoteEvidence duplicate_vote_evidence = 1; 16 | LightClientAttackEvidence light_client_attack_evidence = 2; 17 | } 18 | } 19 | 20 | // DuplicateVoteEvidence contains evidence of a validator signed two conflicting votes. 21 | message DuplicateVoteEvidence { 22 | cometbft.types.v1beta1.Vote vote_a = 1; 23 | cometbft.types.v1beta1.Vote vote_b = 2; 24 | int64 total_voting_power = 3; 25 | int64 validator_power = 4; 26 | google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 27 | } 28 | 29 | // LightClientAttackEvidence contains evidence of a set of validators attempting to mislead a light client. 30 | message LightClientAttackEvidence { 31 | cometbft.types.v1beta1.LightBlock conflicting_block = 1; 32 | int64 common_height = 2; 33 | repeated cometbft.types.v1beta1.Validator byzantine_validators = 3; 34 | int64 total_voting_power = 4; 35 | google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 36 | } 37 | 38 | // EvidenceList is a list of evidence. 39 | message EvidenceList { 40 | repeated Evidence evidence = 1 [(gogoproto.nullable) = false]; 41 | } 42 | -------------------------------------------------------------------------------- /protos/cometbft/consensus/v1/wal.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.consensus.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/consensus/v1"; 5 | 6 | import "cometbft/consensus/v1/types.proto"; 7 | import "cometbft/types/v1/events.proto"; 8 | 9 | import "gogoproto/gogo.proto"; 10 | import "google/protobuf/duration.proto"; 11 | import "google/protobuf/timestamp.proto"; 12 | 13 | // MsgInfo are msgs from the reactor which may update the state 14 | message MsgInfo { 15 | Message msg = 1 [(gogoproto.nullable) = false]; 16 | string peer_id = 2 [(gogoproto.customname) = "PeerID"]; 17 | google.protobuf.Timestamp receive_time = 3 [(gogoproto.stdtime) = true, (gogoproto.nullable) = true]; 18 | } 19 | 20 | // TimeoutInfo internally generated messages which may update the state 21 | message TimeoutInfo { 22 | google.protobuf.Duration duration = 1 23 | [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; 24 | int64 height = 2; 25 | int32 round = 3; 26 | uint32 step = 4; 27 | } 28 | 29 | // EndHeight marks the end of the given height inside WAL. 30 | // @internal used by scripts/wal2json util. 31 | message EndHeight { 32 | int64 height = 1; 33 | } 34 | 35 | // WALMessage describes a consensus WAL (Write Ahead Log) entry. 36 | message WALMessage { 37 | // Sum of all possible messages. 38 | oneof sum { 39 | cometbft.types.v1.EventDataRoundState event_data_round_state = 1; 40 | MsgInfo msg_info = 2; 41 | TimeoutInfo timeout_info = 3; 42 | EndHeight end_height = 4; 43 | } 44 | } 45 | 46 | // TimedWALMessage wraps WALMessage and adds Time for debugging purposes. 47 | message TimedWALMessage { 48 | google.protobuf.Timestamp time = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 49 | WALMessage msg = 2; 50 | } 51 | -------------------------------------------------------------------------------- /protos/cometbft/types/v1/validator.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.types.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cometbft/crypto/v1/keys.proto"; 8 | 9 | // BlockIdFlag indicates which BlockID the signature is for 10 | enum BlockIDFlag { 11 | option (gogoproto.goproto_enum_stringer) = true; 12 | option (gogoproto.goproto_enum_prefix) = false; 13 | 14 | // Indicates an error condition 15 | BLOCK_ID_FLAG_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "BlockIDFlagUnknown"]; 16 | // The vote was not received 17 | BLOCK_ID_FLAG_ABSENT = 1 [(gogoproto.enumvalue_customname) = "BlockIDFlagAbsent"]; 18 | // Voted for the block that received the majority 19 | BLOCK_ID_FLAG_COMMIT = 2 [(gogoproto.enumvalue_customname) = "BlockIDFlagCommit"]; 20 | // Voted for nil 21 | BLOCK_ID_FLAG_NIL = 3 [(gogoproto.enumvalue_customname) = "BlockIDFlagNil"]; 22 | } 23 | 24 | // ValidatorSet defines a set of validators. 25 | message ValidatorSet { 26 | repeated Validator validators = 1; 27 | Validator proposer = 2; 28 | int64 total_voting_power = 3; 29 | } 30 | 31 | // Validator represents a node participating in the consensus protocol. 32 | message Validator { 33 | bytes address = 1; 34 | cometbft.crypto.v1.PublicKey pub_key = 2 [(gogoproto.nullable) = false]; 35 | int64 voting_power = 3; 36 | int64 proposer_priority = 4; 37 | } 38 | 39 | // SimpleValidator is a Validator, which is serialized and hashed in consensus. 40 | // Address is removed because it's redundant with the pubkey. 41 | // Proposer priority is removed because it changes every round. 42 | message SimpleValidator { 43 | cometbft.crypto.v1.PublicKey pub_key = 1; 44 | int64 voting_power = 2; 45 | } 46 | -------------------------------------------------------------------------------- /protos/cometbft/types/v1beta1/validator.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.types.v1beta1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cometbft/crypto/v1/keys.proto"; 8 | 9 | // BlockIdFlag indicates which BlockID the signature is for 10 | enum BlockIDFlag { 11 | option (gogoproto.goproto_enum_stringer) = true; 12 | option (gogoproto.goproto_enum_prefix) = false; 13 | 14 | // Indicates an error condition 15 | BLOCK_ID_FLAG_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "BlockIDFlagUnknown"]; 16 | // The vote was not received 17 | BLOCK_ID_FLAG_ABSENT = 1 [(gogoproto.enumvalue_customname) = "BlockIDFlagAbsent"]; 18 | // Voted for the block that received the majority 19 | BLOCK_ID_FLAG_COMMIT = 2 [(gogoproto.enumvalue_customname) = "BlockIDFlagCommit"]; 20 | // Voted for nil 21 | BLOCK_ID_FLAG_NIL = 3 [(gogoproto.enumvalue_customname) = "BlockIDFlagNil"]; 22 | } 23 | 24 | // ValidatorSet defines a set of validators. 25 | message ValidatorSet { 26 | repeated Validator validators = 1; 27 | Validator proposer = 2; 28 | int64 total_voting_power = 3; 29 | } 30 | 31 | // Validator represents a node participating in the consensus protocol. 32 | message Validator { 33 | bytes address = 1; 34 | cometbft.crypto.v1.PublicKey pub_key = 2 [(gogoproto.nullable) = false]; 35 | int64 voting_power = 3; 36 | int64 proposer_priority = 4; 37 | } 38 | 39 | // SimpleValidator is a Validator, which is serialized and hashed in consensus. 40 | // Address is removed because it's redundant with the pubkey. 41 | // Proposer priority is removed because it changes every round. 42 | message SimpleValidator { 43 | cometbft.crypto.v1.PublicKey pub_key = 1; 44 | int64 voting_power = 2; 45 | } 46 | -------------------------------------------------------------------------------- /tests/integration/contracts/rollback/con_mutable_map.py: -------------------------------------------------------------------------------- 1 | nested = Hash() 2 | aliased = Hash(default_value={"count": 0, "items": []}) 3 | 4 | @export 5 | def init_key(key: str): 6 | assert ":" not in key and "." not in key, "Illegal key" 7 | nested[key] = {"count": 1, "items": [1]} 8 | 9 | @export 10 | def mutate_in_place_and_fail(key: str): 11 | d = nested[key] 12 | d["count"] = d.get("count", 0) + 1 13 | d["items"].append(2) 14 | assert False, "Forced failure after in-place mutation" 15 | 16 | @export 17 | def read(key: str): 18 | return nested[key] 19 | 20 | @export 21 | def init_nested(key: str): 22 | assert ":" not in key and "." not in key, "Illegal key" 23 | nested[key] = {"child": {"x": 1}, "items": [{"v": 1}]} 24 | 25 | @export 26 | def mutate_nested_and_fail(key: str): 27 | d = nested[key] 28 | d["child"]["x"] = d["child"].get("x", 0) + 1 29 | d["items"][0]["v"] = 2 30 | assert False, "Forced failure after deep in-place mutation" 31 | 32 | @export 33 | def mutate_then_reassign_and_fail(key: str): 34 | d = nested[key] 35 | d["count"] = d.get("count", 0) + 1 36 | nested[key] = d 37 | assert False, "Forced failure after reassign" 38 | 39 | @export 40 | def cross_mutate_then_fail(key: str, mutator: str = "con_mutator"): 41 | m = importlib.import_module(mutator) 42 | m.mutate_target(key=key, target_contract=str(ctx.this)) 43 | assert False, "Forced failure after cross-contract mutation" 44 | 45 | @export 46 | def alias_set(key: str): 47 | assert ":" not in key and "." not in key, "Illegal key" 48 | v = aliased[key] 49 | aliased[key] = {"count": v.get("count", 0), "items": list(v.get("items", []))} 50 | 51 | @export 52 | def alias_mutate_and_fail(key: str): 53 | d = aliased[key] 54 | d["count"] = d.get("count", 0) + 1 55 | d["items"].append(7) 56 | assert False, "Forced failure after alias mutate" 57 | 58 | @export 59 | def type_error_after_mutation(key: str): 60 | d = nested[key] 61 | d["count"] = d["count"] + 1 62 | oops = 1 + "x" 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/xian/validators.py: -------------------------------------------------------------------------------- 1 | from cometbft.abci.v1beta1.types_pb2 import ValidatorUpdate 2 | from cometbft.crypto.v1.keys_pb2 import PublicKey 3 | import requests 4 | import base64 5 | import logging 6 | 7 | 8 | class ValidatorHandler: 9 | def __init__(self, app): 10 | self.client = app.client 11 | 12 | def get_validators_from_state(self) -> list[str]: 13 | validators = self.client.raw_driver.get("masternodes.nodes") 14 | return validators 15 | 16 | def get_tendermint_validators(self) -> list[str]: 17 | try: 18 | response = requests.get("http://localhost:26657/validators") 19 | validators = [base64.b64decode(validator['pub_key']['value']).hex() for validator in response.json()['result']['validators'] if int(validator['voting_power']) > 0] 20 | except Exception as e: 21 | validators = [] 22 | return validators 23 | 24 | def to_bytes(self, data: str) -> bytes: 25 | return bytes.fromhex(data) 26 | 27 | def build_validator_updates(self, height) -> list[ValidatorUpdate]: 28 | validators_state = self.get_validators_from_state() 29 | validators_tendermint = self.get_tendermint_validators() 30 | if len(validators_tendermint) == 0: 31 | logging.error("Failed to get validators from tendermint") 32 | return [] 33 | updates = [] 34 | for validator in validators_state: 35 | if validator not in validators_tendermint: 36 | updates.append(ValidatorUpdate(pub_key=PublicKey(ed25519=self.to_bytes(validator)), power=10)) 37 | logging.info(f"Adding {validator} to tendermint validators") 38 | for validator in validators_tendermint: 39 | if validator not in validators_state: 40 | updates.append(ValidatorUpdate(pub_key=PublicKey(ed25519=self.to_bytes(validator)), power=0)) 41 | logging.info(f"Removing {validator} from tendermint validators") 42 | 43 | return updates 44 | -------------------------------------------------------------------------------- /tests/abci_methods/test_commit.py: -------------------------------------------------------------------------------- 1 | import os 2 | import unittest 3 | from io import BytesIO 4 | import logging 5 | import asyncio 6 | 7 | from xian.xian_abci import Xian 8 | from abci.server import ProtocolHandler 9 | from abci.utils import read_messages 10 | 11 | from cometbft.abci.v1beta3.types_pb2 import ( 12 | Request, 13 | Response, 14 | ResponseCommit, 15 | ) 16 | from cometbft.abci.v1beta1.types_pb2 import ( 17 | RequestCommit, 18 | ) 19 | 20 | from fixtures.mock_constants import MockConstants 21 | from utils import setup_fixtures, teardown_fixtures 22 | # Disable any kind of logging 23 | logging.disable(logging.CRITICAL) 24 | 25 | async def deserialize(raw: bytes) -> Response: 26 | try: 27 | resp = next(read_messages(BytesIO(raw), Response)) 28 | return resp 29 | except Exception as e: 30 | logging.error("Deserialization error: %s", e) 31 | raise 32 | 33 | class TestCommit(unittest.IsolatedAsyncioTestCase): 34 | 35 | async def asyncSetUp(self): 36 | setup_fixtures() 37 | self.app = await Xian.create(constants=MockConstants) 38 | self.app.current_block_meta = {"height": 0, "nanos": 0} 39 | self.app.merkle_root_hash = b'abc123' 40 | self.app.chain_id = "xian-testnet-1" 41 | self.app.fingerprint_hashes = [] 42 | self.app.current_block_rewards = {} 43 | self.handler = ProtocolHandler(self.app) 44 | 45 | async def asyncTearDown(self): 46 | teardown_fixtures() 47 | 48 | 49 | async def process_request(self, request_type, req): 50 | raw = await self.handler.process(request_type, req) 51 | resp = await deserialize(raw) 52 | return resp 53 | 54 | async def test_commit(self): 55 | # breakpoint() 56 | request = Request(commit=RequestCommit()) 57 | response = await self.process_request("commit", request) 58 | self.assertEqual(response.commit.retain_height, 0) 59 | 60 | if __name__ == "__main__": 61 | unittest.main() 62 | -------------------------------------------------------------------------------- /src/xian/formatting.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | 4 | def vk_is_formatted(s: str): 5 | try: 6 | int(s, 16) 7 | if len(s) != 64: 8 | return False 9 | return True 10 | except ValueError: 11 | return False 12 | except TypeError: 13 | return False 14 | 15 | 16 | def signature_is_formatted(s: str): 17 | try: 18 | int(s, 16) 19 | if len(s) != 128: 20 | return False 21 | return True 22 | except ValueError: 23 | return False 24 | except TypeError: 25 | return False 26 | 27 | 28 | def identifier_is_formatted(s: str): 29 | try: 30 | iden = re.match(r'^[a-zA-Z][a-zA-Z0-9_]*$', s) 31 | if iden is None: 32 | return False 33 | return True 34 | except TypeError: 35 | return False 36 | 37 | 38 | def kwargs_are_formatted(k: dict): 39 | for k in k.keys(): 40 | if not identifier_is_formatted(k): 41 | return False 42 | return True 43 | 44 | 45 | def number_is_formatted(i: int): 46 | if type(i) != int: 47 | return False 48 | if i < 0: 49 | return False 50 | return True 51 | 52 | 53 | def cid_id_formated(s: str): 54 | return isinstance(s, str) 55 | 56 | 57 | def contract_name_is_formatted(s: str): 58 | try: 59 | func = re.match(r'^con_[a-zA-Z][a-zA-Z0-9_]*$', s) 60 | if func is None: 61 | return False 62 | return True 63 | except TypeError: 64 | return False 65 | 66 | 67 | TRANSACTION_PAYLOAD_RULES = { 68 | 'sender': vk_is_formatted, 69 | 'nonce': number_is_formatted, 70 | 'stamps_supplied': number_is_formatted, 71 | 'contract': identifier_is_formatted, 72 | 'function': identifier_is_formatted, 73 | 'kwargs': kwargs_are_formatted, 74 | 'chain_id': cid_id_formated 75 | } 76 | 77 | TRANSACTION_METADATA_RULES = { 78 | 'signature': signature_is_formatted 79 | } 80 | 81 | TRANSACTION_RULES = { 82 | 'metadata': TRANSACTION_METADATA_RULES, 83 | 'payload': TRANSACTION_PAYLOAD_RULES 84 | } 85 | -------------------------------------------------------------------------------- /src/xian/tools/state_patches/state_patches.json: -------------------------------------------------------------------------------- 1 | { 2 | "2451": [ 3 | { 4 | "key": "currency.balances:what", 5 | "value": 1000000000, 6 | "comment": "Testing the state patcher" 7 | } 8 | ], 9 | "2455": [ 10 | { 11 | "key": "masternodes.types", 12 | "value": {"types": ["add_member", "remove_member", "change_registration_fee", "reward_change", "dao_payout", "stamp_cost_change", "change_types", "create_stream", "change_close_time", "finalize_stream", "close_balance_finalize", "topic_vote", "some_new_type"]}, 13 | "comment": "Testing Adding New Types" 14 | } 15 | ], 16 | "2460": [ 17 | { 18 | "key": "masternodes.types", 19 | "value": ["add_member", "remove_member", "change_registration_fee", "reward_change", "dao_payout", "stamp_cost_change", "change_types", "create_stream", "change_close_time", "finalize_stream", "close_balance_finalize", "topic_vote", "some_new_type"], 20 | "comment": "Testing Adding New Types" 21 | } 22 | ], 23 | "2465": [ 24 | { 25 | "key": "con_test_deploy_update.__code__", 26 | "value": "# Version 1: Initial Deploy\n\nversion = Variable()\n\n@construct\ndef seed():\n version.set('v1.0')\n\n@export\ndef get_version():\n return version.get()", 27 | "comment": "Deploy the initial version (v1.0) of con_test_deploy_update" 28 | } 29 | ], 30 | "2470": [ 31 | { 32 | "key": "con_test_deploy_update.__code__", 33 | "value": "# Version 2: Update Contract\n\nversion = Variable()\nmessage = Variable()\n\n@construct\ndef seed():\n version.set('v2.0')\n message.set('Hello from v2!')\n\n@export\ndef get_version():\n return version.get()\n\n@export\ndef get_message():\n return message.get()", 34 | "comment": "Update con_test_deploy_update to v2.0, adding a message variable and getter" 35 | }, 36 | { 37 | "key": "con_test_deploy_update.message", 38 | "value": "Updated message via patch!", 39 | "comment": "Optionally, also patch a variable value during the contract update block" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /protos/cometbft/types/v1beta1/canonical.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.types.v1beta1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cometbft/types/v1beta1/types.proto"; 8 | import "google/protobuf/timestamp.proto"; 9 | 10 | // CanonicalBlockID is a canonical representation of a BlockID, which gets 11 | // serialized and signed. 12 | message CanonicalBlockID { 13 | bytes hash = 1; 14 | CanonicalPartSetHeader part_set_header = 2 [(gogoproto.nullable) = false]; 15 | } 16 | 17 | // CanonicalPartSetHeader is a canonical representation of a PartSetHeader, 18 | // which gets serialized and signed. 19 | message CanonicalPartSetHeader { 20 | uint32 total = 1; 21 | bytes hash = 2; 22 | } 23 | 24 | // CanonicalProposal is a canonical representation of a Proposal, which gets 25 | // serialized and signed. 26 | message CanonicalProposal { 27 | SignedMsgType type = 1; // type alias for byte 28 | sfixed64 height = 2; // canonicalization requires fixed size encoding here 29 | sfixed64 round = 3; // canonicalization requires fixed size encoding here 30 | int64 pol_round = 4 [(gogoproto.customname) = "POLRound"]; 31 | CanonicalBlockID block_id = 5 [(gogoproto.customname) = "BlockID"]; 32 | google.protobuf.Timestamp timestamp = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 33 | string chain_id = 7 [(gogoproto.customname) = "ChainID"]; 34 | } 35 | 36 | // CanonicalVote is a canonical representation of a Vote, which gets 37 | // serialized and signed. 38 | message CanonicalVote { 39 | SignedMsgType type = 1; // type alias for byte 40 | sfixed64 height = 2; // canonicalization requires fixed size encoding here 41 | sfixed64 round = 3; // canonicalization requires fixed size encoding here 42 | CanonicalBlockID block_id = 4 [(gogoproto.customname) = "BlockID"]; 43 | google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 44 | string chain_id = 6 [(gogoproto.customname) = "ChainID"]; 45 | } 46 | -------------------------------------------------------------------------------- /protos/cometbft/abci/v1/service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.abci.v1; 3 | 4 | import "cometbft/abci/v1/types.proto"; 5 | 6 | option go_package = "github.com/cometbft/cometbft/api/cometbft/abci/v1"; 7 | 8 | // ABCIService is a service for an ABCI application. 9 | service ABCIService { 10 | // Echo returns back the same message it is sent. 11 | rpc Echo(EchoRequest) returns (EchoResponse); 12 | // Flush flushes the write buffer. 13 | rpc Flush(FlushRequest) returns (FlushResponse); 14 | // Info returns information about the application state. 15 | rpc Info(InfoRequest) returns (InfoResponse); 16 | // CheckTx validates a transaction. 17 | rpc CheckTx(CheckTxRequest) returns (CheckTxResponse); 18 | // Query queries the application state. 19 | rpc Query(QueryRequest) returns (QueryResponse); 20 | // Commit commits a block of transactions. 21 | rpc Commit(CommitRequest) returns (CommitResponse); 22 | // InitChain initializes the blockchain. 23 | rpc InitChain(InitChainRequest) returns (InitChainResponse); 24 | // ListSnapshots lists all the available snapshots. 25 | rpc ListSnapshots(ListSnapshotsRequest) returns (ListSnapshotsResponse); 26 | // OfferSnapshot sends a snapshot offer. 27 | rpc OfferSnapshot(OfferSnapshotRequest) returns (OfferSnapshotResponse); 28 | // LoadSnapshotChunk returns a chunk of snapshot. 29 | rpc LoadSnapshotChunk(LoadSnapshotChunkRequest) returns (LoadSnapshotChunkResponse); 30 | // ApplySnapshotChunk applies a chunk of snapshot. 31 | rpc ApplySnapshotChunk(ApplySnapshotChunkRequest) returns (ApplySnapshotChunkResponse); 32 | // PrepareProposal returns a proposal for the next block. 33 | rpc PrepareProposal(PrepareProposalRequest) returns (PrepareProposalResponse); 34 | // ProcessProposal validates a proposal. 35 | rpc ProcessProposal(ProcessProposalRequest) returns (ProcessProposalResponse); 36 | // ExtendVote extends a vote with application-injected data (vote extensions). 37 | rpc ExtendVote(ExtendVoteRequest) returns (ExtendVoteResponse); 38 | // VerifyVoteExtension verifies a vote extension. 39 | rpc VerifyVoteExtension(VerifyVoteExtensionRequest) returns (VerifyVoteExtensionResponse); 40 | // FinalizeBlock finalizes a block. 41 | rpc FinalizeBlock(FinalizeBlockRequest) returns (FinalizeBlockResponse); 42 | } 43 | -------------------------------------------------------------------------------- /tests/abci_methods/test_info.py: -------------------------------------------------------------------------------- 1 | import os 2 | import unittest 3 | from io import BytesIO 4 | import logging 5 | import asyncio 6 | 7 | from xian.xian_abci import Xian 8 | from abci.server import ProtocolHandler 9 | from abci.utils import read_messages 10 | from fixtures.mock_constants import MockConstants 11 | 12 | from cometbft.abci.v1beta3.types_pb2 import ( 13 | Request, 14 | Response, 15 | ) 16 | 17 | from cometbft.abci.v1beta2.types_pb2 import ( 18 | RequestInfo, 19 | ) 20 | 21 | from cometbft.abci.v1beta1.types_pb2 import ResponseInfo, RequestCommit 22 | 23 | from utils import setup_fixtures, teardown_fixtures 24 | 25 | # Disable any kind of logging 26 | logging.disable(logging.CRITICAL) 27 | 28 | async def deserialize(raw: bytes) -> Response: 29 | try: 30 | resp = next(read_messages(BytesIO(raw), Response)) 31 | return resp 32 | except Exception as e: 33 | logging.error("Deserialization error: %s", e) 34 | raise 35 | 36 | class TestInfo(unittest.IsolatedAsyncioTestCase): 37 | 38 | async def asyncSetUp(self): 39 | setup_fixtures() 40 | self.app = await Xian.create(constants=MockConstants) 41 | self.app.current_block_meta = {"height": 0, "nanos": 0} 42 | self.handler = ProtocolHandler(self.app) 43 | self.app.merkle_root_hash = b'' 44 | 45 | async def asyncTearDown(self): 46 | teardown_fixtures() 47 | 48 | async def process_request(self, request_type, req): 49 | raw = await self.handler.process(request_type, req) 50 | resp = await deserialize(raw) 51 | return resp 52 | 53 | async def test_info(self): 54 | commit_request = Request(commit=RequestCommit()) 55 | await self.process_request("commit", commit_request) 56 | request = Request(info=RequestInfo()) 57 | response = await self.process_request("info", request) 58 | self.assertEqual(response.info.app_version, 1) 59 | self.assertEqual(response.info.data, "") # We don't use that 60 | self.assertEqual(response.info.version, "") # Not running CometBFT 61 | self.assertEqual(response.info.last_block_height, 0) 62 | self.assertEqual(response.info.last_block_app_hash, b"") 63 | 64 | if __name__ == "__main__": 65 | unittest.main() 66 | -------------------------------------------------------------------------------- /tests/integration/contracts/rollback/currency_1.py: -------------------------------------------------------------------------------- 1 | balances = Hash(default_value=0) 2 | metadata = Hash() 3 | 4 | TransferEvent = LogEvent(event="Transfer", params={"from":{'type':str, 'idx':True}, "to": {'type':str, 'idx':True}, "amount": {'type':(int, float, decimal)}}) 5 | ApproveEvent = LogEvent(event="Approve", params={"from":{'type':str, 'idx':True}, "to": {'type':str, 'idx':True}, "amount": {'type':(int, float, decimal)}}) 6 | ChangeMetadataEvent = LogEvent(event="ChangeMetadata", params={"key":{'type':str, 'idx':True}, "value": {'type':str, 'idx':False}}) 7 | 8 | @construct 9 | def seed(): 10 | balances[ctx.caller] = 1_000_000 11 | metadata['token_name'] = "TEST TOKEN" 12 | metadata['token_symbol'] = "TST" 13 | metadata['token_logo_url'] = 'https://some.token.url/test-token.png' 14 | metadata['token_website'] = 'https://some.token.url' 15 | metadata['operator'] = ctx.caller 16 | 17 | @export 18 | def change_metadata(key: str, value: Any): 19 | assert ctx.caller == metadata['operator'], 'Only operator can set metadata!' 20 | metadata[key] = value 21 | ChangeMetadataEvent({"key": key, "value": value}) 22 | 23 | @export 24 | def transfer(amount: float, to: str): 25 | assert amount > 0, 'Cannot send negative balances!' 26 | assert balances[ctx.caller] >= amount, 'Not enough coins to send!' 27 | balances[ctx.caller] -= amount 28 | balances[to] += amount 29 | TransferEvent({"from": ctx.caller, "to": to, "amount": amount}) 30 | return f"Sent {amount} to {to}" 31 | 32 | @export 33 | def approve(amount: float, to: str): 34 | assert amount > 0, 'Cannot send negative balances!' 35 | balances[ctx.caller, to] = amount 36 | ApproveEvent({"from": ctx.caller, "to": to, "amount": amount}) 37 | return f"Approved {amount} for {to}" 38 | 39 | @export 40 | def transfer_from(amount: float, to: str, main_account: str): 41 | assert amount > 0, 'Cannot send negative balances!' 42 | assert balances[main_account, ctx.caller] >= amount, f'Not enough coins approved to send! You have {balances[main_account, ctx.caller]} and are trying to spend {amount}' 43 | assert balances[main_account] >= amount, 'Not enough coins to send!' 44 | balances[main_account, ctx.caller] -= amount 45 | balances[main_account] -= amount 46 | balances[to] += amount 47 | TransferEvent({"from": main_account, "to": to, "amount": amount}) 48 | return f"Sent {amount} to {to} from {main_account}" 49 | 50 | 51 | -------------------------------------------------------------------------------- /tests/integration/contracts/token_contract.py: -------------------------------------------------------------------------------- 1 | balances = Hash(default_value=0) 2 | metadata = Hash() 3 | 4 | TransferEvent = LogEvent(event="Transfer", params={"from":{'type':str, 'idx':True}, "to": {'type':str, 'idx':True}, "amount": {'type':(int, float, decimal)}}) 5 | ApproveEvent = LogEvent(event="Approve", params={"from":{'type':str, 'idx':True}, "to": {'type':str, 'idx':True}, "amount": {'type':(int, float, decimal)}}) 6 | ChangeMetadataEvent = LogEvent(event="ChangeMetadata", params={"key":{'type':str, 'idx':True}, "value": {'type':str, 'idx':False}}) 7 | 8 | 9 | @construct 10 | def seed(): 11 | balances[ctx.caller] = 1_000_000 12 | 13 | metadata['token_name'] = "TEST TOKEN" 14 | metadata['token_symbol'] = "TST" 15 | metadata['token_logo_url'] = 'https://some.token.url/test-token.png' 16 | metadata['token_website'] = 'https://some.token.url' 17 | metadata['operator'] = ctx.caller 18 | 19 | 20 | @export 21 | def change_metadata(key: str, value: Any): 22 | assert ctx.caller == metadata['operator'], 'Only operator can set metadata!' 23 | metadata[key] = value 24 | ChangeMetadataEvent({"key": key, "value": value}) 25 | 26 | 27 | @export 28 | def transfer(amount: float, to: str): 29 | assert amount > 0, 'Cannot send negative balances!' 30 | assert balances[ctx.caller] >= amount, 'Not enough coins to send!' 31 | 32 | balances[ctx.caller] -= amount 33 | balances[to] += amount 34 | 35 | TransferEvent({"from": ctx.caller, "to": to, "amount": amount}) 36 | 37 | return f"Sent {amount} to {to}" 38 | 39 | 40 | @export 41 | def approve(amount: float, to: str): 42 | assert amount > 0, 'Cannot send negative balances!' 43 | balances[ctx.caller, to] = amount 44 | 45 | ApproveEvent({"from": ctx.caller, "to": to, "amount": amount}) 46 | 47 | return f"Approved {amount} for {to}" 48 | 49 | 50 | @export 51 | def transfer_from(amount: float, to: str, main_account: str): 52 | assert amount > 0, 'Cannot send negative balances!' 53 | assert balances[main_account, ctx.caller] >= amount, f'Not enough coins approved to send! You have {balances[main_account, ctx.caller]} and are trying to spend {amount}' 54 | assert balances[main_account] >= amount, 'Not enough coins to send!' 55 | 56 | balances[main_account, ctx.caller] -= amount 57 | balances[main_account] -= amount 58 | balances[to] += amount 59 | 60 | TransferEvent({"from": main_account, "to": to, "amount": amount}) 61 | 62 | return f"Sent {amount} to {to} from {main_account}" 63 | -------------------------------------------------------------------------------- /src/cometbft/services/version/v1/version_service_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: cometbft/services/version/v1/version_service.proto 4 | 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from cometbft.services.version.v1 import version_pb2 as cometbft_dot_services_dot_version_dot_v1_dot_version__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor.FileDescriptor( 18 | name='cometbft/services/version/v1/version_service.proto', 19 | package='cometbft.services.version.v1', 20 | syntax='proto3', 21 | serialized_options=b'Z=github.com/cometbft/cometbft/api/cometbft/services/version/v1', 22 | create_key=_descriptor._internal_create_key, 23 | serialized_pb=b'\n2cometbft/services/version/v1/version_service.proto\x12\x1c\x63ometbft.services.version.v1\x1a*cometbft/services/version/v1/version.proto2\x81\x01\n\x0eVersionService\x12o\n\nGetVersion\x12/.cometbft.services.version.v1.GetVersionRequest\x1a\x30.cometbft.services.version.v1.GetVersionResponseB?Z=github.com/cometbft/cometbft/api/cometbft/services/version/v1b\x06proto3' 24 | , 25 | dependencies=[cometbft_dot_services_dot_version_dot_v1_dot_version__pb2.DESCRIPTOR,]) 26 | 27 | 28 | 29 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 30 | 31 | 32 | DESCRIPTOR._options = None 33 | 34 | _VERSIONSERVICE = _descriptor.ServiceDescriptor( 35 | name='VersionService', 36 | full_name='cometbft.services.version.v1.VersionService', 37 | file=DESCRIPTOR, 38 | index=0, 39 | serialized_options=None, 40 | create_key=_descriptor._internal_create_key, 41 | serialized_start=129, 42 | serialized_end=258, 43 | methods=[ 44 | _descriptor.MethodDescriptor( 45 | name='GetVersion', 46 | full_name='cometbft.services.version.v1.VersionService.GetVersion', 47 | index=0, 48 | containing_service=None, 49 | input_type=cometbft_dot_services_dot_version_dot_v1_dot_version__pb2._GETVERSIONREQUEST, 50 | output_type=cometbft_dot_services_dot_version_dot_v1_dot_version__pb2._GETVERSIONRESPONSE, 51 | serialized_options=None, 52 | create_key=_descriptor._internal_create_key, 53 | ), 54 | ]) 55 | _sym_db.RegisterServiceDescriptor(_VERSIONSERVICE) 56 | 57 | DESCRIPTOR.services_by_name['VersionService'] = _VERSIONSERVICE 58 | 59 | # @@protoc_insertion_point(module_scope) 60 | -------------------------------------------------------------------------------- /protos/cometbft/types/v1/canonical.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.types.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cometbft/types/v1/types.proto"; 8 | import "google/protobuf/timestamp.proto"; 9 | 10 | // CanonicalBlockID is a canonical representation of a BlockID, which gets 11 | // serialized and signed. 12 | message CanonicalBlockID { 13 | bytes hash = 1; 14 | CanonicalPartSetHeader part_set_header = 2 [(gogoproto.nullable) = false]; 15 | } 16 | 17 | // CanonicalPartSetHeader is a canonical representation of a PartSetHeader, 18 | // which gets serialized and signed. 19 | message CanonicalPartSetHeader { 20 | uint32 total = 1; 21 | bytes hash = 2; 22 | } 23 | 24 | // CanonicalProposal is a canonical representation of a Proposal, which gets 25 | // serialized and signed. 26 | message CanonicalProposal { 27 | SignedMsgType type = 1; // type alias for byte 28 | sfixed64 height = 2; // canonicalization requires fixed size encoding here 29 | sfixed64 round = 3; // canonicalization requires fixed size encoding here 30 | int64 pol_round = 4 [(gogoproto.customname) = "POLRound"]; 31 | CanonicalBlockID block_id = 5 [(gogoproto.customname) = "BlockID"]; 32 | google.protobuf.Timestamp timestamp = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 33 | string chain_id = 7 [(gogoproto.customname) = "ChainID"]; 34 | } 35 | 36 | // CanonicalVote is a canonical representation of a Vote, which gets 37 | // serialized and signed. 38 | message CanonicalVote { 39 | SignedMsgType type = 1; // type alias for byte 40 | sfixed64 height = 2; // canonicalization requires fixed size encoding here 41 | sfixed64 round = 3; // canonicalization requires fixed size encoding here 42 | CanonicalBlockID block_id = 4 [(gogoproto.customname) = "BlockID"]; 43 | google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 44 | string chain_id = 6 [(gogoproto.customname) = "ChainID"]; 45 | } 46 | 47 | // CanonicalVoteExtension provides us a way to serialize a vote extension from 48 | // a particular validator such that we can sign over those serialized bytes. 49 | message CanonicalVoteExtension { 50 | bytes extension = 1; 51 | sfixed64 height = 2; 52 | sfixed64 round = 3; 53 | string chain_id = 4; 54 | } 55 | -------------------------------------------------------------------------------- /protos/cometbft/privval/v1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.privval.v1; 3 | 4 | import "cometbft/crypto/v1/keys.proto"; 5 | import "cometbft/types/v1/types.proto"; 6 | import "gogoproto/gogo.proto"; 7 | 8 | option go_package = "github.com/cometbft/cometbft/api/cometbft/privval/v1"; 9 | 10 | // remotesignererror is returned when the remote signer fails. 11 | message RemoteSignerError { 12 | int32 code = 1; 13 | string description = 2; 14 | } 15 | 16 | // PubKeyRequest requests the consensus public key from the remote signer. 17 | message PubKeyRequest { 18 | string chain_id = 1; 19 | } 20 | 21 | // PubKeyResponse is a response message containing the public key. 22 | message PubKeyResponse { 23 | cometbft.crypto.v1.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; 24 | RemoteSignerError error = 2; 25 | } 26 | 27 | // SignVoteRequest is a request to sign a vote 28 | message SignVoteRequest { 29 | cometbft.types.v1.Vote vote = 1; 30 | string chain_id = 2; 31 | bool skip_extension_signing = 3; // if true, the signer may skip signing the extension bytes. 32 | } 33 | 34 | // SignedVoteResponse is a response containing a signed vote or an error 35 | message SignedVoteResponse { 36 | cometbft.types.v1.Vote vote = 1 [(gogoproto.nullable) = false]; 37 | RemoteSignerError error = 2; 38 | } 39 | 40 | // SignProposalRequest is a request to sign a proposal 41 | message SignProposalRequest { 42 | cometbft.types.v1.Proposal proposal = 1; 43 | string chain_id = 2; 44 | } 45 | 46 | // SignedProposalResponse is response containing a signed proposal or an error 47 | message SignedProposalResponse { 48 | cometbft.types.v1.Proposal proposal = 1 [(gogoproto.nullable) = false]; 49 | RemoteSignerError error = 2; 50 | } 51 | 52 | // PingRequest is a request to confirm that the connection is alive. 53 | message PingRequest {} 54 | 55 | // PingResponse is a response to confirm that the connection is alive. 56 | message PingResponse {} 57 | 58 | // Message is an abstract message to/from the remote signer. 59 | message Message { 60 | // Sum of all possible messages. 61 | oneof sum { 62 | PubKeyRequest pub_key_request = 1; 63 | PubKeyResponse pub_key_response = 2; 64 | SignVoteRequest sign_vote_request = 3; 65 | SignedVoteResponse signed_vote_response = 4; 66 | SignProposalRequest sign_proposal_request = 5; 67 | SignedProposalResponse signed_proposal_response = 6; 68 | PingRequest ping_request = 7; 69 | PingResponse ping_response = 8; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /protos/cometbft/services/pruning/v1/pruning.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package cometbft.services.pruning.v1; 4 | 5 | // SetBlockRetainHeightRequest sets the retain height for blocks. 6 | message SetBlockRetainHeightRequest { 7 | uint64 height = 1; 8 | } 9 | 10 | // SetBlockRetainHeightResponse is empty. 11 | message SetBlockRetainHeightResponse {} 12 | 13 | // GetBlockRetainHeightRequest is a request for the retain height. 14 | message GetBlockRetainHeightRequest {} 15 | 16 | // GetBlockRetainHeightResponse returns the retain height for blocks. 17 | message GetBlockRetainHeightResponse { 18 | // The retain height set by the application. 19 | uint64 app_retain_height = 1; 20 | 21 | // The retain height set via the pruning service (e.g. by the data 22 | // companion) specifically for blocks. 23 | uint64 pruning_service_retain_height = 2; 24 | } 25 | 26 | // SetBlockResultsRetainHeightRequest sets the retain height for block results. 27 | message SetBlockResultsRetainHeightRequest { 28 | uint64 height = 1; 29 | } 30 | 31 | // SetBlockResultsRetainHeightResponse is empty. 32 | message SetBlockResultsRetainHeightResponse {} 33 | 34 | // GetBlockResultsRetainHeightRequest is a request for the retain height. 35 | message GetBlockResultsRetainHeightRequest {} 36 | 37 | // GetBlockResultsRetainHeightResponse returns the retain height for block results. 38 | message GetBlockResultsRetainHeightResponse { 39 | // The retain height set by the pruning service (e.g. by the data 40 | // companion) specifically for block results. 41 | uint64 pruning_service_retain_height = 1; 42 | } 43 | 44 | // SetTxIndexerRetainHeightRequest sets the retain height for the tx indexer. 45 | message SetTxIndexerRetainHeightRequest { 46 | uint64 height = 1; 47 | } 48 | 49 | // SetTxIndexerRetainHeightResponse is empty. 50 | message SetTxIndexerRetainHeightResponse {} 51 | 52 | // GetTxIndexerRetainHeightRequest is a request for the retain height. 53 | message GetTxIndexerRetainHeightRequest {} 54 | 55 | // GetTxIndexerRetainHeightResponse returns the retain height for the tx indexer. 56 | message GetTxIndexerRetainHeightResponse { 57 | uint64 height = 1; 58 | } 59 | 60 | // SetBlockIndexerRetainHeightRequest sets the retain height for the block indexer. 61 | message SetBlockIndexerRetainHeightRequest { 62 | uint64 height = 1; 63 | } 64 | 65 | // SetBlockIndexerRetainHeightResponse is empty. 66 | message SetBlockIndexerRetainHeightResponse {} 67 | 68 | // GetBlockIndexerRetainHeightRequest is a request for the retain height. 69 | message GetBlockIndexerRetainHeightRequest {} 70 | 71 | // GetBlockIndexerRetainHeightResponse returns the retain height for the block indexer. 72 | message GetBlockIndexerRetainHeightResponse { 73 | uint64 height = 1; 74 | } 75 | -------------------------------------------------------------------------------- /protos/cometbft/services/pruning/v1/service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package cometbft.services.pruning.v1; 4 | 5 | import "cometbft/services/pruning/v1/pruning.proto"; 6 | 7 | // PruningService provides privileged access to specialized pruning 8 | // functionality on the CometBFT node to help control node storage. 9 | service PruningService { 10 | // SetBlockRetainHeightRequest indicates to the node that it can safely 11 | // prune all block data up to the specified retain height. 12 | // 13 | // The lower of this retain height and that set by the application in its 14 | // Commit response will be used by the node to determine which heights' data 15 | // can be pruned. 16 | rpc SetBlockRetainHeight(SetBlockRetainHeightRequest) returns (SetBlockRetainHeightResponse); 17 | 18 | // GetBlockRetainHeight returns information about the retain height 19 | // parameters used by the node to influence block retention/pruning. 20 | rpc GetBlockRetainHeight(GetBlockRetainHeightRequest) returns (GetBlockRetainHeightResponse); 21 | 22 | // SetBlockResultsRetainHeightRequest indicates to the node that it can 23 | // safely prune all block results data up to the specified height. 24 | // 25 | // The node will always store the block results for the latest height to 26 | // help facilitate crash recovery. 27 | rpc SetBlockResultsRetainHeight(SetBlockResultsRetainHeightRequest) returns (SetBlockResultsRetainHeightResponse); 28 | 29 | // GetBlockResultsRetainHeight returns information about the retain height 30 | // parameters used by the node to influence block results retention/pruning. 31 | rpc GetBlockResultsRetainHeight(GetBlockResultsRetainHeightRequest) returns (GetBlockResultsRetainHeightResponse); 32 | 33 | // SetTxIndexerRetainHeightRequest indicates to the node that it can safely 34 | // prune all tx indices up to the specified retain height. 35 | rpc SetTxIndexerRetainHeight(SetTxIndexerRetainHeightRequest) returns (SetTxIndexerRetainHeightResponse); 36 | 37 | // GetTxIndexerRetainHeight returns information about the retain height 38 | // parameters used by the node to influence TxIndexer pruning 39 | rpc GetTxIndexerRetainHeight(GetTxIndexerRetainHeightRequest) returns (GetTxIndexerRetainHeightResponse); 40 | 41 | // SetBlockIndexerRetainHeightRequest indicates to the node that it can safely 42 | // prune all block indices up to the specified retain height. 43 | rpc SetBlockIndexerRetainHeight(SetBlockIndexerRetainHeightRequest) returns (SetBlockIndexerRetainHeightResponse); 44 | 45 | // GetBlockIndexerRetainHeight returns information about the retain height 46 | // parameters used by the node to influence BlockIndexer pruning 47 | rpc GetBlockIndexerRetainHeight(GetBlockIndexerRetainHeightRequest) returns (GetBlockIndexerRetainHeightResponse); 48 | } 49 | -------------------------------------------------------------------------------- /src/cometbft/services/block_results/v1/block_results_service_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: cometbft/services/block_results/v1/block_results_service.proto 4 | 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from cometbft.services.block_results.v1 import block_results_pb2 as cometbft_dot_services_dot_block__results_dot_v1_dot_block__results__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor.FileDescriptor( 18 | name='cometbft/services/block_results/v1/block_results_service.proto', 19 | package='cometbft.services.block_results.v1', 20 | syntax='proto3', 21 | serialized_options=b'ZCgithub.com/cometbft/cometbft/api/cometbft/services/block_results/v1', 22 | create_key=_descriptor._internal_create_key, 23 | serialized_pb=b'\n>cometbft/services/block_results/v1/block_results_service.proto\x12\"cometbft.services.block_results.v1\x1a\x36\x63ometbft/services/block_results/v1/block_results.proto2\xa2\x01\n\x13\x42lockResultsService\x12\x8a\x01\n\x0fGetBlockResults\x12:.cometbft.services.block_results.v1.GetBlockResultsRequest\x1a;.cometbft.services.block_results.v1.GetBlockResultsResponseBEZCgithub.com/cometbft/cometbft/api/cometbft/services/block_results/v1b\x06proto3' 24 | , 25 | dependencies=[cometbft_dot_services_dot_block__results_dot_v1_dot_block__results__pb2.DESCRIPTOR,]) 26 | 27 | 28 | 29 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 30 | 31 | 32 | DESCRIPTOR._options = None 33 | 34 | _BLOCKRESULTSSERVICE = _descriptor.ServiceDescriptor( 35 | name='BlockResultsService', 36 | full_name='cometbft.services.block_results.v1.BlockResultsService', 37 | file=DESCRIPTOR, 38 | index=0, 39 | serialized_options=None, 40 | create_key=_descriptor._internal_create_key, 41 | serialized_start=159, 42 | serialized_end=321, 43 | methods=[ 44 | _descriptor.MethodDescriptor( 45 | name='GetBlockResults', 46 | full_name='cometbft.services.block_results.v1.BlockResultsService.GetBlockResults', 47 | index=0, 48 | containing_service=None, 49 | input_type=cometbft_dot_services_dot_block__results_dot_v1_dot_block__results__pb2._GETBLOCKRESULTSREQUEST, 50 | output_type=cometbft_dot_services_dot_block__results_dot_v1_dot_block__results__pb2._GETBLOCKRESULTSRESPONSE, 51 | serialized_options=None, 52 | create_key=_descriptor._internal_create_key, 53 | ), 54 | ]) 55 | _sym_db.RegisterServiceDescriptor(_BLOCKRESULTSSERVICE) 56 | 57 | DESCRIPTOR.services_by_name['BlockResultsService'] = _BLOCKRESULTSSERVICE 58 | 59 | # @@protoc_insertion_point(module_scope) 60 | -------------------------------------------------------------------------------- /src/xian/tools/validator_gen.py: -------------------------------------------------------------------------------- 1 | from argparse import ArgumentParser 2 | from nacl.signing import SigningKey 3 | from nacl.encoding import HexEncoder, Base64Encoder 4 | from pathlib import Path 5 | 6 | import hashlib 7 | import json 8 | 9 | """ 10 | Generate priv_validator_key.json file for your validator node 11 | """ 12 | 13 | 14 | class ValidatorGen: 15 | def __init__(self): 16 | parser = ArgumentParser(description='Validator File Generator') 17 | parser.add_argument( 18 | '--validator_privkey', 19 | type=str, 20 | help="Validator's private key", 21 | required=True 22 | ) 23 | parser.add_argument( 24 | '--output-path', 25 | type=Path, 26 | default=None, 27 | help="Path to save generated file" 28 | ) 29 | self.args = parser.parse_args() 30 | 31 | def generate_keys(self): 32 | pk_hex = self.args.validator_privkey 33 | 34 | # Convert hex private key to bytes and generate signing key object 35 | signing_key = SigningKey(pk_hex, encoder=HexEncoder) 36 | 37 | # Obtain the verify key (public key) from the signing key 38 | verify_key = signing_key.verify_key 39 | 40 | # Concatenate private and public key bytes 41 | priv_key_with_pub = signing_key.encode() + verify_key.encode() 42 | 43 | # Encode concatenated private and public keys in Base64 for the output 44 | priv_key_with_pub_b64 = Base64Encoder.encode(priv_key_with_pub).decode('utf-8') 45 | 46 | # Encode public key in Base64 for the output 47 | public_key_b64 = verify_key.encode(encoder=Base64Encoder).decode('utf-8') 48 | 49 | # Hash the public key using SHA-256 and take the first 20 bytes for the address 50 | address_bytes = hashlib.sha256(verify_key.encode()).digest()[:20] 51 | address = address_bytes.hex().upper() 52 | 53 | output = { 54 | "address": address, 55 | "pub_key": { 56 | "type": "tendermint/PubKeyEd25519", 57 | "value": public_key_b64 58 | }, 59 | 'priv_key': { 60 | 'type': 'tendermint/PrivKeyEd25519', 61 | 'value': priv_key_with_pub_b64 62 | } 63 | } 64 | return output 65 | 66 | def main(self): 67 | output_path = Path(self.args.output_path) if self.args.output_path else Path.cwd() 68 | output_file = output_path / Path('priv_validator_key.json') 69 | 70 | if len(self.args.validator_privkey) != 64: 71 | print('Validator private key must be 64 characters') 72 | return 73 | 74 | keys = self.generate_keys() 75 | 76 | with open(output_file, 'w') as f: 77 | f.write(json.dumps(keys, indent=2)) 78 | 79 | 80 | if __name__ == '__main__': 81 | ValidatorGen().main() 82 | -------------------------------------------------------------------------------- /src/cometbft/libs/bits/v1/types_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: cometbft/libs/bits/v1/types.proto 4 | 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor.FileDescriptor( 17 | name='cometbft/libs/bits/v1/types.proto', 18 | package='cometbft.libs.bits.v1', 19 | syntax='proto3', 20 | serialized_options=b'Z6github.com/cometbft/cometbft/api/cometbft/libs/bits/v1', 21 | create_key=_descriptor._internal_create_key, 22 | serialized_pb=b'\n!cometbft/libs/bits/v1/types.proto\x12\x15\x63ometbft.libs.bits.v1\"\'\n\x08\x42itArray\x12\x0c\n\x04\x62its\x18\x01 \x01(\x03\x12\r\n\x05\x65lems\x18\x02 \x03(\x04\x42\x38Z6github.com/cometbft/cometbft/api/cometbft/libs/bits/v1b\x06proto3' 23 | ) 24 | 25 | 26 | 27 | 28 | _BITARRAY = _descriptor.Descriptor( 29 | name='BitArray', 30 | full_name='cometbft.libs.bits.v1.BitArray', 31 | filename=None, 32 | file=DESCRIPTOR, 33 | containing_type=None, 34 | create_key=_descriptor._internal_create_key, 35 | fields=[ 36 | _descriptor.FieldDescriptor( 37 | name='bits', full_name='cometbft.libs.bits.v1.BitArray.bits', index=0, 38 | number=1, type=3, cpp_type=2, label=1, 39 | has_default_value=False, default_value=0, 40 | message_type=None, enum_type=None, containing_type=None, 41 | is_extension=False, extension_scope=None, 42 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 43 | _descriptor.FieldDescriptor( 44 | name='elems', full_name='cometbft.libs.bits.v1.BitArray.elems', index=1, 45 | number=2, type=4, cpp_type=4, label=3, 46 | has_default_value=False, default_value=[], 47 | message_type=None, enum_type=None, containing_type=None, 48 | is_extension=False, extension_scope=None, 49 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 50 | ], 51 | extensions=[ 52 | ], 53 | nested_types=[], 54 | enum_types=[ 55 | ], 56 | serialized_options=None, 57 | is_extendable=False, 58 | syntax='proto3', 59 | extension_ranges=[], 60 | oneofs=[ 61 | ], 62 | serialized_start=60, 63 | serialized_end=99, 64 | ) 65 | 66 | DESCRIPTOR.message_types_by_name['BitArray'] = _BITARRAY 67 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 68 | 69 | BitArray = _reflection.GeneratedProtocolMessageType('BitArray', (_message.Message,), { 70 | 'DESCRIPTOR' : _BITARRAY, 71 | '__module__' : 'cometbft.libs.bits.v1.types_pb2' 72 | # @@protoc_insertion_point(class_scope:cometbft.libs.bits.v1.BitArray) 73 | }) 74 | _sym_db.RegisterMessage(BitArray) 75 | 76 | 77 | DESCRIPTOR._options = None 78 | # @@protoc_insertion_point(module_scope) 79 | -------------------------------------------------------------------------------- /protos/cometbft/types/v1beta1/params.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.types.v1beta1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "google/protobuf/duration.proto"; 8 | 9 | option (gogoproto.equal_all) = true; 10 | 11 | // ConsensusParams contains consensus critical parameters that determine the 12 | // validity of blocks. 13 | message ConsensusParams { 14 | BlockParams block = 1 [(gogoproto.nullable) = false]; 15 | EvidenceParams evidence = 2 [(gogoproto.nullable) = false]; 16 | ValidatorParams validator = 3 [(gogoproto.nullable) = false]; 17 | VersionParams version = 4 [(gogoproto.nullable) = false]; 18 | } 19 | 20 | // BlockParams contains limits on the block size. 21 | message BlockParams { 22 | // Max block size, in bytes. 23 | // Note: must be greater than 0 24 | int64 max_bytes = 1; 25 | // Max gas per block. 26 | // Note: must be greater or equal to -1 27 | int64 max_gas = 2; 28 | // Minimum time increment between consecutive blocks (in milliseconds) If the 29 | // block header timestamp is ahead of the system clock, decrease this value. 30 | // 31 | // Not exposed to the application. 32 | int64 time_iota_ms = 3; 33 | } 34 | 35 | // EvidenceParams determine how we handle evidence of malfeasance. 36 | message EvidenceParams { 37 | // Max age of evidence, in blocks. 38 | // 39 | // The basic formula for calculating this is: MaxAgeDuration / {average block 40 | // time}. 41 | int64 max_age_num_blocks = 1; 42 | 43 | // Max age of evidence, in time. 44 | // 45 | // It should correspond with an app's "unbonding period" or other similar 46 | // mechanism for handling [Nothing-At-Stake 47 | // attacks](https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed). 48 | google.protobuf.Duration max_age_duration = 2 49 | [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; 50 | 51 | // This sets the maximum size of total evidence in bytes that can be committed in a single block. 52 | // and should fall comfortably under the max block bytes. 53 | // Default is 1048576 or 1MB 54 | int64 max_bytes = 3; 55 | } 56 | 57 | // ValidatorParams restrict the public key types validators can use. 58 | // NOTE: uses ABCI pubkey naming, not Amino names. 59 | message ValidatorParams { 60 | option (gogoproto.populate) = true; 61 | option (gogoproto.equal) = true; 62 | 63 | repeated string pub_key_types = 1; 64 | } 65 | 66 | // VersionParams contains the ABCI application version. 67 | message VersionParams { 68 | option (gogoproto.populate) = true; 69 | option (gogoproto.equal) = true; 70 | 71 | // Was named app_version in Tendermint 0.34 72 | uint64 app = 1; 73 | } 74 | 75 | // HashedParams is a subset of ConsensusParams. 76 | // 77 | // It is hashed into the Header.ConsensusHash. 78 | message HashedParams { 79 | int64 block_max_bytes = 1; 80 | int64 block_max_gas = 2; 81 | } 82 | -------------------------------------------------------------------------------- /protos/cometbft/privval/v1beta2/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.privval.v1beta2; 3 | 4 | import "cometbft/crypto/v1/keys.proto"; 5 | import "cometbft/types/v1/types.proto"; 6 | import "gogoproto/gogo.proto"; 7 | 8 | option go_package = "github.com/cometbft/cometbft/api/cometbft/privval/v1beta2"; 9 | 10 | // Errors is a list of error codes that can be returned by the remote signer. 11 | enum Errors { 12 | // Unknown error 13 | ERRORS_UNKNOWN = 0; 14 | // Unexpected response 15 | ERRORS_UNEXPECTED_RESPONSE = 1; 16 | // Connection lost 17 | ERRORS_NO_CONNECTION = 2; 18 | // Connection timeout 19 | ERRORS_CONNECTION_TIMEOUT = 3; 20 | // Read timeout 21 | ERRORS_READ_TIMEOUT = 4; 22 | // Write timeout 23 | ERRORS_WRITE_TIMEOUT = 5; 24 | } 25 | 26 | // remotesignererror is returned when the remote signer fails. 27 | message RemoteSignerError { 28 | int32 code = 1; 29 | string description = 2; 30 | } 31 | 32 | // PubKeyRequest requests the consensus public key from the remote signer. 33 | message PubKeyRequest { 34 | string chain_id = 1; 35 | } 36 | 37 | // PubKeyResponse is a response message containing the public key. 38 | message PubKeyResponse { 39 | cometbft.crypto.v1.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; 40 | RemoteSignerError error = 2; 41 | } 42 | 43 | // SignVoteRequest is a request to sign a vote 44 | message SignVoteRequest { 45 | cometbft.types.v1.Vote vote = 1; 46 | string chain_id = 2; 47 | } 48 | 49 | // SignedVoteResponse is a response containing a signed vote or an error 50 | message SignedVoteResponse { 51 | cometbft.types.v1.Vote vote = 1 [(gogoproto.nullable) = false]; 52 | RemoteSignerError error = 2; 53 | } 54 | 55 | // SignProposalRequest is a request to sign a proposal 56 | message SignProposalRequest { 57 | cometbft.types.v1.Proposal proposal = 1; 58 | string chain_id = 2; 59 | } 60 | 61 | // SignedProposalResponse is response containing a signed proposal or an error 62 | message SignedProposalResponse { 63 | cometbft.types.v1.Proposal proposal = 1 [(gogoproto.nullable) = false]; 64 | RemoteSignerError error = 2; 65 | } 66 | 67 | // PingRequest is a request to confirm that the connection is alive. 68 | message PingRequest {} 69 | 70 | // PingResponse is a response to confirm that the connection is alive. 71 | message PingResponse {} 72 | 73 | // Message is an abstract message to/from the remote signer. 74 | message Message { 75 | // Sum of all possible messages. 76 | oneof sum { 77 | PubKeyRequest pub_key_request = 1; 78 | PubKeyResponse pub_key_response = 2; 79 | SignVoteRequest sign_vote_request = 3; 80 | SignedVoteResponse signed_vote_response = 4; 81 | SignProposalRequest sign_proposal_request = 5; 82 | SignedProposalResponse signed_proposal_response = 6; 83 | PingRequest ping_request = 7; 84 | PingResponse ping_response = 8; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/cometbft/store/v1/types_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: cometbft/store/v1/types.proto 4 | 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor.FileDescriptor( 17 | name='cometbft/store/v1/types.proto', 18 | package='cometbft.store.v1', 19 | syntax='proto3', 20 | serialized_options=b'Z2github.com/cometbft/cometbft/api/cometbft/store/v1', 21 | create_key=_descriptor._internal_create_key, 22 | serialized_pb=b'\n\x1d\x63ometbft/store/v1/types.proto\x12\x11\x63ometbft.store.v1\"/\n\x0f\x42lockStoreState\x12\x0c\n\x04\x62\x61se\x18\x01 \x01(\x03\x12\x0e\n\x06height\x18\x02 \x01(\x03\x42\x34Z2github.com/cometbft/cometbft/api/cometbft/store/v1b\x06proto3' 23 | ) 24 | 25 | 26 | 27 | 28 | _BLOCKSTORESTATE = _descriptor.Descriptor( 29 | name='BlockStoreState', 30 | full_name='cometbft.store.v1.BlockStoreState', 31 | filename=None, 32 | file=DESCRIPTOR, 33 | containing_type=None, 34 | create_key=_descriptor._internal_create_key, 35 | fields=[ 36 | _descriptor.FieldDescriptor( 37 | name='base', full_name='cometbft.store.v1.BlockStoreState.base', index=0, 38 | number=1, type=3, cpp_type=2, label=1, 39 | has_default_value=False, default_value=0, 40 | message_type=None, enum_type=None, containing_type=None, 41 | is_extension=False, extension_scope=None, 42 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 43 | _descriptor.FieldDescriptor( 44 | name='height', full_name='cometbft.store.v1.BlockStoreState.height', index=1, 45 | number=2, type=3, cpp_type=2, label=1, 46 | has_default_value=False, default_value=0, 47 | message_type=None, enum_type=None, containing_type=None, 48 | is_extension=False, extension_scope=None, 49 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 50 | ], 51 | extensions=[ 52 | ], 53 | nested_types=[], 54 | enum_types=[ 55 | ], 56 | serialized_options=None, 57 | is_extendable=False, 58 | syntax='proto3', 59 | extension_ranges=[], 60 | oneofs=[ 61 | ], 62 | serialized_start=52, 63 | serialized_end=99, 64 | ) 65 | 66 | DESCRIPTOR.message_types_by_name['BlockStoreState'] = _BLOCKSTORESTATE 67 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 68 | 69 | BlockStoreState = _reflection.GeneratedProtocolMessageType('BlockStoreState', (_message.Message,), { 70 | 'DESCRIPTOR' : _BLOCKSTORESTATE, 71 | '__module__' : 'cometbft.store.v1.types_pb2' 72 | # @@protoc_insertion_point(class_scope:cometbft.store.v1.BlockStoreState) 73 | }) 74 | _sym_db.RegisterMessage(BlockStoreState) 75 | 76 | 77 | DESCRIPTOR._options = None 78 | # @@protoc_insertion_point(module_scope) 79 | -------------------------------------------------------------------------------- /protos/cometbft/privval/v1beta1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.privval.v1beta1; 3 | 4 | import "cometbft/crypto/v1/keys.proto"; 5 | import "cometbft/types/v1beta1/types.proto"; 6 | import "gogoproto/gogo.proto"; 7 | 8 | option go_package = "github.com/cometbft/cometbft/api/cometbft/privval/v1beta1"; 9 | 10 | // Errors is a list of error codes that can be returned by the remote signer. 11 | enum Errors { 12 | // Unknown error 13 | ERRORS_UNKNOWN = 0; 14 | // Unexpected response 15 | ERRORS_UNEXPECTED_RESPONSE = 1; 16 | // Connection lost 17 | ERRORS_NO_CONNECTION = 2; 18 | // Connection timeout 19 | ERRORS_CONNECTION_TIMEOUT = 3; 20 | // Read timeout 21 | ERRORS_READ_TIMEOUT = 4; 22 | // Write timeout 23 | ERRORS_WRITE_TIMEOUT = 5; 24 | } 25 | 26 | // A service for broadcasting transactions. 27 | message RemoteSignerError { 28 | int32 code = 1; 29 | string description = 2; 30 | } 31 | 32 | // PubKeyRequest requests the consensus public key from the remote signer. 33 | message PubKeyRequest { 34 | string chain_id = 1; 35 | } 36 | 37 | // PubKeyResponse is a response message containing the public key. 38 | message PubKeyResponse { 39 | cometbft.crypto.v1.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; 40 | RemoteSignerError error = 2; 41 | } 42 | 43 | // SignVoteRequest is a request to sign a vote 44 | message SignVoteRequest { 45 | cometbft.types.v1beta1.Vote vote = 1; 46 | string chain_id = 2; 47 | } 48 | 49 | // SignedVoteResponse is a response containing a signed vote or an error 50 | message SignedVoteResponse { 51 | cometbft.types.v1beta1.Vote vote = 1 [(gogoproto.nullable) = false]; 52 | RemoteSignerError error = 2; 53 | } 54 | 55 | // SignProposalRequest is a request to sign a proposal 56 | message SignProposalRequest { 57 | cometbft.types.v1beta1.Proposal proposal = 1; 58 | string chain_id = 2; 59 | } 60 | 61 | // SignedProposalResponse is response containing a signed proposal or an error 62 | message SignedProposalResponse { 63 | cometbft.types.v1beta1.Proposal proposal = 1 [(gogoproto.nullable) = false]; 64 | RemoteSignerError error = 2; 65 | } 66 | 67 | // PingRequest is a request to confirm that the connection is alive. 68 | message PingRequest {} 69 | 70 | // PingResponse is a response to confirm that the connection is alive. 71 | message PingResponse {} 72 | 73 | // Message is an abstract message to/from the remote signer. 74 | message Message { 75 | // Sum of all possible messages. 76 | oneof sum { 77 | PubKeyRequest pub_key_request = 1; 78 | PubKeyResponse pub_key_response = 2; 79 | SignVoteRequest sign_vote_request = 3; 80 | SignedVoteResponse signed_vote_response = 4; 81 | SignProposalRequest sign_proposal_request = 5; 82 | SignedProposalResponse signed_proposal_response = 6; 83 | PingRequest ping_request = 7; 84 | PingResponse ping_response = 8; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/cometbft/services/block/v1/block_service_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: cometbft/services/block/v1/block_service.proto 4 | 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from cometbft.services.block.v1 import block_pb2 as cometbft_dot_services_dot_block_dot_v1_dot_block__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor.FileDescriptor( 18 | name='cometbft/services/block/v1/block_service.proto', 19 | package='cometbft.services.block.v1', 20 | syntax='proto3', 21 | serialized_options=b'Z;github.com/cometbft/cometbft/api/cometbft/services/block/v1', 22 | create_key=_descriptor._internal_create_key, 23 | serialized_pb=b'\n.cometbft/services/block/v1/block_service.proto\x12\x1a\x63ometbft.services.block.v1\x1a&cometbft/services/block/v1/block.proto2\xfc\x01\n\x0c\x42lockService\x12n\n\x0bGetByHeight\x12..cometbft.services.block.v1.GetByHeightRequest\x1a/.cometbft.services.block.v1.GetByHeightResponse\x12|\n\x0fGetLatestHeight\x12\x32.cometbft.services.block.v1.GetLatestHeightRequest\x1a\x33.cometbft.services.block.v1.GetLatestHeightResponse0\x01\x42=Z;github.com/cometbft/cometbft/api/cometbft/services/block/v1b\x06proto3' 24 | , 25 | dependencies=[cometbft_dot_services_dot_block_dot_v1_dot_block__pb2.DESCRIPTOR,]) 26 | 27 | 28 | 29 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 30 | 31 | 32 | DESCRIPTOR._options = None 33 | 34 | _BLOCKSERVICE = _descriptor.ServiceDescriptor( 35 | name='BlockService', 36 | full_name='cometbft.services.block.v1.BlockService', 37 | file=DESCRIPTOR, 38 | index=0, 39 | serialized_options=None, 40 | create_key=_descriptor._internal_create_key, 41 | serialized_start=119, 42 | serialized_end=371, 43 | methods=[ 44 | _descriptor.MethodDescriptor( 45 | name='GetByHeight', 46 | full_name='cometbft.services.block.v1.BlockService.GetByHeight', 47 | index=0, 48 | containing_service=None, 49 | input_type=cometbft_dot_services_dot_block_dot_v1_dot_block__pb2._GETBYHEIGHTREQUEST, 50 | output_type=cometbft_dot_services_dot_block_dot_v1_dot_block__pb2._GETBYHEIGHTRESPONSE, 51 | serialized_options=None, 52 | create_key=_descriptor._internal_create_key, 53 | ), 54 | _descriptor.MethodDescriptor( 55 | name='GetLatestHeight', 56 | full_name='cometbft.services.block.v1.BlockService.GetLatestHeight', 57 | index=1, 58 | containing_service=None, 59 | input_type=cometbft_dot_services_dot_block_dot_v1_dot_block__pb2._GETLATESTHEIGHTREQUEST, 60 | output_type=cometbft_dot_services_dot_block_dot_v1_dot_block__pb2._GETLATESTHEIGHTRESPONSE, 61 | serialized_options=None, 62 | create_key=_descriptor._internal_create_key, 63 | ), 64 | ]) 65 | _sym_db.RegisterServiceDescriptor(_BLOCKSERVICE) 66 | 67 | DESCRIPTOR.services_by_name['BlockService'] = _BLOCKSERVICE 68 | 69 | # @@protoc_insertion_point(module_scope) 70 | -------------------------------------------------------------------------------- /src/xian/nonce.py: -------------------------------------------------------------------------------- 1 | from xian.constants import Constants as c 2 | from xian.exceptions import TransactionException 3 | 4 | from contracting import constants as config 5 | 6 | 7 | class NonceStorage: 8 | def __init__(self, client, root=None): 9 | root = root if root is not None else c.STORAGE_HOME 10 | self.client = client 11 | 12 | def check_nonce(self, tx: dict): 13 | tx_nonce = tx["payload"]["nonce"] 14 | tx_sender = tx["payload"]["sender"] 15 | current_nonce = self.get_nonce(sender=tx_sender) 16 | 17 | if not (current_nonce is None or tx_nonce > current_nonce): 18 | raise TransactionException('Transaction nonce is invalid') 19 | 20 | def set_nonce_by_tx(self, tx): 21 | self.client.raw_driver.set( 22 | c.NONCE_FILENAME + config.INDEX_SEPARATOR + tx['payload']['sender'] + config.DELIMITER, 23 | tx['payload']['nonce'] 24 | ) 25 | 26 | def set_nonce(self, sender, value): 27 | self.client.raw_driver.set( 28 | c.NONCE_FILENAME + config.INDEX_SEPARATOR + sender + config.DELIMITER, 29 | value 30 | ) 31 | 32 | # Move this to transaction.py 33 | def get_nonce(self, sender): 34 | return self.client.raw_driver.get(c.NONCE_FILENAME + config.INDEX_SEPARATOR + sender + config.DELIMITER) 35 | 36 | # Move this to transaction.py 37 | def get_pending_nonce(self, sender): 38 | return self.client.raw_driver.get(c.PENDING_NONCE_FILENAME + config.INDEX_SEPARATOR + sender + config.DELIMITER) 39 | 40 | def safe_set_nonce(self, sender, value): 41 | current_nonce = self.get_nonce(sender=sender) 42 | 43 | if current_nonce is None: 44 | current_nonce = -1 45 | 46 | if value > current_nonce: 47 | self.client.raw_driver.set( 48 | c.NONCE_FILENAME + config.INDEX_SEPARATOR + sender + config.DELIMITER, 49 | value 50 | ) 51 | 52 | def set_pending_nonce(self, sender, value): 53 | self.client.raw_driver.set( 54 | c.PENDING_NONCE_FILENAME + config.INDEX_SEPARATOR + sender + config.DELIMITER, 55 | value 56 | ) 57 | 58 | # Move this to webserver.py 59 | def get_latest_nonce(self, sender): 60 | latest_nonce = self.get_pending_nonce(sender=sender) 61 | 62 | if latest_nonce is None: 63 | latest_nonce = self.get_nonce(sender=sender) 64 | 65 | if latest_nonce is None: 66 | latest_nonce = 0 67 | 68 | return latest_nonce 69 | 70 | def get_next_nonce(self, sender): 71 | current_nonce = self.get_pending_nonce(sender=sender) 72 | 73 | if current_nonce is None: 74 | current_nonce = self.get_nonce(sender=sender) 75 | 76 | if current_nonce is None: 77 | return 0 78 | 79 | return current_nonce + 1 80 | 81 | def flush(self): 82 | self.client.raw_driver.flush_file(c.NONCE_FILENAME) 83 | self.client.raw_driver.flush_file(c.PENDING_NONCE_FILENAME) 84 | 85 | def flush_pending(self): 86 | self.client.raw_driver.flush_file(c.PENDING_NONCE_FILENAME) 87 | -------------------------------------------------------------------------------- /src/abci/utils.py: -------------------------------------------------------------------------------- 1 | """ 2 | Various utils 3 | """ 4 | from io import BytesIO 5 | import logging, colorlog 6 | from google.protobuf.message import Message 7 | 8 | 9 | def get_logger(name: str) -> logging.Logger: 10 | """ 11 | Create a (colored) logger with the given name 12 | """ 13 | logger = logging.getLogger(name) 14 | 15 | if logger.hasHandlers(): 16 | return logger 17 | 18 | formatter = colorlog.ColoredFormatter( 19 | "%(log_color)s%(levelname)-8s%(reset)s %(white)s%(message)s", 20 | datefmt=None, 21 | reset=True, 22 | log_colors={ 23 | "DEBUG": "cyan", 24 | "INFO": "green", 25 | "WARNING": "yellow", 26 | "ERROR": "red", 27 | "CRITICAL": "red,bg_white", 28 | }, 29 | secondary_log_colors={}, 30 | style="%", 31 | ) 32 | 33 | handler = logging.StreamHandler() 34 | handler.setFormatter(formatter) 35 | logger.addHandler(handler) 36 | logger.setLevel(logging.INFO) 37 | 38 | return logger 39 | 40 | 41 | def encode_varint(number: int) -> bytes: 42 | """ 43 | Encode varint (as uint64) into bytes 44 | """ 45 | buf = b"" 46 | while True: 47 | towrite = number & 0x7F 48 | number >>= 7 49 | if number: 50 | buf += bytes((towrite | 0x80,)) 51 | else: 52 | buf += bytes((towrite,)) 53 | break 54 | return buf 55 | 56 | 57 | def decode_varint(stream: BytesIO) -> int: 58 | """ 59 | Decode bytes into int 60 | """ 61 | shift = 0 62 | result = 0 63 | while True: 64 | i = _read_one(stream) 65 | result |= (i & 0x7F) << shift 66 | shift += 7 67 | if not (i & 0x80): 68 | break 69 | return result 70 | 71 | 72 | def _read_one(stream: BytesIO) -> int: 73 | """ 74 | Read 1 byte, converting it into an int 75 | """ 76 | c = stream.read(1) 77 | if c == b"": 78 | raise EOFError("Unexpected EOF while reading bytes") 79 | return ord(c) 80 | 81 | 82 | def write_message(message: Message) -> bytes: 83 | """ 84 | Write length prefixed protobuf message 85 | """ 86 | buffer = BytesIO(b"") 87 | bz = message.SerializeToString() 88 | buffer.write(encode_varint(len(bz))) 89 | buffer.write(bz) 90 | return buffer.getvalue() 91 | 92 | 93 | def read_messages(reader: BytesIO, message_class): 94 | """ 95 | Return an iterator over the messages found in the byte stream. 96 | """ 97 | while True: 98 | start_pos = reader.tell() 99 | try: 100 | length = decode_varint(reader) 101 | except EOFError: 102 | # Not enough data to read the length, reset and wait for more data 103 | reader.seek(start_pos) 104 | break # Exit the loop to wait for more data 105 | 106 | data = reader.read(length) 107 | if len(data) < length: 108 | # Not enough data to read the full message, reset and wait 109 | reader.seek(start_pos) 110 | break # Exit the loop to wait for more data 111 | 112 | # Parse the message 113 | msg = message_class() 114 | msg.ParseFromString(data) 115 | yield msg -------------------------------------------------------------------------------- /protos/cometbft/state/v1beta2/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.state.v1beta2; 3 | 4 | import "cometbft/abci/v1beta2/types.proto"; 5 | import "cometbft/state/v1beta1/types.proto"; 6 | import "cometbft/types/v1beta1/types.proto"; 7 | import "cometbft/types/v1beta1/validator.proto"; 8 | import "cometbft/types/v1beta2/params.proto"; 9 | import "gogoproto/gogo.proto"; 10 | import "google/protobuf/timestamp.proto"; 11 | 12 | option go_package = "github.com/cometbft/cometbft/api/cometbft/state/v1beta2"; 13 | 14 | // ABCIResponses retains the responses 15 | // of the various ABCI calls during block processing. 16 | // It is persisted to disk for each height before calling Commit. 17 | message ABCIResponses { 18 | repeated cometbft.abci.v1beta2.ResponseDeliverTx deliver_txs = 1; 19 | cometbft.abci.v1beta2.ResponseEndBlock end_block = 2; 20 | cometbft.abci.v1beta2.ResponseBeginBlock begin_block = 3; 21 | } 22 | 23 | // ConsensusParamsInfo represents the latest consensus params, or the last height it changed 24 | message ConsensusParamsInfo { 25 | cometbft.types.v1beta2.ConsensusParams consensus_params = 1 [(gogoproto.nullable) = false]; 26 | int64 last_height_changed = 2; 27 | } 28 | 29 | // ABCIResponsesInfo retains the responses of the ABCI calls during block processing. 30 | message ABCIResponsesInfo { 31 | ABCIResponses abci_responses = 1; 32 | int64 height = 2; 33 | } 34 | 35 | // State represents the state of the blockchain. 36 | message State { 37 | v1beta1.Version version = 1 [(gogoproto.nullable) = false]; 38 | 39 | // immutable 40 | string chain_id = 2 [(gogoproto.customname) = "ChainID"]; 41 | int64 initial_height = 14; 42 | 43 | // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist) 44 | int64 last_block_height = 3; 45 | cometbft.types.v1beta1.BlockID last_block_id = 4 [ 46 | (gogoproto.nullable) = false, 47 | (gogoproto.customname) = "LastBlockID" 48 | ]; 49 | google.protobuf.Timestamp last_block_time = 5 [ 50 | (gogoproto.nullable) = false, 51 | (gogoproto.stdtime) = true 52 | ]; 53 | 54 | // LastValidators is used to validate block.LastCommit. 55 | // Validators are persisted to the database separately every time they change, 56 | // so we can query for historical validator sets. 57 | // Note that if s.LastBlockHeight causes a valset change, 58 | // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1 + 1 59 | // Extra +1 due to nextValSet delay. 60 | cometbft.types.v1beta1.ValidatorSet next_validators = 6; 61 | cometbft.types.v1beta1.ValidatorSet validators = 7; 62 | cometbft.types.v1beta1.ValidatorSet last_validators = 8; 63 | int64 last_height_validators_changed = 9; 64 | 65 | // Consensus parameters used for validating blocks. 66 | // Changes returned by EndBlock and updated after Commit. 67 | cometbft.types.v1beta2.ConsensusParams consensus_params = 10 [(gogoproto.nullable) = false]; 68 | int64 last_height_consensus_params_changed = 11; 69 | 70 | // Merkle root of the results from executing prev block 71 | bytes last_results_hash = 12; 72 | 73 | // the latest AppHash we've received from calling abci.Commit() 74 | bytes app_hash = 13; 75 | } 76 | -------------------------------------------------------------------------------- /protos/tendermint/types/params.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package tendermint.types; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "google/protobuf/duration.proto"; 6 | 7 | option (gogoproto.equal_all) = true; 8 | 9 | // ConsensusParams contains consensus critical parameters that determine the 10 | // validity of blocks. 11 | message ConsensusParams { 12 | BlockParams block = 1; 13 | EvidenceParams evidence = 2; 14 | ValidatorParams validator = 3; 15 | VersionParams version = 4; 16 | ABCIParams abci = 5; 17 | } 18 | 19 | // BlockParams contains limits on the block size. 20 | message BlockParams { 21 | // Max block size, in bytes. 22 | // Note: must be greater than 0 23 | int64 max_bytes = 1; 24 | // Max gas per block. 25 | // Note: must be greater or equal to -1 26 | int64 max_gas = 2; 27 | 28 | reserved 3; // was TimeIotaMs see https://github.com/tendermint/tendermint/pull/5792 29 | } 30 | 31 | // EvidenceParams determine how we handle evidence of malfeasance. 32 | message EvidenceParams { 33 | // Max age of evidence, in blocks. 34 | // 35 | // The basic formula for calculating this is: MaxAgeDuration / {average block 36 | // time}. 37 | int64 max_age_num_blocks = 1; 38 | 39 | // Max age of evidence, in time. 40 | // 41 | // It should correspond with an app's "unbonding period" or other similar 42 | // mechanism for handling [Nothing-At-Stake 43 | // attacks](https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed). 44 | google.protobuf.Duration max_age_duration = 2 45 | [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; 46 | 47 | // This sets the maximum size of total evidence in bytes that can be committed in a single block. 48 | // and should fall comfortably under the max block bytes. 49 | // Default is 1048576 or 1MB 50 | int64 max_bytes = 3; 51 | } 52 | 53 | // ValidatorParams restrict the public key types validators can use. 54 | // NOTE: uses ABCI pubkey naming, not Amino names. 55 | message ValidatorParams { 56 | option (gogoproto.populate) = true; 57 | option (gogoproto.equal) = true; 58 | 59 | repeated string pub_key_types = 1; 60 | } 61 | 62 | // VersionParams contains the ABCI application version. 63 | message VersionParams { 64 | option (gogoproto.populate) = true; 65 | option (gogoproto.equal) = true; 66 | 67 | uint64 app = 1; 68 | } 69 | 70 | // HashedParams is a subset of ConsensusParams. 71 | // 72 | // It is hashed into the Header.ConsensusHash. 73 | message HashedParams { 74 | int64 block_max_bytes = 1; 75 | int64 block_max_gas = 2; 76 | } 77 | 78 | // ABCIParams configure functionality specific to the Application Blockchain Interface. 79 | message ABCIParams { 80 | // vote_extensions_enable_height configures the first height during which 81 | // vote extensions will be enabled. During this specified height, and for all 82 | // subsequent heights, precommit messages that do not contain valid extension data 83 | // will be considered invalid. Prior to this height, vote extensions will not 84 | // be used or accepted by validators on the network. 85 | // 86 | // Once enabled, vote extensions will be created by the application in ExtendVote, 87 | // passed to the application for validation in VerifyVoteExtension and given 88 | // to the application to use when proposing a block during PrepareProposal. 89 | int64 vote_extensions_enable_height = 1; 90 | } 91 | -------------------------------------------------------------------------------- /tests/abci_methods/fixtures/.cometbft-fixture/config/config.toml: -------------------------------------------------------------------------------- 1 | version = "0.38.7" 2 | proxy_app = "unix:///tmp/abci.sock" 3 | moniker = "test-node" 4 | db_backend = "goleveldb" 5 | db_dir = "data" 6 | log_level = "info" 7 | log_format = "plain" 8 | genesis_file = "config/genesis.json" 9 | priv_validator_key_file = "config/priv_validator_key.json" 10 | priv_validator_state_file = "data/priv_validator_state.json" 11 | priv_validator_laddr = "" 12 | node_key_file = "config/node_key.json" 13 | abci = "socket" 14 | filter_peers = false 15 | 16 | [rpc] 17 | laddr = "tcp://127.0.0.1:26657" 18 | cors_allowed_origins = [ "*",] 19 | cors_allowed_methods = [ "HEAD", "GET", "POST",] 20 | cors_allowed_headers = [ "Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time",] 21 | grpc_laddr = "" 22 | grpc_max_open_connections = 900 23 | unsafe = false 24 | max_open_connections = 900 25 | max_subscription_clients = 100 26 | max_subscriptions_per_client = 5 27 | experimental_subscription_buffer_size = 200 28 | experimental_websocket_write_buffer_size = 200 29 | experimental_close_on_slow_client = false 30 | timeout_broadcast_tx_commit = "10s" 31 | max_body_bytes = 1000000 32 | max_header_bytes = 1048576 33 | tls_cert_file = "" 34 | tls_key_file = "" 35 | pprof_laddr = "" 36 | 37 | [p2p] 38 | laddr = "tcp://0.0.0.0:26656" 39 | external_address = "" 40 | seeds = "" 41 | persistent_peers = "" 42 | addr_book_file = "config/addrbook.json" 43 | addr_book_strict = true 44 | max_num_inbound_peers = 40 45 | max_num_outbound_peers = 10 46 | unconditional_peer_ids = "" 47 | persistent_peers_max_dial_period = "0s" 48 | flush_throttle_timeout = "100ms" 49 | max_packet_msg_payload_size = 1024 50 | send_rate = 5120000 51 | recv_rate = 5120000 52 | pex = true 53 | seed_mode = false 54 | private_peer_ids = "" 55 | allow_duplicate_ip = false 56 | handshake_timeout = "20s" 57 | dial_timeout = "3s" 58 | 59 | [mempool] 60 | type = "flood" 61 | recheck = true 62 | broadcast = true 63 | wal_dir = "" 64 | size = 5000 65 | max_txs_bytes = 1073741824 66 | cache_size = 10000 67 | keep-invalid-txs-in-cache = false 68 | max_tx_bytes = 1048576 69 | max_batch_bytes = 0 70 | experimental_max_gossip_connections_to_persistent_peers = 0 71 | experimental_max_gossip_connections_to_non_persistent_peers = 0 72 | 73 | [statesync] 74 | enable = false 75 | rpc_servers = "" 76 | trust_height = 0 77 | trust_hash = "" 78 | trust_period = "168h0m0s" 79 | discovery_time = "15s" 80 | temp_dir = "" 81 | chunk_request_timeout = "10s" 82 | chunk_fetchers = "4" 83 | 84 | [blocksync] 85 | version = "v0" 86 | 87 | [consensus] 88 | wal_file = "data/cs.wal/wal" 89 | timeout_propose = "3s" 90 | timeout_propose_delta = "500ms" 91 | timeout_prevote = "1s" 92 | timeout_prevote_delta = "500ms" 93 | timeout_precommit = "1s" 94 | timeout_precommit_delta = "500ms" 95 | timeout_commit = "1s" 96 | double_sign_check_height = 0 97 | skip_timeout_commit = false 98 | create_empty_blocks = false 99 | create_empty_blocks_interval = "0s" 100 | peer_gossip_sleep_duration = "100ms" 101 | peer_query_maj23_sleep_duration = "2s" 102 | 103 | [storage] 104 | discard_abci_responses = false 105 | 106 | [tx_index] 107 | indexer = "kv" 108 | psql-conn = "" 109 | 110 | [instrumentation] 111 | prometheus = true 112 | prometheus_listen_addr = ":26660" 113 | max_open_connections = 3 114 | namespace = "cometbft" 115 | 116 | [xian] 117 | block_service_mode = false 118 | pruning_enabled = false 119 | blocks_to_keep = 100000 120 | -------------------------------------------------------------------------------- /tests/governance/fixtures/.cometbft-fixture/config/config.toml: -------------------------------------------------------------------------------- 1 | version = "0.38.7" 2 | proxy_app = "unix:///tmp/abci.sock" 3 | moniker = "test-node" 4 | db_backend = "goleveldb" 5 | db_dir = "data" 6 | log_level = "info" 7 | log_format = "plain" 8 | genesis_file = "config/genesis.json" 9 | priv_validator_key_file = "config/priv_validator_key.json" 10 | priv_validator_state_file = "data/priv_validator_state.json" 11 | priv_validator_laddr = "" 12 | node_key_file = "config/node_key.json" 13 | abci = "socket" 14 | filter_peers = false 15 | 16 | [rpc] 17 | laddr = "tcp://127.0.0.1:26657" 18 | cors_allowed_origins = [ "*",] 19 | cors_allowed_methods = [ "HEAD", "GET", "POST",] 20 | cors_allowed_headers = [ "Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time",] 21 | grpc_laddr = "" 22 | grpc_max_open_connections = 900 23 | unsafe = false 24 | max_open_connections = 900 25 | max_subscription_clients = 100 26 | max_subscriptions_per_client = 5 27 | experimental_subscription_buffer_size = 200 28 | experimental_websocket_write_buffer_size = 200 29 | experimental_close_on_slow_client = false 30 | timeout_broadcast_tx_commit = "10s" 31 | max_body_bytes = 1000000 32 | max_header_bytes = 1048576 33 | tls_cert_file = "" 34 | tls_key_file = "" 35 | pprof_laddr = "" 36 | 37 | [p2p] 38 | laddr = "tcp://0.0.0.0:26656" 39 | external_address = "" 40 | seeds = "" 41 | persistent_peers = "" 42 | addr_book_file = "config/addrbook.json" 43 | addr_book_strict = true 44 | max_num_inbound_peers = 40 45 | max_num_outbound_peers = 10 46 | unconditional_peer_ids = "" 47 | persistent_peers_max_dial_period = "0s" 48 | flush_throttle_timeout = "100ms" 49 | max_packet_msg_payload_size = 1024 50 | send_rate = 5120000 51 | recv_rate = 5120000 52 | pex = true 53 | seed_mode = false 54 | private_peer_ids = "" 55 | allow_duplicate_ip = false 56 | handshake_timeout = "20s" 57 | dial_timeout = "3s" 58 | 59 | [mempool] 60 | type = "flood" 61 | recheck = true 62 | broadcast = true 63 | wal_dir = "" 64 | size = 5000 65 | max_txs_bytes = 1073741824 66 | cache_size = 10000 67 | keep-invalid-txs-in-cache = false 68 | max_tx_bytes = 1048576 69 | max_batch_bytes = 0 70 | experimental_max_gossip_connections_to_persistent_peers = 0 71 | experimental_max_gossip_connections_to_non_persistent_peers = 0 72 | 73 | [statesync] 74 | enable = false 75 | rpc_servers = "" 76 | trust_height = 0 77 | trust_hash = "" 78 | trust_period = "168h0m0s" 79 | discovery_time = "15s" 80 | temp_dir = "" 81 | chunk_request_timeout = "10s" 82 | chunk_fetchers = "4" 83 | 84 | [blocksync] 85 | version = "v0" 86 | 87 | [consensus] 88 | wal_file = "data/cs.wal/wal" 89 | timeout_propose = "3s" 90 | timeout_propose_delta = "500ms" 91 | timeout_prevote = "1s" 92 | timeout_prevote_delta = "500ms" 93 | timeout_precommit = "1s" 94 | timeout_precommit_delta = "500ms" 95 | timeout_commit = "1s" 96 | double_sign_check_height = 0 97 | skip_timeout_commit = false 98 | create_empty_blocks = false 99 | create_empty_blocks_interval = "0s" 100 | peer_gossip_sleep_duration = "100ms" 101 | peer_query_maj23_sleep_duration = "2s" 102 | 103 | [storage] 104 | discard_abci_responses = false 105 | 106 | [tx_index] 107 | indexer = "kv" 108 | psql-conn = "" 109 | 110 | [instrumentation] 111 | prometheus = true 112 | prometheus_listen_addr = ":26660" 113 | max_open_connections = 3 114 | namespace = "cometbft" 115 | 116 | [xian] 117 | block_service_mode = false 118 | pruning_enabled = false 119 | blocks_to_keep = 100000 120 | -------------------------------------------------------------------------------- /tests/integration/fixtures/.cometbft-fixture/config/config.toml: -------------------------------------------------------------------------------- 1 | version = "0.38.7" 2 | proxy_app = "unix:///tmp/abci.sock" 3 | moniker = "test-node" 4 | db_backend = "goleveldb" 5 | db_dir = "data" 6 | log_level = "info" 7 | log_format = "plain" 8 | genesis_file = "config/genesis.json" 9 | priv_validator_key_file = "config/priv_validator_key.json" 10 | priv_validator_state_file = "data/priv_validator_state.json" 11 | priv_validator_laddr = "" 12 | node_key_file = "config/node_key.json" 13 | abci = "socket" 14 | filter_peers = false 15 | 16 | [rpc] 17 | laddr = "tcp://127.0.0.1:26657" 18 | cors_allowed_origins = [ "*",] 19 | cors_allowed_methods = [ "HEAD", "GET", "POST",] 20 | cors_allowed_headers = [ "Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time",] 21 | grpc_laddr = "" 22 | grpc_max_open_connections = 900 23 | unsafe = false 24 | max_open_connections = 900 25 | max_subscription_clients = 100 26 | max_subscriptions_per_client = 5 27 | experimental_subscription_buffer_size = 200 28 | experimental_websocket_write_buffer_size = 200 29 | experimental_close_on_slow_client = false 30 | timeout_broadcast_tx_commit = "10s" 31 | max_body_bytes = 1000000 32 | max_header_bytes = 1048576 33 | tls_cert_file = "" 34 | tls_key_file = "" 35 | pprof_laddr = "" 36 | 37 | [p2p] 38 | laddr = "tcp://0.0.0.0:26656" 39 | external_address = "" 40 | seeds = "" 41 | persistent_peers = "" 42 | addr_book_file = "config/addrbook.json" 43 | addr_book_strict = true 44 | max_num_inbound_peers = 40 45 | max_num_outbound_peers = 10 46 | unconditional_peer_ids = "" 47 | persistent_peers_max_dial_period = "0s" 48 | flush_throttle_timeout = "100ms" 49 | max_packet_msg_payload_size = 1024 50 | send_rate = 5120000 51 | recv_rate = 5120000 52 | pex = true 53 | seed_mode = false 54 | private_peer_ids = "" 55 | allow_duplicate_ip = false 56 | handshake_timeout = "20s" 57 | dial_timeout = "3s" 58 | 59 | [mempool] 60 | type = "flood" 61 | recheck = true 62 | broadcast = true 63 | wal_dir = "" 64 | size = 5000 65 | max_txs_bytes = 1073741824 66 | cache_size = 10000 67 | keep-invalid-txs-in-cache = false 68 | max_tx_bytes = 1048576 69 | max_batch_bytes = 0 70 | experimental_max_gossip_connections_to_persistent_peers = 0 71 | experimental_max_gossip_connections_to_non_persistent_peers = 0 72 | 73 | [statesync] 74 | enable = false 75 | rpc_servers = "" 76 | trust_height = 0 77 | trust_hash = "" 78 | trust_period = "168h0m0s" 79 | discovery_time = "15s" 80 | temp_dir = "" 81 | chunk_request_timeout = "10s" 82 | chunk_fetchers = "4" 83 | 84 | [blocksync] 85 | version = "v0" 86 | 87 | [consensus] 88 | wal_file = "data/cs.wal/wal" 89 | timeout_propose = "3s" 90 | timeout_propose_delta = "500ms" 91 | timeout_prevote = "1s" 92 | timeout_prevote_delta = "500ms" 93 | timeout_precommit = "1s" 94 | timeout_precommit_delta = "500ms" 95 | timeout_commit = "1s" 96 | double_sign_check_height = 0 97 | skip_timeout_commit = false 98 | create_empty_blocks = false 99 | create_empty_blocks_interval = "0s" 100 | peer_gossip_sleep_duration = "100ms" 101 | peer_query_maj23_sleep_duration = "2s" 102 | 103 | [storage] 104 | discard_abci_responses = false 105 | 106 | [tx_index] 107 | indexer = "kv" 108 | psql-conn = "" 109 | 110 | [instrumentation] 111 | prometheus = true 112 | prometheus_listen_addr = ":26660" 113 | max_open_connections = 3 114 | namespace = "cometbft" 115 | 116 | [xian] 117 | block_service_mode = false 118 | pruning_enabled = false 119 | blocks_to_keep = 100000 120 | -------------------------------------------------------------------------------- /src/cometbft/types/v1/events_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: cometbft/types/v1/events.proto 4 | 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor.FileDescriptor( 17 | name='cometbft/types/v1/events.proto', 18 | package='cometbft.types.v1', 19 | syntax='proto3', 20 | serialized_options=b'Z2github.com/cometbft/cometbft/api/cometbft/types/v1', 21 | create_key=_descriptor._internal_create_key, 22 | serialized_pb=b'\n\x1e\x63ometbft/types/v1/events.proto\x12\x11\x63ometbft.types.v1\"B\n\x13\x45ventDataRoundState\x12\x0e\n\x06height\x18\x01 \x01(\x03\x12\r\n\x05round\x18\x02 \x01(\x05\x12\x0c\n\x04step\x18\x03 \x01(\tB4Z2github.com/cometbft/cometbft/api/cometbft/types/v1b\x06proto3' 23 | ) 24 | 25 | 26 | 27 | 28 | _EVENTDATAROUNDSTATE = _descriptor.Descriptor( 29 | name='EventDataRoundState', 30 | full_name='cometbft.types.v1.EventDataRoundState', 31 | filename=None, 32 | file=DESCRIPTOR, 33 | containing_type=None, 34 | create_key=_descriptor._internal_create_key, 35 | fields=[ 36 | _descriptor.FieldDescriptor( 37 | name='height', full_name='cometbft.types.v1.EventDataRoundState.height', index=0, 38 | number=1, type=3, cpp_type=2, label=1, 39 | has_default_value=False, default_value=0, 40 | message_type=None, enum_type=None, containing_type=None, 41 | is_extension=False, extension_scope=None, 42 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 43 | _descriptor.FieldDescriptor( 44 | name='round', full_name='cometbft.types.v1.EventDataRoundState.round', index=1, 45 | number=2, type=5, cpp_type=1, label=1, 46 | has_default_value=False, default_value=0, 47 | message_type=None, enum_type=None, containing_type=None, 48 | is_extension=False, extension_scope=None, 49 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 50 | _descriptor.FieldDescriptor( 51 | name='step', full_name='cometbft.types.v1.EventDataRoundState.step', index=2, 52 | number=3, type=9, cpp_type=9, label=1, 53 | has_default_value=False, default_value=b"".decode('utf-8'), 54 | message_type=None, enum_type=None, containing_type=None, 55 | is_extension=False, extension_scope=None, 56 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 57 | ], 58 | extensions=[ 59 | ], 60 | nested_types=[], 61 | enum_types=[ 62 | ], 63 | serialized_options=None, 64 | is_extendable=False, 65 | syntax='proto3', 66 | extension_ranges=[], 67 | oneofs=[ 68 | ], 69 | serialized_start=53, 70 | serialized_end=119, 71 | ) 72 | 73 | DESCRIPTOR.message_types_by_name['EventDataRoundState'] = _EVENTDATAROUNDSTATE 74 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 75 | 76 | EventDataRoundState = _reflection.GeneratedProtocolMessageType('EventDataRoundState', (_message.Message,), { 77 | 'DESCRIPTOR' : _EVENTDATAROUNDSTATE, 78 | '__module__' : 'cometbft.types.v1.events_pb2' 79 | # @@protoc_insertion_point(class_scope:cometbft.types.v1.EventDataRoundState) 80 | }) 81 | _sym_db.RegisterMessage(EventDataRoundState) 82 | 83 | 84 | DESCRIPTOR._options = None 85 | # @@protoc_insertion_point(module_scope) 86 | -------------------------------------------------------------------------------- /src/cometbft/types/v1beta1/events_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: cometbft/types/v1beta1/events.proto 4 | 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor.FileDescriptor( 17 | name='cometbft/types/v1beta1/events.proto', 18 | package='cometbft.types.v1beta1', 19 | syntax='proto3', 20 | serialized_options=b'Z7github.com/cometbft/cometbft/api/cometbft/types/v1beta1', 21 | create_key=_descriptor._internal_create_key, 22 | serialized_pb=b'\n#cometbft/types/v1beta1/events.proto\x12\x16\x63ometbft.types.v1beta1\"B\n\x13\x45ventDataRoundState\x12\x0e\n\x06height\x18\x01 \x01(\x03\x12\r\n\x05round\x18\x02 \x01(\x05\x12\x0c\n\x04step\x18\x03 \x01(\tB9Z7github.com/cometbft/cometbft/api/cometbft/types/v1beta1b\x06proto3' 23 | ) 24 | 25 | 26 | 27 | 28 | _EVENTDATAROUNDSTATE = _descriptor.Descriptor( 29 | name='EventDataRoundState', 30 | full_name='cometbft.types.v1beta1.EventDataRoundState', 31 | filename=None, 32 | file=DESCRIPTOR, 33 | containing_type=None, 34 | create_key=_descriptor._internal_create_key, 35 | fields=[ 36 | _descriptor.FieldDescriptor( 37 | name='height', full_name='cometbft.types.v1beta1.EventDataRoundState.height', index=0, 38 | number=1, type=3, cpp_type=2, label=1, 39 | has_default_value=False, default_value=0, 40 | message_type=None, enum_type=None, containing_type=None, 41 | is_extension=False, extension_scope=None, 42 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 43 | _descriptor.FieldDescriptor( 44 | name='round', full_name='cometbft.types.v1beta1.EventDataRoundState.round', index=1, 45 | number=2, type=5, cpp_type=1, label=1, 46 | has_default_value=False, default_value=0, 47 | message_type=None, enum_type=None, containing_type=None, 48 | is_extension=False, extension_scope=None, 49 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 50 | _descriptor.FieldDescriptor( 51 | name='step', full_name='cometbft.types.v1beta1.EventDataRoundState.step', index=2, 52 | number=3, type=9, cpp_type=9, label=1, 53 | has_default_value=False, default_value=b"".decode('utf-8'), 54 | message_type=None, enum_type=None, containing_type=None, 55 | is_extension=False, extension_scope=None, 56 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 57 | ], 58 | extensions=[ 59 | ], 60 | nested_types=[], 61 | enum_types=[ 62 | ], 63 | serialized_options=None, 64 | is_extendable=False, 65 | syntax='proto3', 66 | extension_ranges=[], 67 | oneofs=[ 68 | ], 69 | serialized_start=63, 70 | serialized_end=129, 71 | ) 72 | 73 | DESCRIPTOR.message_types_by_name['EventDataRoundState'] = _EVENTDATAROUNDSTATE 74 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 75 | 76 | EventDataRoundState = _reflection.GeneratedProtocolMessageType('EventDataRoundState', (_message.Message,), { 77 | 'DESCRIPTOR' : _EVENTDATAROUNDSTATE, 78 | '__module__' : 'cometbft.types.v1beta1.events_pb2' 79 | # @@protoc_insertion_point(class_scope:cometbft.types.v1beta1.EventDataRoundState) 80 | }) 81 | _sym_db.RegisterMessage(EventDataRoundState) 82 | 83 | 84 | DESCRIPTOR._options = None 85 | # @@protoc_insertion_point(module_scope) 86 | -------------------------------------------------------------------------------- /src/tendermint/crypto/keys_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: tendermint/crypto/keys.proto 4 | 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from gogoproto import gogo_pb2 as gogoproto_dot_gogo__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor.FileDescriptor( 18 | name='tendermint/crypto/keys.proto', 19 | package='tendermint.crypto', 20 | syntax='proto3', 21 | serialized_options=None, 22 | create_key=_descriptor._internal_create_key, 23 | serialized_pb=b'\n\x1ctendermint/crypto/keys.proto\x12\x11tendermint.crypto\x1a\x14gogoproto/gogo.proto\"D\n\tPublicKey\x12\x11\n\x07\x65\x64\x32\x35\x35\x31\x39\x18\x01 \x01(\x0cH\x00\x12\x13\n\tsecp256k1\x18\x02 \x01(\x0cH\x00:\x08\xe8\xa1\x1f\x01\xe8\xa0\x1f\x01\x42\x05\n\x03sumb\x06proto3' 24 | , 25 | dependencies=[gogoproto_dot_gogo__pb2.DESCRIPTOR,]) 26 | 27 | 28 | 29 | 30 | _PUBLICKEY = _descriptor.Descriptor( 31 | name='PublicKey', 32 | full_name='tendermint.crypto.PublicKey', 33 | filename=None, 34 | file=DESCRIPTOR, 35 | containing_type=None, 36 | create_key=_descriptor._internal_create_key, 37 | fields=[ 38 | _descriptor.FieldDescriptor( 39 | name='ed25519', full_name='tendermint.crypto.PublicKey.ed25519', index=0, 40 | number=1, type=12, cpp_type=9, label=1, 41 | has_default_value=False, default_value=b"", 42 | message_type=None, enum_type=None, containing_type=None, 43 | is_extension=False, extension_scope=None, 44 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 45 | _descriptor.FieldDescriptor( 46 | name='secp256k1', full_name='tendermint.crypto.PublicKey.secp256k1', index=1, 47 | number=2, type=12, cpp_type=9, label=1, 48 | has_default_value=False, default_value=b"", 49 | message_type=None, enum_type=None, containing_type=None, 50 | is_extension=False, extension_scope=None, 51 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 52 | ], 53 | extensions=[ 54 | ], 55 | nested_types=[], 56 | enum_types=[ 57 | ], 58 | serialized_options=b'\350\241\037\001\350\240\037\001', 59 | is_extendable=False, 60 | syntax='proto3', 61 | extension_ranges=[], 62 | oneofs=[ 63 | _descriptor.OneofDescriptor( 64 | name='sum', full_name='tendermint.crypto.PublicKey.sum', 65 | index=0, containing_type=None, 66 | create_key=_descriptor._internal_create_key, 67 | fields=[]), 68 | ], 69 | serialized_start=73, 70 | serialized_end=141, 71 | ) 72 | 73 | _PUBLICKEY.oneofs_by_name['sum'].fields.append( 74 | _PUBLICKEY.fields_by_name['ed25519']) 75 | _PUBLICKEY.fields_by_name['ed25519'].containing_oneof = _PUBLICKEY.oneofs_by_name['sum'] 76 | _PUBLICKEY.oneofs_by_name['sum'].fields.append( 77 | _PUBLICKEY.fields_by_name['secp256k1']) 78 | _PUBLICKEY.fields_by_name['secp256k1'].containing_oneof = _PUBLICKEY.oneofs_by_name['sum'] 79 | DESCRIPTOR.message_types_by_name['PublicKey'] = _PUBLICKEY 80 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 81 | 82 | PublicKey = _reflection.GeneratedProtocolMessageType('PublicKey', (_message.Message,), { 83 | 'DESCRIPTOR' : _PUBLICKEY, 84 | '__module__' : 'tendermint.crypto.keys_pb2' 85 | # @@protoc_insertion_point(class_scope:tendermint.crypto.PublicKey) 86 | }) 87 | _sym_db.RegisterMessage(PublicKey) 88 | 89 | 90 | _PUBLICKEY._options = None 91 | # @@protoc_insertion_point(module_scope) 92 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Python template 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | cover/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | .pybuilder/ 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | # For a library or package, you might want to ignore these files since the code is 88 | # intended to run in multiple environments; otherwise, check them in: 89 | # .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # poetry 99 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 100 | # This is especially recommended for binary packages to ensure reproducibility, and is more 101 | # commonly ignored for libraries. 102 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 103 | #poetry.lock 104 | 105 | # pdm 106 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 107 | #pdm.lock 108 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 109 | # in version control. 110 | # https://pdm.fming.dev/#use-with-ide 111 | .pdm.toml 112 | 113 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 114 | __pypackages__/ 115 | 116 | # Celery stuff 117 | celerybeat-schedule 118 | celerybeat.pid 119 | 120 | # SageMath parsed files 121 | *.sage.py 122 | 123 | # Environments 124 | .env 125 | .venv 126 | env/ 127 | venv/ 128 | ENV/ 129 | env.bak/ 130 | venv.bak/ 131 | 132 | # Spyder project settings 133 | .spyderproject 134 | .spyproject 135 | 136 | # Rope project settings 137 | .ropeproject 138 | 139 | # mkdocs documentation 140 | /site 141 | 142 | # mypy 143 | .mypy_cache/ 144 | .dmypy.json 145 | dmypy.json 146 | 147 | # Pyre type checker 148 | .pyre/ 149 | 150 | # pytype static type analyzer 151 | .pytype/ 152 | 153 | # Cython debug symbols 154 | cython_debug/ 155 | 156 | .idea/ 157 | 158 | .DS_Store 159 | .vscode/ 160 | build 161 | dist 162 | *.pyc 163 | .test_pyabci 164 | .pytest_cache 165 | 166 | tendermint 167 | contracting 168 | lamden 169 | /xian_venv 170 | cometbft 171 | logs 172 | -------------------------------------------------------------------------------- /src/xian/tools/export_state.py: -------------------------------------------------------------------------------- 1 | import json 2 | import hashlib 3 | 4 | from pathlib import Path 5 | from argparse import ArgumentParser 6 | from contracting.storage.driver import Driver 7 | from contracting.storage.encoder import encode 8 | from xian_py.wallet import Wallet 9 | from xian.utils.block import is_compiled_key, get_latest_block_height, get_latest_block_hash 10 | 11 | 12 | def hash_genesis_block_state_changes(state_changes: list) -> str: 13 | # Convert all non-serializable objects in state_changes to a serializable format 14 | def serialize(obj): 15 | if isinstance(obj, bytes): 16 | return obj.hex() # Convert bytes to hex string 17 | # return str(obj) # Fallback: convert other types to string 18 | 19 | h = hashlib.sha3_256() 20 | 21 | # Use the default argument of json.dumps to specify the custom serializer 22 | h.update(json.dumps(state_changes, default=serialize).encode('utf-8')) 23 | return h.hexdigest() 24 | 25 | 26 | def should_ignore(key, ignore_keys): 27 | for ik in ignore_keys: 28 | if key.startswith(ik): 29 | return True 30 | 31 | return False 32 | 33 | 34 | def fetch_filebased_state(): 35 | print('Migrating existing file-based state...') 36 | driver = Driver() 37 | contract_state = driver.get_all_contract_state() 38 | run_state = driver.get_run_state() 39 | return contract_state, run_state 40 | 41 | 42 | def build_genesis_block(founder_sk: str, contract_state: dict, run_state: dict): 43 | hash = get_latest_block_hash() 44 | print('hash', hash) 45 | block_number = get_latest_block_height() 46 | 47 | genesis_block = { 48 | 'hash': hash.hex(), 49 | 'number': block_number, 50 | 'origin': { 51 | 'signature': '', 52 | 'sender': '' 53 | }, 54 | 'genesis': [], 55 | } 56 | 57 | print("Populating run state...") 58 | 59 | nonces = [{'key': k[4:], 'value': v} for k, v in run_state.items() if k.startswith("__n.")] 60 | 61 | print('Populating genesis block...') 62 | for key, value in contract_state.items(): 63 | if not is_compiled_key(key) and value is not None: 64 | genesis_block['genesis'].append({ 65 | 'key': key, 66 | 'value': value 67 | }) 68 | 69 | print('Sorting state changes...') 70 | genesis_block['genesis'] = sorted(genesis_block['genesis'], key=lambda d: d['key']) 71 | genesis_block['nonces'] = nonces 72 | 73 | if founder_sk: 74 | print('Signing state changes...') 75 | founders_wallet = Wallet(seed=bytes.fromhex(founder_sk)) 76 | genesis_block['origin']['sender'] = founders_wallet.public_key 77 | genesis_block['origin']['signature'] = founders_wallet.sign_msg(hash_genesis_block_state_changes(genesis_block['genesis'])) 78 | return genesis_block 79 | 80 | 81 | def main( 82 | founder_sk: str, 83 | output_path: Path, 84 | ): 85 | output_path = output_path.joinpath('exported_state.json') 86 | 87 | contract_state, run_state = fetch_filebased_state() 88 | 89 | genesis_block = build_genesis_block(founder_sk, contract_state, run_state) 90 | 91 | print(f'Saving genesis block to "{output_path}"...') 92 | with open(output_path, 'w') as f: 93 | f.write(encode(genesis_block)) 94 | 95 | 96 | if __name__ == '__main__': 97 | parser = ArgumentParser() 98 | parser.add_argument('-k', '--key', type=str, required=False) 99 | parser.add_argument('--output-path', type=str, required=False) 100 | args = parser.parse_args() 101 | output_path = Path(args.output_path) if args.output_path is not None else Path.cwd() 102 | main(args.key, output_path) 103 | -------------------------------------------------------------------------------- /protos/cometbft/state/v1beta1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.state.v1beta1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/state/v1beta1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cometbft/abci/v1beta1/types.proto"; 8 | import "cometbft/types/v1beta1/types.proto"; 9 | import "cometbft/types/v1beta1/validator.proto"; 10 | import "cometbft/types/v1beta1/params.proto"; 11 | import "cometbft/version/v1/types.proto"; 12 | import "google/protobuf/timestamp.proto"; 13 | 14 | // ABCIResponses retains the responses 15 | // of the various ABCI calls during block processing. 16 | // It is persisted to disk for each height before calling Commit. 17 | message ABCIResponses { 18 | repeated cometbft.abci.v1beta1.ResponseDeliverTx deliver_txs = 1; 19 | cometbft.abci.v1beta1.ResponseEndBlock end_block = 2; 20 | cometbft.abci.v1beta1.ResponseBeginBlock begin_block = 3; 21 | } 22 | 23 | // ValidatorsInfo represents the latest validator set, or the last height it changed 24 | message ValidatorsInfo { 25 | cometbft.types.v1beta1.ValidatorSet validator_set = 1; 26 | int64 last_height_changed = 2; 27 | } 28 | 29 | // ConsensusParamsInfo represents the latest consensus params, or the last height it changed 30 | message ConsensusParamsInfo { 31 | cometbft.types.v1beta1.ConsensusParams consensus_params = 1 [(gogoproto.nullable) = false]; 32 | int64 last_height_changed = 2; 33 | } 34 | 35 | // ABCIResponsesInfo retains the responses of the ABCI calls during block processing. 36 | message ABCIResponsesInfo { 37 | ABCIResponses abci_responses = 1; 38 | int64 height = 2; 39 | } 40 | 41 | // Version is a message for storing versioning information. 42 | message Version { 43 | cometbft.version.v1.Consensus consensus = 1 [(gogoproto.nullable) = false]; 44 | string software = 2; 45 | } 46 | 47 | // State represents the state of the blockchain. 48 | message State { 49 | Version version = 1 [(gogoproto.nullable) = false]; 50 | 51 | // immutable 52 | string chain_id = 2 [(gogoproto.customname) = "ChainID"]; 53 | int64 initial_height = 14; 54 | 55 | // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist) 56 | int64 last_block_height = 3; 57 | cometbft.types.v1beta1.BlockID last_block_id = 4 58 | [(gogoproto.nullable) = false, (gogoproto.customname) = "LastBlockID"]; 59 | google.protobuf.Timestamp last_block_time = 5 60 | [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; 61 | 62 | // LastValidators is used to validate block.LastCommit. 63 | // Validators are persisted to the database separately every time they change, 64 | // so we can query for historical validator sets. 65 | // Note that if s.LastBlockHeight causes a valset change, 66 | // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1 + 1 67 | // Extra +1 due to nextValSet delay. 68 | cometbft.types.v1beta1.ValidatorSet next_validators = 6; 69 | cometbft.types.v1beta1.ValidatorSet validators = 7; 70 | cometbft.types.v1beta1.ValidatorSet last_validators = 8; 71 | int64 last_height_validators_changed = 9; 72 | 73 | // Consensus parameters used for validating blocks. 74 | // Changes returned by EndBlock and updated after Commit. 75 | cometbft.types.v1beta1.ConsensusParams consensus_params = 10 [(gogoproto.nullable) = false]; 76 | int64 last_height_consensus_params_changed = 11; 77 | 78 | // Merkle root of the results from executing prev block 79 | bytes last_results_hash = 12; 80 | 81 | // the latest AppHash we've received from calling abci.Commit() 82 | bytes app_hash = 13; 83 | } 84 | -------------------------------------------------------------------------------- /src/cometbft/crypto/v1/keys_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: cometbft/crypto/v1/keys.proto 4 | 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | from gogoproto import gogo_pb2 as gogoproto_dot_gogo__pb2 15 | 16 | 17 | DESCRIPTOR = _descriptor.FileDescriptor( 18 | name='cometbft/crypto/v1/keys.proto', 19 | package='cometbft.crypto.v1', 20 | syntax='proto3', 21 | serialized_options=b'Z3github.com/cometbft/cometbft/api/cometbft/crypto/v1', 22 | create_key=_descriptor._internal_create_key, 23 | serialized_pb=b'\n\x1d\x63ometbft/crypto/v1/keys.proto\x12\x12\x63ometbft.crypto.v1\x1a\x14gogoproto/gogo.proto\"D\n\tPublicKey\x12\x11\n\x07\x65\x64\x32\x35\x35\x31\x39\x18\x01 \x01(\x0cH\x00\x12\x13\n\tsecp256k1\x18\x02 \x01(\x0cH\x00:\x08\xe8\xa1\x1f\x01\xe8\xa0\x1f\x01\x42\x05\n\x03sumB5Z3github.com/cometbft/cometbft/api/cometbft/crypto/v1b\x06proto3' 24 | , 25 | dependencies=[gogoproto_dot_gogo__pb2.DESCRIPTOR,]) 26 | 27 | 28 | 29 | 30 | _PUBLICKEY = _descriptor.Descriptor( 31 | name='PublicKey', 32 | full_name='cometbft.crypto.v1.PublicKey', 33 | filename=None, 34 | file=DESCRIPTOR, 35 | containing_type=None, 36 | create_key=_descriptor._internal_create_key, 37 | fields=[ 38 | _descriptor.FieldDescriptor( 39 | name='ed25519', full_name='cometbft.crypto.v1.PublicKey.ed25519', index=0, 40 | number=1, type=12, cpp_type=9, label=1, 41 | has_default_value=False, default_value=b"", 42 | message_type=None, enum_type=None, containing_type=None, 43 | is_extension=False, extension_scope=None, 44 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 45 | _descriptor.FieldDescriptor( 46 | name='secp256k1', full_name='cometbft.crypto.v1.PublicKey.secp256k1', index=1, 47 | number=2, type=12, cpp_type=9, label=1, 48 | has_default_value=False, default_value=b"", 49 | message_type=None, enum_type=None, containing_type=None, 50 | is_extension=False, extension_scope=None, 51 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 52 | ], 53 | extensions=[ 54 | ], 55 | nested_types=[], 56 | enum_types=[ 57 | ], 58 | serialized_options=b'\350\241\037\001\350\240\037\001', 59 | is_extendable=False, 60 | syntax='proto3', 61 | extension_ranges=[], 62 | oneofs=[ 63 | _descriptor.OneofDescriptor( 64 | name='sum', full_name='cometbft.crypto.v1.PublicKey.sum', 65 | index=0, containing_type=None, 66 | create_key=_descriptor._internal_create_key, 67 | fields=[]), 68 | ], 69 | serialized_start=75, 70 | serialized_end=143, 71 | ) 72 | 73 | _PUBLICKEY.oneofs_by_name['sum'].fields.append( 74 | _PUBLICKEY.fields_by_name['ed25519']) 75 | _PUBLICKEY.fields_by_name['ed25519'].containing_oneof = _PUBLICKEY.oneofs_by_name['sum'] 76 | _PUBLICKEY.oneofs_by_name['sum'].fields.append( 77 | _PUBLICKEY.fields_by_name['secp256k1']) 78 | _PUBLICKEY.fields_by_name['secp256k1'].containing_oneof = _PUBLICKEY.oneofs_by_name['sum'] 79 | DESCRIPTOR.message_types_by_name['PublicKey'] = _PUBLICKEY 80 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 81 | 82 | PublicKey = _reflection.GeneratedProtocolMessageType('PublicKey', (_message.Message,), { 83 | 'DESCRIPTOR' : _PUBLICKEY, 84 | '__module__' : 'cometbft.crypto.v1.keys_pb2' 85 | # @@protoc_insertion_point(class_scope:cometbft.crypto.v1.PublicKey) 86 | }) 87 | _sym_db.RegisterMessage(PublicKey) 88 | 89 | 90 | DESCRIPTOR._options = None 91 | _PUBLICKEY._options = None 92 | # @@protoc_insertion_point(module_scope) 93 | -------------------------------------------------------------------------------- /src/xian/utils/encoding.py: -------------------------------------------------------------------------------- 1 | import json 2 | import binascii 3 | import hashlib 4 | import decimal 5 | 6 | from typing import Tuple 7 | from contracting.stdlib.bridge.decimal import ContractingDecimal 8 | from contracting.stdlib.bridge.time import Datetime 9 | from loguru import logger 10 | 11 | 12 | def encode_str(value): 13 | return value.encode("utf-8") 14 | 15 | 16 | def decode_transaction_bytes(raw) -> Tuple[dict, str]: 17 | tx_bytes = raw 18 | tx_hex = tx_bytes.decode("utf-8") 19 | tx_decoded_bytes = bytes.fromhex(tx_hex) 20 | tx_str = tx_decoded_bytes.decode("utf-8") 21 | tx_json = json.loads(tx_str) 22 | payload_str = extract_payload_string(tx_str) 23 | 24 | assert json.loads(payload_str) == tx_json["payload"], 'Invalid payload' 25 | return tx_json, payload_str 26 | 27 | 28 | def encode_transaction_bytes(tx_str: str) -> bytes: 29 | tx_bytes = tx_str.encode("utf-8") 30 | tx_hex = binascii.hexlify(tx_bytes).decode("utf-8") 31 | return tx_hex.encode("utf-8") 32 | 33 | 34 | def extract_payload_string(json_str): 35 | try: 36 | # Find the start of the 'payload' object 37 | start_index = json_str.find('"payload":') 38 | if start_index == -1: 39 | raise ValueError("No 'payload' found in the provided JSON string.") 40 | 41 | # Find the opening brace of the 'payload' object 42 | start_brace_index = json_str.find('{', start_index) 43 | if start_brace_index == -1: 44 | raise ValueError("Malformed JSON: No opening brace for 'payload'.") 45 | 46 | # Use a stack to find the matching closing brace, ignoring braces within strings 47 | brace_count = 0 48 | in_string = False 49 | i = start_brace_index 50 | while i < len(json_str): 51 | char = json_str[i] 52 | 53 | if char == '"' and (i == 0 or json_str[i-1] != '\\'): 54 | in_string = not in_string 55 | 56 | if not in_string: 57 | if char == '{': 58 | brace_count += 1 59 | elif char == '}': 60 | brace_count -= 1 61 | 62 | # When brace_count is zero, we've found the matching closing brace 63 | if brace_count == 0: 64 | return json_str[start_brace_index:i+1] 65 | 66 | i += 1 67 | 68 | raise ValueError("Malformed JSON: No matching closing brace for 'payload'.") 69 | except Exception as e: 70 | logger.error(f"An unexpected error occurred: {e}") 71 | raise 72 | 73 | def hash_bytes(bytes): 74 | return hashlib.sha256(bytes).hexdigest() 75 | 76 | 77 | def convert_binary_to_hex(binary_data): 78 | try: 79 | return binascii.hexlify(binary_data).decode() 80 | except UnicodeDecodeError as e: 81 | logger.error(f"The binary data could not be decoded with UTF-8 encoding: {e}") 82 | raise 83 | except Exception as e: 84 | logger.error(f"An unexpected error occurred: {e}") 85 | raise 86 | 87 | 88 | def stringify_decimals(obj): 89 | try: 90 | if isinstance(obj, ContractingDecimal): 91 | return str(obj) 92 | elif isinstance(obj, decimal.Decimal): 93 | return str(obj) 94 | elif isinstance(obj, dict): 95 | return {key: stringify_decimals(val) for key, val in obj.items()} 96 | elif isinstance(obj, list): 97 | return [stringify_decimals(elem) for elem in obj] 98 | elif isinstance(obj, Datetime): 99 | return str(obj) 100 | elif isinstance(obj, bytes): 101 | try: 102 | return obj.decode("utf-8") 103 | except UnicodeDecodeError: 104 | return str(obj) 105 | else: 106 | return obj 107 | except: 108 | return "" 109 | 110 | -------------------------------------------------------------------------------- /src/xian/services/bds/database.py: -------------------------------------------------------------------------------- 1 | import json 2 | import asyncpg 3 | 4 | from loguru import logger 5 | from xian.services.bds.config import Config 6 | 7 | 8 | def result_to_json(result): 9 | results = [] 10 | for row in result: 11 | row_dict = dict(row) 12 | results.append(row_dict) 13 | 14 | # Convert the list of dictionaries to JSON 15 | return json.dumps(results, default=str) 16 | 17 | 18 | class DB: 19 | 20 | batch = [] 21 | 22 | def __init__(self, config: Config): 23 | self.cfg = config 24 | self.pool = None 25 | 26 | async def init_pool(self): 27 | # Create a temporary connection to the default database to check/create the target database 28 | temp_conn = await asyncpg.connect( 29 | user=self.cfg.get('db_user'), 30 | password=self.cfg.get('db_pass'), 31 | database='postgres', # Connect to the default 'postgres' database 32 | host=self.cfg.get('db_host'), 33 | port=self.cfg.get('db_port') 34 | ) 35 | try: 36 | # Check if the target database exists 37 | result = await temp_conn.fetchval( 38 | "SELECT 1 FROM pg_database WHERE datname = $1", 39 | self.cfg.get('db_name') 40 | ) 41 | if not result: 42 | # Create the target database if it does not exist 43 | await temp_conn.execute( 44 | f"CREATE DATABASE {self.cfg.get('db_name')}" 45 | ) 46 | finally: 47 | await temp_conn.close() 48 | 49 | # Now create the connection pool to the target database 50 | self.pool = await asyncpg.create_pool( 51 | user=self.cfg.get('db_user'), 52 | password=self.cfg.get('db_pass'), 53 | database=self.cfg.get('db_name'), 54 | host=self.cfg.get('db_host'), 55 | port=self.cfg.get('db_port') 56 | ) 57 | 58 | async def execute(self, query: str, params: list = []): 59 | """ 60 | This is meant for INSERT, UPDATE and DELETE statements 61 | that usually don't return data 62 | """ 63 | async with self.pool.acquire() as connection: 64 | try: 65 | result = await connection.execute(query, *params) 66 | return result 67 | except Exception as e: 68 | logger.exception(f'Error while executing SQL: {e}') 69 | raise e 70 | 71 | def add_query_to_batch(self, query: str, args: list): 72 | self.batch.append((query, args)) 73 | 74 | async def commit_batch_to_disk(self): 75 | async with self.pool.acquire() as connection: 76 | try: 77 | for query, params in self.batch: 78 | await connection.execute(query, *params) 79 | except Exception as e: 80 | logger.exception(f'Error while executing SQL: {e}') 81 | raise e 82 | finally: 83 | self.batch = [] 84 | 85 | async def fetch(self, query: str, params: list = []): 86 | """ 87 | This is meant for SELECT statements that return data 88 | """ 89 | async with self.pool.acquire() as connection: 90 | try: 91 | result = await connection.fetch(query, *params) 92 | return result 93 | except Exception as e: 94 | logger.exception(f'Error while executing SQL: {e}') 95 | raise e 96 | 97 | async def has_entries(self, table_name: str) -> bool: 98 | try: 99 | result = await self.fetch(f"SELECT COUNT(*) as count FROM {table_name}") 100 | logger.debug(result) 101 | return result[0]['count'] > 0 102 | except Exception as e: 103 | logger.exception(e) 104 | return False 105 | -------------------------------------------------------------------------------- /protos/cometbft/consensus/v1beta1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.consensus.v1beta1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/consensus/v1beta1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cometbft/types/v1beta1/types.proto"; 8 | import "cometbft/libs/bits/v1/types.proto"; 9 | 10 | // NewRoundStep is sent for every step taken in the ConsensusState. 11 | // For every height/round/step transition 12 | message NewRoundStep { 13 | int64 height = 1; 14 | int32 round = 2; 15 | uint32 step = 3; 16 | int64 seconds_since_start_time = 4; 17 | int32 last_commit_round = 5; 18 | } 19 | 20 | // NewValidBlock is sent when a validator observes a valid block B in some round r, 21 | // i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r. 22 | // In case the block is also committed, then IsCommit flag is set to true. 23 | message NewValidBlock { 24 | int64 height = 1; 25 | int32 round = 2; 26 | cometbft.types.v1beta1.PartSetHeader block_part_set_header = 3 [(gogoproto.nullable) = false]; 27 | cometbft.libs.bits.v1.BitArray block_parts = 4; 28 | bool is_commit = 5; 29 | } 30 | 31 | // Proposal is sent when a new block is proposed. 32 | message Proposal { 33 | cometbft.types.v1beta1.Proposal proposal = 1 [(gogoproto.nullable) = false]; 34 | } 35 | 36 | // ProposalPOL is sent when a previous proposal is re-proposed. 37 | message ProposalPOL { 38 | int64 height = 1; 39 | int32 proposal_pol_round = 2; 40 | cometbft.libs.bits.v1.BitArray proposal_pol = 3 [(gogoproto.nullable) = false]; 41 | } 42 | 43 | // BlockPart is sent when gossipping a piece of the proposed block. 44 | message BlockPart { 45 | int64 height = 1; 46 | int32 round = 2; 47 | cometbft.types.v1beta1.Part part = 3 [(gogoproto.nullable) = false]; 48 | } 49 | 50 | // Vote is sent when voting for a proposal (or lack thereof). 51 | message Vote { 52 | cometbft.types.v1beta1.Vote vote = 1; 53 | } 54 | 55 | // HasVote is sent to indicate that a particular vote has been received. 56 | message HasVote { 57 | int64 height = 1; 58 | int32 round = 2; 59 | cometbft.types.v1beta1.SignedMsgType type = 3; 60 | int32 index = 4; 61 | } 62 | 63 | // VoteSetMaj23 is sent to indicate that a given BlockID has seen +2/3 votes. 64 | message VoteSetMaj23 { 65 | int64 height = 1; 66 | int32 round = 2; 67 | cometbft.types.v1beta1.SignedMsgType type = 3; 68 | cometbft.types.v1beta1.BlockID block_id = 4 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; 69 | } 70 | 71 | // VoteSetBits is sent to communicate the bit-array of votes seen for the BlockID. 72 | message VoteSetBits { 73 | int64 height = 1; 74 | int32 round = 2; 75 | cometbft.types.v1beta1.SignedMsgType type = 3; 76 | cometbft.types.v1beta1.BlockID block_id = 4 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; 77 | cometbft.libs.bits.v1.BitArray votes = 5 [(gogoproto.nullable) = false]; 78 | } 79 | 80 | // Message is an abstract consensus message. 81 | message Message { 82 | // Sum of all possible messages. 83 | oneof sum { 84 | NewRoundStep new_round_step = 1; 85 | NewValidBlock new_valid_block = 2; 86 | Proposal proposal = 3; 87 | ProposalPOL proposal_pol = 4; 88 | BlockPart block_part = 5; 89 | Vote vote = 6; 90 | HasVote has_vote = 7; 91 | VoteSetMaj23 vote_set_maj23 = 8; 92 | VoteSetBits vote_set_bits = 9; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/xian/tools/genesis_upgrades/approvals_upgrade.py: -------------------------------------------------------------------------------- 1 | import json 2 | from typing import List, Dict, Tuple 3 | 4 | def find_xsc001_tokens(genesis_data: dict) -> List[str]: 5 | """Find all XSC001 token contracts in genesis data""" 6 | token_contracts = [] 7 | 8 | for entry in genesis_data['abci_genesis']['genesis']: 9 | key = entry.get('key', '') 10 | if key.endswith('.__code__') and "pixel" not in key: 11 | contract_name = key.replace('.__code__', '') 12 | code = entry['value'] 13 | 14 | # Check if it's an XSC001 token 15 | required_elements = [ 16 | '__balances = Hash(', 17 | '__metadata = Hash(', 18 | 'def transfer(', 19 | 'def approve(', 20 | 'def transfer_from(' 21 | ] 22 | 23 | if all(element in code for element in required_elements): 24 | token_contracts.append(contract_name) 25 | 26 | return token_contracts 27 | 28 | def migrate_approvals(genesis_data: dict, token_contracts: List[str]) -> Tuple[dict, bool]: 29 | """ 30 | Migrate old approval format to new format for specified token contracts 31 | Returns: (updated_genesis_data, changes_made) 32 | """ 33 | changes_made = False 34 | new_genesis = [] 35 | 36 | for entry in genesis_data['abci_genesis']['genesis']: 37 | key = entry.get('key', '') 38 | 39 | # Check if this is an approval entry that needs migration 40 | is_approval = False 41 | for contract in token_contracts: 42 | if key.startswith(f"{contract}.balances:") and ":" in key[len(contract)+10:]: 43 | # This is an approval entry that needs to be migrated 44 | # Original format: contract.balances:sender:spender 45 | # New format: contract.approvals:sender:spender 46 | new_key = key.replace(f"{contract}.balances:", f"{contract}.approvals:") 47 | new_entry = { 48 | 'key': new_key, 49 | 'value': entry['value'] 50 | } 51 | new_genesis.append(new_entry) 52 | changes_made = True 53 | is_approval = True 54 | break 55 | 56 | # If it's not an approval entry, keep it 57 | if not is_approval: 58 | new_genesis.append(entry) 59 | 60 | genesis_data['abci_genesis']['genesis'] = new_genesis 61 | return genesis_data, changes_made 62 | 63 | def process_genesis_data(genesis_data: dict) -> Tuple[dict, bool]: 64 | """ 65 | Main function to process the genesis data 66 | Returns: (updated_genesis_data, changes_made) 67 | """ 68 | # First find all XSC001 tokens 69 | token_contracts = find_xsc001_tokens(genesis_data) 70 | 71 | if not token_contracts: 72 | print("No XSC001 tokens found") 73 | return genesis_data, False 74 | 75 | print(f"Found {len(token_contracts)} XSC001 tokens:") 76 | for contract in token_contracts: 77 | print(f" - {contract}") 78 | 79 | # Then migrate approvals for these tokens 80 | return migrate_approvals(genesis_data, token_contracts) 81 | 82 | if __name__ == "__main__": 83 | genesis_file_path = "./genesis.json" 84 | 85 | # Read the genesis file 86 | with open(genesis_file_path, 'r') as f: 87 | genesis_data = json.load(f) 88 | 89 | # Process the genesis data 90 | updated_genesis, changes_made = process_genesis_data(genesis_data) 91 | 92 | if changes_made: 93 | # Generate output filename based on input 94 | import os 95 | dir_path = os.path.dirname(genesis_file_path) 96 | base_name = os.path.basename(genesis_file_path) 97 | name, ext = os.path.splitext(base_name) 98 | output_path = os.path.join(dir_path, f"{name}_updated{ext}") 99 | 100 | # Write the updated genesis file 101 | with open(output_path, 'w') as f: 102 | json.dump(updated_genesis, f, indent=4) 103 | print(f"Updated genesis file written to: {output_path}") 104 | else: 105 | print("No changes were made to the genesis file") 106 | -------------------------------------------------------------------------------- /protos/cometbft/consensus/v1/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package cometbft.consensus.v1; 3 | 4 | option go_package = "github.com/cometbft/cometbft/api/cometbft/consensus/v1"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cometbft/libs/bits/v1/types.proto"; 8 | import "cometbft/types/v1/types.proto"; 9 | 10 | // NewRoundStep is sent for every step taken in the ConsensusState. 11 | // For every height/round/step transition 12 | message NewRoundStep { 13 | int64 height = 1; 14 | int32 round = 2; 15 | uint32 step = 3; 16 | int64 seconds_since_start_time = 4; 17 | int32 last_commit_round = 5; 18 | } 19 | 20 | // NewValidBlock is sent when a validator observes a valid block B in some round r, 21 | // i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r. 22 | // In case the block is also committed, then IsCommit flag is set to true. 23 | message NewValidBlock { 24 | int64 height = 1; 25 | int32 round = 2; 26 | cometbft.types.v1.PartSetHeader block_part_set_header = 3 [(gogoproto.nullable) = false]; 27 | cometbft.libs.bits.v1.BitArray block_parts = 4; 28 | bool is_commit = 5; 29 | } 30 | 31 | // Proposal is sent when a new block is proposed. 32 | message Proposal { 33 | cometbft.types.v1.Proposal proposal = 1 [(gogoproto.nullable) = false]; 34 | } 35 | 36 | // ProposalPOL is sent when a previous proposal is re-proposed. 37 | message ProposalPOL { 38 | int64 height = 1; 39 | int32 proposal_pol_round = 2; 40 | cometbft.libs.bits.v1.BitArray proposal_pol = 3 [(gogoproto.nullable) = false]; 41 | } 42 | 43 | // BlockPart is sent when gossipping a piece of the proposed block. 44 | message BlockPart { 45 | int64 height = 1; 46 | int32 round = 2; 47 | cometbft.types.v1.Part part = 3 [(gogoproto.nullable) = false]; 48 | } 49 | 50 | // Vote is sent when voting for a proposal (or lack thereof). 51 | message Vote { 52 | cometbft.types.v1.Vote vote = 1; 53 | } 54 | 55 | // HasVote is sent to indicate that a particular vote has been received. 56 | message HasVote { 57 | int64 height = 1; 58 | int32 round = 2; 59 | cometbft.types.v1.SignedMsgType type = 3; 60 | int32 index = 4; 61 | } 62 | 63 | // VoteSetMaj23 is sent to indicate that a given BlockID has seen +2/3 votes. 64 | message VoteSetMaj23 { 65 | int64 height = 1; 66 | int32 round = 2; 67 | cometbft.types.v1.SignedMsgType type = 3; 68 | cometbft.types.v1.BlockID block_id = 4 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; 69 | } 70 | 71 | // VoteSetBits is sent to communicate the bit-array of votes seen for the BlockID. 72 | message VoteSetBits { 73 | int64 height = 1; 74 | int32 round = 2; 75 | cometbft.types.v1.SignedMsgType type = 3; 76 | cometbft.types.v1.BlockID block_id = 4 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; 77 | cometbft.libs.bits.v1.BitArray votes = 5 [(gogoproto.nullable) = false]; 78 | } 79 | 80 | // HasProposalBlockPart is sent to indicate that a particular proposal block part has been received. 81 | message HasProposalBlockPart { 82 | int64 height = 1; 83 | int32 round = 2; 84 | int32 index = 3; 85 | } 86 | 87 | // Message is an abstract consensus message. 88 | message Message { 89 | // Sum of all possible messages. 90 | oneof sum { 91 | NewRoundStep new_round_step = 1; 92 | NewValidBlock new_valid_block = 2; 93 | Proposal proposal = 3; 94 | ProposalPOL proposal_pol = 4; 95 | BlockPart block_part = 5; 96 | Vote vote = 6; 97 | HasVote has_vote = 7; 98 | VoteSetMaj23 vote_set_maj23 = 8; 99 | VoteSetBits vote_set_bits = 9; 100 | HasProposalBlockPart has_proposal_block_part = 10; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/cometbft/mempool/v1/types_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: cometbft/mempool/v1/types.proto 4 | 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import message as _message 7 | from google.protobuf import reflection as _reflection 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor.FileDescriptor( 17 | name='cometbft/mempool/v1/types.proto', 18 | package='cometbft.mempool.v1', 19 | syntax='proto3', 20 | serialized_options=b'Z4github.com/cometbft/cometbft/api/cometbft/mempool/v1', 21 | create_key=_descriptor._internal_create_key, 22 | serialized_pb=b'\n\x1f\x63ometbft/mempool/v1/types.proto\x12\x13\x63ometbft.mempool.v1\"\x12\n\x03Txs\x12\x0b\n\x03txs\x18\x01 \x03(\x0c\"9\n\x07Message\x12\'\n\x03txs\x18\x01 \x01(\x0b\x32\x18.cometbft.mempool.v1.TxsH\x00\x42\x05\n\x03sumB6Z4github.com/cometbft/cometbft/api/cometbft/mempool/v1b\x06proto3' 23 | ) 24 | 25 | 26 | 27 | 28 | _TXS = _descriptor.Descriptor( 29 | name='Txs', 30 | full_name='cometbft.mempool.v1.Txs', 31 | filename=None, 32 | file=DESCRIPTOR, 33 | containing_type=None, 34 | create_key=_descriptor._internal_create_key, 35 | fields=[ 36 | _descriptor.FieldDescriptor( 37 | name='txs', full_name='cometbft.mempool.v1.Txs.txs', index=0, 38 | number=1, type=12, cpp_type=9, label=3, 39 | has_default_value=False, default_value=[], 40 | message_type=None, enum_type=None, containing_type=None, 41 | is_extension=False, extension_scope=None, 42 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 43 | ], 44 | extensions=[ 45 | ], 46 | nested_types=[], 47 | enum_types=[ 48 | ], 49 | serialized_options=None, 50 | is_extendable=False, 51 | syntax='proto3', 52 | extension_ranges=[], 53 | oneofs=[ 54 | ], 55 | serialized_start=56, 56 | serialized_end=74, 57 | ) 58 | 59 | 60 | _MESSAGE = _descriptor.Descriptor( 61 | name='Message', 62 | full_name='cometbft.mempool.v1.Message', 63 | filename=None, 64 | file=DESCRIPTOR, 65 | containing_type=None, 66 | create_key=_descriptor._internal_create_key, 67 | fields=[ 68 | _descriptor.FieldDescriptor( 69 | name='txs', full_name='cometbft.mempool.v1.Message.txs', index=0, 70 | number=1, type=11, cpp_type=10, label=1, 71 | has_default_value=False, default_value=None, 72 | message_type=None, enum_type=None, containing_type=None, 73 | is_extension=False, extension_scope=None, 74 | serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), 75 | ], 76 | extensions=[ 77 | ], 78 | nested_types=[], 79 | enum_types=[ 80 | ], 81 | serialized_options=None, 82 | is_extendable=False, 83 | syntax='proto3', 84 | extension_ranges=[], 85 | oneofs=[ 86 | _descriptor.OneofDescriptor( 87 | name='sum', full_name='cometbft.mempool.v1.Message.sum', 88 | index=0, containing_type=None, 89 | create_key=_descriptor._internal_create_key, 90 | fields=[]), 91 | ], 92 | serialized_start=76, 93 | serialized_end=133, 94 | ) 95 | 96 | _MESSAGE.fields_by_name['txs'].message_type = _TXS 97 | _MESSAGE.oneofs_by_name['sum'].fields.append( 98 | _MESSAGE.fields_by_name['txs']) 99 | _MESSAGE.fields_by_name['txs'].containing_oneof = _MESSAGE.oneofs_by_name['sum'] 100 | DESCRIPTOR.message_types_by_name['Txs'] = _TXS 101 | DESCRIPTOR.message_types_by_name['Message'] = _MESSAGE 102 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 103 | 104 | Txs = _reflection.GeneratedProtocolMessageType('Txs', (_message.Message,), { 105 | 'DESCRIPTOR' : _TXS, 106 | '__module__' : 'cometbft.mempool.v1.types_pb2' 107 | # @@protoc_insertion_point(class_scope:cometbft.mempool.v1.Txs) 108 | }) 109 | _sym_db.RegisterMessage(Txs) 110 | 111 | Message = _reflection.GeneratedProtocolMessageType('Message', (_message.Message,), { 112 | 'DESCRIPTOR' : _MESSAGE, 113 | '__module__' : 'cometbft.mempool.v1.types_pb2' 114 | # @@protoc_insertion_point(class_scope:cometbft.mempool.v1.Message) 115 | }) 116 | _sym_db.RegisterMessage(Message) 117 | 118 | 119 | DESCRIPTOR._options = None 120 | # @@protoc_insertion_point(module_scope) 121 | -------------------------------------------------------------------------------- /protos/README.md: -------------------------------------------------------------------------------- 1 | [NB]: # ( 2 | Ensure that all hyperlinks in this doc are absolute URLs, not relative ones, 3 | as this doc gets published to the Buf registry and relative URLs will fail 4 | to resolve. 5 | ) 6 | 7 | # CometBFT Protocol Buffers Definitions 8 | 9 | This is the set of [Protobuf][protobuf] definitions of types used by various 10 | parts of [CometBFT]: 11 | 12 | - The [Application Blockchain Interface][abci] (ABCI), especially in the context 13 | of _remote_ applications. 14 | - The P2P layer, in how CometBFT nodes interact with each other over the 15 | network. 16 | - In interaction with remote signers ("privval"). 17 | - The RPC, in that the native JSON serialization of certain Protobuf types is 18 | used when accepting and responding to RPC requests. 19 | - The storage layer, in how data is serialized to and deserialized from on-disk 20 | storage. 21 | 22 | The canonical Protobuf definitions live in the `proto` folder of the relevant 23 | release branch of CometBFT. These definitions are published to the [Buf 24 | registry][buf] for integrators' convenience. 25 | 26 | The Protobuf files are organized under two domains: `cometbft` and `tendermint`. 27 | The `cometbft.*` packages use version suffixes to let application developers 28 | target versions of the protocols as they have evolved between CometBFT releases. 29 | 30 | ## Which CometBFT release does each package belong to? 31 | 32 | By the 1.0.0 release, the entire set of Protobuf definitions used by CometBFT 33 | is published in packages suffixed with `.v1`. Earlier revisions of the 34 | definitions, where they differed, are provided alongside in `.v1beta`_N_ 35 | packages. The correspondence between package suffixes and releases is as follows: 36 | 37 | | Domain | 0.34 | 0.37 | 0.38 | 1.0 | 38 | |-----------------|-----------|-----------|-----------|------| 39 | | `abci` | `v1beta1` | `v1beta2` | `v1beta3` | `v1` | 40 | | `blocksync` | | `v1beta1` | `v1` | `v1` | 41 | | `consensus` | `v1beta1` | `v1beta1` | `v1beta1` | `v1` | 42 | | `crypto` | `v1` | `v1` | `v1` | `v1` | 43 | | `libs/bits` | `v1` | `v1` | `v1` | `v1` | 44 | | `mempool` | `v1` | `v1` | `v1` | `v1` | 45 | | `p2p` | `v1` | `v1` | `v1` | `v1` | 46 | | `privval` | `v1beta1` | `v1beta1` | `v1beta2` | `v1` | 47 | | `rpc/grpc`[^1] | `v1beta1` | `v1beta2` | `v1beta3` | | 48 | | `state` | `v1beta1` | `v1beta2` | `v1beta3` | `v1` | 49 | | `statesync` | `v1` | `v1` | `v1` | `v1` | 50 | | `types` | `v1beta1` | `v1beta2` | `v1` | `v1` | 51 | | `version` | `v1` | `v1` | `v1` | `v1` | 52 | 53 | [^1]: Retired in 1.0 54 | 55 | ## Why does CometBFT provide `tendermint` Protobuf definitions? 56 | 57 | This is as a result of CometBFT being a fork of [Tendermint Core][tmcore] and 58 | wanting to provide integrators with as painless a way as possible of 59 | transitioning from Tendermint Core to CometBFT. 60 | 61 | As of CometBFT v1, however, the project will transition to using and providing a 62 | `cometbft` package of Protobuf definitions (see [\#1330]). 63 | 64 | Protobuf definitions for each respective release are also, for convenience, 65 | published to a corresponding branch in the `tendermint/tendermint` Buf repository. 66 | 67 | | CometBFT version | Canonical Protobufs | Buf registry | 68 | |------------------|---------------------------------------------|-------------------------------------------| 69 | | v0.38.x | [v0.38.x Protobuf definitions][v038-protos] | [Buf repository v0.38.x branch][v038-buf] | 70 | | v0.37.x | [v0.37.x Protobuf definitions][v037-protos] | [Buf repository v0.37.x branch][v037-buf] | 71 | | v0.34.x | [v0.34.x Protobuf definitions][v034-protos] | [Buf repository v0.34.x branch][v034-buf] | 72 | 73 | [protobuf]: https://protobuf.dev/ 74 | [CometBFT]: https://github.com/cometbft/cometbft 75 | [abci]: https://github.com/cometbft/cometbft/tree/main/spec/abci 76 | [buf]: https://buf.build/tendermint/tendermint 77 | [tmcore]: https://github.com/tendermint/tendermint 78 | [\#1330]: https://github.com/cometbft/cometbft/issues/1330 79 | [v034-protos]: https://github.com/cometbft/cometbft/tree/v0.34.x/proto 80 | [v034-buf]: https://buf.build/tendermint/tendermint/docs/v0.34.x 81 | [v037-protos]: https://github.com/cometbft/cometbft/tree/v0.37.x/proto 82 | [v037-buf]: https://buf.build/tendermint/tendermint/docs/v0.37.x 83 | [v038-protos]: https://github.com/cometbft/cometbft/tree/v0.38.x/proto 84 | [v038-buf]: https://buf.build/tendermint/tendermint/docs/v0.38.x 85 | --------------------------------------------------------------------------------