An attestation-native sovereign rollup.
Register verifiable claims, run the attestor sets that vouch for them, and pay for verified work through an on-chain marketplace. Domain-agnostic; AI provenance is the first vertical, not the only one.
Ligate Chain is an attestation-native sovereign rollup. Its core primitive is the attestation: a signed, on-chain record that some claim is true. Around that sits a marketplace that pays for producing verified claims. The chain never sees what you attest; it records who vouched for what, and settles payment for verified work.
It is deliberately domain-agnostic. The same primitives serve AI-prompt provenance (the first vertical, via Themisra), code and security audits, data labeling, supply-chain and ESG claims, document notarization, oracle feeds, governance receipts: anywhere the pattern is "trusted parties vouch that X is true, and someone gets paid for it."
- Attestation: register a schema (what kind of claim), an attestor set (the M-of-N signers trusted to vouch for that kind of claim), then submit attestations (a specific claim, signed by the set). The chain stores only hashes and signatures, never plaintext payloads. (spec)
- Bounty: a standing, buyer-funded offer: "I pay per verified attestation of type X." Open and fungible; anyone whose work the attestor set verifies gets paid. (spec)
- Contract: work-for-hire. One buyer escrows a pool for a specific deliverable, names an arbiter to resolve disputes, and the worker is paid on acceptance or an automatic timeout. (spec)
Ligate Chain is a Sovereign SDK rollup. The sequencer orders transactions and posts them as blobs to Celestia for data availability; every full node pulls the same blob stream and independently runs the state-transition function to derive identical state; a Risc0 zkVM proves that execution. There is no node-to-node gossip and no settlement to Ethereum, the chain is sovereign and delegates ordering plus availability to Celestia. Attestor sets are an application layer, not consensus participants: they sign claims off-chain, and the on-chain attestation module verifies those signatures against the registered set. Economics are buyer-funded, with no inflation and no staking required to use the chain: submitters pay a fee, and schema authors can route up to 50% of it to themselves (economics RFC). The Architecture section goes deeper.
Just want to run a node, not build from source? Pre-built Linux x86_64 / Linux arm64 / macOS arm64 binaries ship on every release: https://github.com/ligate-io/ligate-chain/releases. A multi-arch container image is also published on every release tag at
ghcr.io/ligate-io/ligate-chain:<version>(e.g.:0.4.0, plus:latest). See docs.ligate.io/nodes for the operator-facing install + boot recipes.
# Clone
git clone https://github.com/ligate-io/ligate-chain
cd ligate-chain
# Build the workspace (Rust 1.93 auto-installs via rust-toolchain.toml).
# Ubuntu / Debian first install: sudo apt install -y libclang-dev clang
# macOS first install: xcode-select --install (see "macOS first-build trifecta" below)
cargo build --workspace
# Run the workspace tests (lib + integration + doctests)
cargo test --workspaceThe ligate-node binary boots a single-node rollup against the checked-in devnet genesis. Two flavours, sharing the same chain state and only differing in DA layer:
# Default: in-process MockDa (SQLite). Single command, no external services.
cargo run --bin ligate-node
# Real Celestia DA (Mocha public RPC). Needs a Celestia signer key.
SOV_CELESTIA_RPC_URL=wss://celestia-mocha.public-rpc.com \
SOV_CELESTIA_SIGNER_KEY=$(pass celestia/devnet-signer) \
cargo run --bin ligate-node -- --da-layer celestiaDefaults pick up localnet/rollup.toml (or localnet/celestia.toml) and the localnet/genesis/*.json files. The bootstrap account holds treasury, sequencer, attester, and prover roles for v0; two extra accounts (lig1d0vqhk… and lig1njjery…) ship with AVOW so you can exercise transfers without minting.
The bootstrap and dev accounts above are derived from string labels via SHA-256 and have no associated private key, so on a freshly-booted localnet there's no account anyone can sign with out-of-the-box. To make cargo run --bin ligate-node immediately useful, localnet/local-dev-key.json ships a deterministic Ed25519 keypair (private-key seed = 0x0101…01, address lig132yw8ht5p8cetl2jmvknewjawt9xwzdlrk2pyxlnwjyqz3m499u) pre-funded with 10 000 AVOW. Treat it like Anvil's account-0: convenient for local testing, never for any real network.
Operators deploying ligate-devnet-2 MUST remove this address from localnet/genesis/bank.json (or use a substituted genesis bundle from ligate-genesis-tool) before producing the deploy artefacts. The local-dev-key.json file itself is harmless to ship publicly. Its private key being well-known is the point.
To use the dev key with ligate-cli:
mkdir -p ~/.local/share/io.ligate.cli/keys
echo '0101010101010101010101010101010101010101010101010101010101010101' \
> ~/.local/share/io.ligate.cli/keys/dev.key
chmod 600 ~/.local/share/io.ligate.cli/keys/dev.key
echo 'lig132yw8ht5p8cetl2jmvknewjawt9xwzdlrk2pyxlnwjyqz3m499u' \
> ~/.local/share/io.ligate.cli/keys/dev.address
# Now you can transfer from `dev`:
ligate transfer --signer dev --to lig1xyz... --amount 1.0 \
--chain-id 4242 --chain-hash $(curl -s http://127.0.0.1:12346/v1/rollup/info | jq -r .chain_hash) \
--token-id $(...)ligate-node runs a single binary on every cluster VM. Which node produces batches is decided at runtime by the Sovereign SDK's DbElected machinery: every node heartbeats into a shared Postgres, the SDK elects a single leader, and only the leader posts blobs to DA. If the leader process dies, a replica takes the lock in roughly one second and resumes batch production with the same PID. GET /v1/sequencer/role returns either "BatchProducer" or "PgSyncReplica"; GET /v1/cluster/nodes lists the whole topology.
The previous --mode {sequencer,follower} flag and its corresponding 503-on-submit middleware were removed in chain#446 after a paper-leader incident (a Follower-mode node promoted via in-process role transition kept the boot-time automatic_batch_production = false flag, holding the lock but never posting). DbElected gates posting on the lock and the SDK already returns 503 on POST /v1/sequencer/txs when not the leader, so the chain-level mode toggle was redundant.
A public devnet with federated attestor orgs is targeted for Q2 2026. Until then the protocol runs single-node locally as above. Per-flavour boot details (Mock / Celestia, env vars, secret-store helpers) live in localnet/README.md. Forward-looking operator notes (genesis ceremony, attestor key generation, multi-org topology) are in docs/development/devnet.md. Note that runbook still has sections marked Preview only from before Phase A landed; refresh tracked separately.
This repository holds the Ligate Chain protocol and its first-party SDKs. The v0 surface is a generic attestation protocol plus a marketplace that pays for verified work: anyone can register an attestor set and a schema, submit cryptographically signed records ("attestations") under it that anyone can verify later, and fund bounties or contracts that pay out when the work is attested. The chain stores only hashes and signatures, never plaintext payloads.
Product-specific code (Themisra, Iris, Kleidon) lives in separate repositories. Those products are the first consumers of this protocol, not part of it. They register their own schemas and attestor sets and submit attestations through the same public interface any other builder would use.
Who this repo is for:
- App builders who want to attach a verifiable, on-chain receipt to something that happened off-chain (model inferences, purchases, tickets, state transitions). The protocol is deliberately narrow and generic.
- Node operators running or planning to run a Ligate Chain node.
- Protocol contributors working on the rollup, the module, or the SDK.
The canonical specification is in docs/protocol/attestation-v0.md. Read it before opening a non-trivial PR against crates/modules/attestation.
Ligate Chain is a specialized app-chain, not a general-purpose smart-contract platform. The closer comparisons are Celestia, Hyperliquid, dYdX v4, or Cosmos app-chains: each chain has a narrow remit and is shaped around it. Our remit is on-chain attestation infrastructure: any cryptographically signed off-chain record, verifiable later by anyone, with the curated module set (tokens, NFTs, payments, identity, agents) layered around it. AI provenance is the highest-conviction wedge use case (via Themisra) but the protocol is domain-agnostic: anyone registers a schema and an attestor set, anyone submits attestations under it.
It is:
- A sovereign rollup on Celestia DA. Own state, own token (AVOW), own sequencer, own protocol logic.
- A curated module set. Today:
attestation,bounty,contract. Planned:tokens(#47) andnft(#48) in v1,payments,agents,identity,disputeslater. Each module is a designed product surface, not a sandbox. - Permissionless at the schema level: anyone registers a schema on the attestation module and submits attestations under it. No gatekeeper.
It isn't:
- An EVM chain in v0 / v1 / v2 / v3. There is no Solidity, no contract deployment, no ERC-20 deploy via tx in any of those phases. Tokens and NFTs come through the curated
tokensandnftmodules. EVM compatibility is tracked as a long-horizon v4 option (#52) we will revisit only after the attestation focus has paid off in shipped, in-production users; until then we don't dilute the chain identity for it. - An L1 in the Bitcoin / Ethereum sense. We use Celestia for data availability rather than building our own DA layer. We are sovereign in the rollup sense (no settlement to Ethereum, our own validator set), but DA is outsourced.
- An L2 in the Optimism / Arbitrum sense. We do not settle to Ethereum.
- A general DeFi platform. The chain is shaped for attestation primitives plus a few sister modules. Lending, AMMs, perps, and similar live on chains designed for them.
What you can build on Ligate Chain today and through the v1 roadmap: apps that register schemas and submit attestations (any domain: AI provenance, supply-chain, document notary, oracle data, governance receipts, KYC checkpoints, sensor logs, you name it); apps that issue fungible tokens or NFTs once tokens (#47) and nft (#48) modules ship; apps that compose with payments, identity, agent registry, and disputes modules as those land. What you can't build today: anything requiring arbitrary smart-contract execution (no EVM in v0-v3; tracked as a v4 option in #52). For chain-shaped Web3 features through curated modules + a permissionless attestation primitive, this is the chain. For arbitrary Solidity/Rust contracts, an EVM L2 or Solana is the right place today.
flowchart TB
User["Users / Apps<br/>(client SDK)"]
Celestia[("Celestia DA<br/>Mocha testnet")]
subgraph chain["Ligate Chain (Sovereign SDK rollup)"]
Sequencer["Sequencer<br/>tx ordering + batching"]
FullNode["Full Node<br/>cargo run --bin ligate-node"]
Prover["Risc0 Prover<br/>ZK state proofs"]
end
subgraph offchain["Off-chain attestor quorum (per schema)"]
Quorum["Quorum Service"]
Attestors["Attestor Nodes<br/>ed25519 signers"]
end
User -->|submit_tx| Sequencer
User -->|JSON-RPC query| FullNode
User -.->|attestation request| Quorum
Quorum --> Attestors
Attestors -.->|signed digests| Quorum
Quorum -.->|signed attestation| User
Sequencer -->|blob| Celestia
Celestia -->|blob stream| FullNode
Celestia -->|blob stream| Prover
Prover -.->|state proof| FullNode
Ligate Chain is a sovereign rollup, not a peer-to-peer blockchain. Full nodes do not gossip with each other. Each node:
- Subscribes to a Celestia namespace and pulls the rollup's blobs as they appear.
- Independently runs the STF over each blob to derive the chain state.
- Serves JSON-RPC queries against its own derived state.
Coordination happens through two places, never through node-to-node messaging:
- The sequencer is the canonical entry point for transactions. Users submit transactions to its RPC; it batches them, picks an order, and posts the batch as a blob to Celestia. In v0, Ligate Labs runs the only sequencer; multi-sequencer (leader rotation, based-rollup) is a v1+ direction.
- Celestia is the source of truth for inclusion and ordering. Every node sees the same blob stream and therefore reaches the same state. The chain's "consensus" is delegated to Celestia's DA + ordering; the rollup itself only enforces the STF. Disagreements about state are impossible if a node has correctly executed the STF over the same blobs.
This is the standard rollup model. Same shape as every Sovereign SDK rollup, every modern Cosmos app-chain on Celestia (Stride, Dymension), and every Ethereum L2 (Optimism, Arbitrum, Base), minus settlement back to Ethereum, since we are sovereign and don't post proofs to an L1.
Attestor nodes are not chain consensus participants. They sign attestation digests off-chain on behalf of a particular schema's quorum:
- The schema's off-chain quorum service (e.g. Themisra's attestor service for
themisra.proof-of-prompt/v1) receives a sign request from the user. - It produces a canonical digest and forwards it to each attestor node in its set.
- Each attestor node holds an ed25519 keypair, signs the digest, returns the signature.
- The quorum service collects the M-of-N signatures and hands the user a fully-signed attestation.
- The user's client SDK submits a
SubmitAttestationtransaction containing the signatures to the sequencer. - The on-chain
attestationmodule verifies the signatures match the schema's registered attestor set and writes the attestation to state.
Each schema gets its own attestor set with its own threshold. Different schemas can share attestor pools, or each can run its own. The chain layer stays neutral; signing logic stays in product-specific quorum services.
For v0 devnet:
| Layer | Status | Path to decentralise |
|---|---|---|
| Data availability | Decentralised via Celestia | Already there |
| State verification | Decentralised: anyone runs ligate-node and re-derives |
Already there |
| Sequencer | Centralised (Ligate Labs) | v1+: leader rotation / shared sequencer |
| Public RPC endpoint | Centralised (Ligate Labs hosted) | Anyone runs their own full node today; community RPCs over time |
| Schema attestor sets | Federated per-schema (3-5 orgs each for first-party schemas) | Permissionless: any project registers its own |
| Prover | Centralised (Ligate Labs) | v2: prover marketplace (#39) |
The attestation primitive itself is permissionless from day one: anyone can register a new schema with a new attestor set without asking us. The infrastructure around it (sequencer, RPC, prover) decentralises over the v1 → v2 horizon.
Cargo workspace (resolver 2). Members:
crates/modules/attestation: the attestation protocol module. Data shapes, state layout, call handlers, signature validation, and fee routing throughsov-bank.crates/modules/bounty: the bounty marketplace module. Buyer-funded, schema-anchored bounties that pay the submitter of an accepted attestation; full lifecycle (post / claim / dispute / resolve / cancel / finalise) with module-controlled escrow, composed onattestation+chain_state.crates/modules/contract: the contract module. Work-for-hire deliverable contracts with a named arbiter and a timeout-based auto-accept (post / commit / deliver / accept / reject / resolve / cancel / finalize-delivery).crates/stf: the runtime crate that composes the chain's modules (bank,accounts,sequencer_registry,attester_incentives,prover_incentives,operator_incentives,uniqueness,chain_state,blob_storage,attestation,bounty,contract) into a state-transition function.CHAIN_HASHis derived from the runtime schema at build time so genesis can't drift from code.crates/stf-declaration: the runtime declaration consumed by the SDK macros.crates/rollup: the node binary (ligate-node). Wires the STF to the Celestia DA adapter and exposes the RPC surface.crates/rollup/provers/risc0: the Risc0 inner zkVM prover, including the Celestia guest binary that runs the full STF inside the zkVM.crates/client-rs: the Rust client SDK for applications talking to the chain. Typed builders and ed25519 helpers on the new SDK.crates/genesis-tool: operator-facing offline tool.keys generate,verify,generate(substitute keys into a template genesis bundle).crates/bootstrap-cli: operator-facing online tool. Runs the post-genesis canonical-schema registration ceremony: submits oneRegisterAttestorSet+ oneRegisterSchematx per entry incanonical-schemas.toml. Idempotent. Seedocs/development/canonical-schema-registration.md.
Localnet config (genesis files, Celestia and rollup TOMLs) lives in localnet/ and is checked in so anyone can boot a local node against Celestia mocha-testnet.
Protocol docs:
docs/protocol/attestation-v0.md: attestation protocol specification v0.docs/protocol/addresses-and-signing.md: how Ligate addresses (lig1…) work, why MetaMask doesn't sign for the chain today, and what changes when EVM auth (#72) lands.docs/protocol/rest-api.md: full reference for every REST endpoint exposed byligate-node.docs/protocol/threat-model.md: v0 attacker model, mitigations, and what is deliberately out of scope.docs/protocol/schemas/: canonical first-party schema specs (themisra.proof-of-prompt-v1.json, future Mneme/Iris/Kleidon schemas). Each file is the JSON Schema doc whose SHA-256 is the on-chainpayload_shape_hash.docs/protocol/lips/: Ligate Improvement Proposals. LIP-1 (process), LIP-5 (proof-of-prompt schema, in flight).
Rust toolchain is pinned via rust-toolchain.toml to 1.93.0. Any modern rustup will install it automatically when you enter the repo.
The SDK pulls in librocksdb-sys, which needs libclang at build time:
- Ubuntu / Debian:
sudo apt install libclang-dev clang - macOS: ships with the Command Line Tools (
xcode-select --install); you also need to set the dyld path so thelibrocksdb-sysbuild script can find the dylib at link time. Add to~/.zshrcor~/.bashrc:Or set them per-invocation:export DYLD_FALLBACK_LIBRARY_PATH=/Library/Developer/CommandLineTools/usr/lib export LIBCLANG_PATH=/Library/Developer/CommandLineTools/usr/lib
DYLD_FALLBACK_LIBRARY_PATH=/Library/Developer/CommandLineTools/usr/lib LIBCLANG_PATH=/Library/Developer/CommandLineTools/usr/lib cargo test ....
A clean macOS dev machine hits three failure modes in sequence on the first cargo check. All three are documented in CONTRIBUTING.md, but here's the one-shot recipe to get going:
librocksdb-syslink: the twoexports above.- Risc0 rustup toolchain override:
cargoerrors withoverride toolchain 'risc0' is not installedbefore the workspace even compiles. Install the toolchain manager:This is a ~1-2 GB one-time install. If you don't plan to touch the prover (Phase A.4 /curl -L https://risc0.com/install | bash rzup installcrates/rollup/provers/risc0), the lighter alternative isexport RUSTUP_TOOLCHAIN=1.93.0per shell to bypass the override. - Metal kernel build: Risc0 tries to compile macOS Metal kernels at build time. If you don't have full Xcode (only Command Line Tools), set:
Do NOT set this in CI: Linux runners build CPU kernels cleanly, and skipping there produces unresolved-symbol errors at link time. Per-machine workaround only.
export RISC0_SKIP_BUILD_KERNELS=1
Tracking: #417 covers proposed ergonomic improvements (.cargo/config.toml, etc.); cargo doesn't support target-conditional env vars natively, so this stays a documented per-machine setup for now.
# Compile check across the workspace
cargo check --workspace
# Run every test in every crate
cargo test --workspace
# Formatting (CI runs this with --check)
cargo fmt --all -- --check
# Clippy (CI treats warnings as errors)
cargo clippy --workspace --all-targets -- -D warnings
# Docs (CI treats rustdoc warnings as errors)
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --document-private-items
# Security advisories (install once with: cargo install cargo-audit)
cargo auditIgnored advisories and their rationales are documented in audit.toml. All current ignores are transitive dependencies pinned by the Sovereign SDK; they clear automatically on SDK upgrades.
.pre-commit-config.yaml runs cargo fmt --check on every commit so formatting drift is caught locally instead of in CI. One-time setup per clone:
brew install pre-commit # or: pip install pre-commit
pre-commit install # writes .git/hooks/pre-commitSkip the hook for an emergency commit with git commit --no-verify; the same check still re-runs in CI.
The v0 protocol has three entities. Full detail in the spec.
A quorum of ed25519 signers with an M-of-N threshold. Identified by SHA-256(sorted_members || threshold). Immutable once registered; to "rotate" signers, register a new set and point a new schema version at it.
An application's attestation shape: owner, name, version, the AttestorSetId that must sign under it, and optional fee routing (cap 50% to the schema owner, remainder to treasury). Identified by SHA-256(owner || name || version), so two different owners can safely reuse the same human-readable name. Registration is permissionless and gated only by the registration fee in AVOW.
The on-chain record: (schema_id, payload_hash, submitter, timestamp, signatures), keyed by (schema_id, payload_hash) and write-once. The chain verifies the supplied signatures against the schema's attestor set at submit time; later reads are cheap RPC queries against a StateMap.
Two primitives turn attestations into paid work, both with module-controlled escrow (funds live at the module's own derived address, not a third party):
- Bounty: a buyer escrows a pool against a schema and pays
per_attestationfor each accepted claim. Acceptance is rule-based (Any/AttestorSet/PayloadHashes/PeerCount); claims carry a dispute window; unclaimed or expired pools refund to the poster;FinaliseBountycloses out a fully-settled bounty. Built for fungible, parallel work, many contributors against one schema. (spec) - Contract: a buyer escrows a pool for one specific deliverable and names an arbiter. A worker commits with a bond, delivers, and is paid on the buyer's acceptance, an arbiter's dispute resolution, or an automatic timeout if the buyer never responds (the work-for-hire guarantee). Built for one-buyer, one-deliverable work. (spec)
Discovery and matching (which open bounties an attestation is eligible for, leaderboards, history) are indexer concerns, not consensus: the chain does point lookups, the off-chain indexer does the joins.
Devnet. ligate-devnet-2 is live on Celestia Mocha-testnet (running v0.4.0). The v0.4.0 release adds the bounty + contract marketplace; because it shifts chain_hash it is not state-compatible with devnet-2 and ships via a ligate-devnet-3 re-genesis (cutover in progress). Current surface:
- Attestation module: data types, state layout, call handlers, ed25519 signature validation, replay protection, fee routing.
- Marketplace modules (
v0.4.0):bounty(buyer-funded, schema-anchored, full lifecycle with module escrow, dispute windows, and finalise) andcontract(work-for-hire with a named arbiter and a timeout-based auto-accept). Both compose onattestation+chain_state. - Runtime:
ligate-stfcomposes the curated module set on the upgraded Sovereign SDK. - DA: Celestia adapter wired for block submission and ingestion.
- ZK: Risc0 inner zkVM with a Celestia guest binary that runs the full STF.
- Fees: real
AVOWtransfers throughsov-bank, with up to 50% of attestation fees routable to the schema owner. - Genesis: checked-in devnet config (bank, attestation, attester incentives, prover incentives, sequencer registry, operator incentives).
- Addresses:
lig1accounts,lpk1pubkeys,lsc1schema IDs,las1attestor set IDs,lph1payload hashes (Bech32m). - Chain id ladder (Cosmos-style strings):
ligate-localnet(single-node local dev),ligate-devnet-2(public devnet),ligate-testnet-1(later),ligate-1(mainnet). Trailing number bumps only on state-breaking restarts. Spec sectionChain id.
Open work items toward public devnet: hosted RPC endpoint, EVM authenticator (#72), and the v1 staking and disputes modules. Current tracked work lives in the GitHub issues.
Operator and builder surface lives outside this repo. Each tool is a thin consumer of crates/client-rs's typed message construction + the submit feature's transaction pipeline:
| Repo | Purpose | Tracking |
|---|---|---|
ligate-io/ligate-cli |
Operator and builder CLI: keys, balance, transfer, faucet | #112 |
ligate-io/faucet |
Devnet faucet, rate-limited AVOW drip |
#95 |
ligate-io/ligate-explorer |
Block explorer + indexer service | #80 |
v0 scope is the attestation protocol only. Identity, disputes/slashing, payments, and the agent registry are explicit v1 and v2 non-goals documented in the spec.
External audit reports and remediation tracking live in docs/audits/. Empty today, by design: no audit has been booked yet. Pre-ligate-testnet-1 we'll scope a focused audit of the attestation module and runtime; pre-ligate-1 mainnet a full-protocol audit. The convention for filing audit reports + paired markdown sidecars is documented in docs/audits/README.md.
In-repo security signal:
cargo auditruns on every PR (advisories pinned inaudit.toml).cargo denyenforces license, source, and duplicate-version policy on every PR (deny.toml).- Borsh wire-format snapshot tests guard against accidental hard forks (
crates/modules/attestation/tests/borsh_snapshot.rs). cargo fuzzharnesses run nightly against the public Borsh decoders, Bech32m parsers, and AttestationId round-trip (.github/workflows/fuzz.yml).- DA-isolation grep guard prevents Celestia coupling from leaking into DA-agnostic crates (
scripts/check-da-isolation.sh). - Threat model documented in
docs/protocol/threat-model.md.
The full contributor guide is in CONTRIBUTING.md: local dev setup (including the macOS libclang gotcha and the per-machine Risc0 workaround), code style, commit conventions, PR process, and the CI gates your branch has to pass.
Required reading before a non-trivial protocol PR:
docs/protocol/attestation-v0.md: the protocol specification.docs/protocol/addresses-and-signing.md: addressing and signature schemes..github/workflows/ci.yml: the CI gates.
This project adopts the Contributor Covenant. Security disclosures go through SECURITY.md, not public issues.
Issues and bug reports: github.com/ligate-io/ligate-chain/issues. General questions and design discussions: GitHub Discussions.
Licensed under either of:
- Apache License, Version 2.0 (
LICENSE-APACHEor https://www.apache.org/licenses/LICENSE-2.0) - MIT License (
LICENSE-MITor https://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this repository by you, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.