An attestor is a stateless off-chain service that signs statements about one chain’s state, and an attestation light client trusts exactly the keys that sign.
An attestor is an off-chain service that answers questions about one chain’s state with a signature. The attestation light client accepts a claim only when enough of its attestors have signed it, which makes a connection’s security exactly the keys that sign.This page covers what an attestor reads and signs, the finality offset that bounds its answers, how a set of attestors binds to a client, and the keys an attestor signs with.
An attestor reads one chain and signs a statement about the chain’s state at a certain height upon request. The attestor is stateless: it keeps no store of its own, and it reads the chain through an RPC endpoint it trusts to report accurate state.The light client needs those signatures because it stores no commitment root. Every claim it accepts has to arrive signed by its attestor keys. A set of attestors watches one chain, and the client that trusts that set lives on the other.Attestation is pull-based. An attestor signs when a relayer asks, and the relayer aggregates the signatures it gathers into one proof.
An attestor signs exactly two kinds of claim, both about a single height:
A state attestation binds a height to that block’s timestamp.
A packet attestation binds a height to a list of packet paths in the router store and their commitments, where a zero commitment asserts the path is empty.
Below is an example of a packet attestation:
// The claim: packet 1 on client-0 is committed at height 1337.PacketAttestation { height: 1337, packets: [ PacketCompact { // keccak256 of the store path: client id, a record-type byte, then the 8-byte sequence path: keccak256(hex"636c69656e742d30010000000000000001"), commitment: 0xb691a1950f6fb0bbbcf4bdb16fe2c4d0aa7ef783eb7803073f475cb8164d9b7a } ]}
A state attestation carries only the height and that block’s timestamp:
One attestor returns the encoded claim, the height it applies to, and a single signature, plus the block timestamp when the claim carries one. The relayer collects those answers and submits the encoded claim once, with the signatures alongside it:
AttestationProof { attestationData: abi.encode(PacketAttestation), signatures: [ /* 65 bytes each, r || s || v, threshold many required */ ]}
Each signature covers sha256(tag || sha256(attestationData)), where the tag is 0x01 for a state attestation and 0x02 for a packet attestation.Before signing, an attestor checks each claim against its own view of the chain. It refuses any height above its attestable height, which is set by a finality offset. For a packet attestation it recomputes each path and reads the value on chain: a packet commitment must exist and match, an acknowledgement must exist, and a receipt must be absent. One failing packet in a batch produces no attestation at all.
Configured per attestor, the finality offset decides how far behind the chain head it will sign. It sets the attestable height, and a request above that height is refused rather than answered:
An offset of zero attests up to the chain’s own finalized block. Omitting the field is the same input as writing 0.
A positive offset of n attests up to latest minus n blocks.
A positive offset matters where a chain’s finalized tag lags far behind its head. On Ethereum proof of stake the tag runs roughly 12 to 15 minutes behind, and an offset of zero makes every relay wait out that lag.
Do not set the offset shallower than the chain’s practical finality. A reorg can make a quorum sign a second timestamp for a height it already signed, and conflicting timestamps at one height freeze the client for good.
An attestor set is the attestor addresses and the signature threshold that a light client accepts proofs from, which makes it the trust root of the connection. A connection has an attestation light client on each of its two chains, and each of those clients has a set of its own.The set itself lives on chain. The relayer’s configuration is a separate list of the attestors it can reach:
On chain, the addresses and threshold are fixed when the client is deployed. The constructor rejects an empty set, a zero threshold, a threshold larger than the set, and duplicate addresses.
Off chain, the relayer’s configuration lists the attestors it can reach, in one flat attestors[] list that ibc attestor run reads as well. A type: local entry is an attestor the process runs itself, naming the chain it watches, a signer, and a finality offset. A type: remote entry carries only a name and a bare host:port. A remote attestor reports its own chain and signing address through an Info RPC when the relayer dials it.
The configuration carries no threshold, and it does not say which client an attestor serves. The relayer resolves both against the chain at startup: it reads each client’s on-chain attestation set for its addresses and its threshold, keeps the configured attestors that watch the counterparty chain and appear in that set, and refuses to start if fewer match than the threshold requires.A deployed set never changes. No function adds, removes, or replaces an attestor, and no path changes the threshold, so a different set means deploying a new client.
Attestor set rotation requires client migration on the router, which replaces the client contract under an existing client ID.
Follow Rotate an attestor set to deploy a replacement client and migrate the existing client ID.
An attestor signs with one ECDSA key per attestor entry, resolved through a named signer. The address of that key is what appears in a client’s set: to the client, the attestor is its key.A key lives in one of two places:
A local keyfile on disk.
A remote signing service that holds the key, reached over gRPC and addressed by a key id.
Use separate keys for independent clients and chains. Signatures are not bound to a chain, router, or verifying client.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"IBC Documentation","description":"Documentation for the Inter-Blockchain Communication protocol, its Go implementation, and the IBC CLI.","colors":{"primary":"#000000","light":"#cccccc","dark":"#0E0E0E"},"logo":{"light":"https://mintcdn.com/ibc-docs/_IzGrVOELf0DsHtq/mintlify/assets/brand/ibc-wordmark-dark.svg?fit=max\u0026auto=format\u0026n=_IzGrVOELf0DsHtq\u0026q=85\u0026s=dd69509f8e278637cefba78620bc6f19","dark":"https://mintcdn.com/ibc-docs/_IzGrVOELf0DsHtq/mintlify/assets/brand/ibc-wordmark.svg?fit=max\u0026auto=format\u0026n=_IzGrVOELf0DsHtq\u0026q=85\u0026s=4332fd7d24e0e9834a0ff6d9b0907db8","href":"/"},"favicon":{"light":"https://mintcdn.com/ibc-docs/_IzGrVOELf0DsHtq/mintlify/assets/brand/ibc-dark.svg?fit=max\u0026auto=format\u0026n=_IzGrVOELf0DsHtq\u0026q=85\u0026s=950310224e31e8dcbbbae521db80542e","dark":"https://mintcdn.com/ibc-docs/_IzGrVOELf0DsHtq/mintlify/assets/brand/ibc.svg?fit=max\u0026auto=format\u0026n=_IzGrVOELf0DsHtq\u0026q=85\u0026s=8846e23ba7502345c1b7016d0ec9315d"},"navbar":{"primary":{"type":"button","label":"Get started","href":"/ibc/05-ibc-cli/02-tutorial/01-deploy-ibc-and-send-a-token"}},"footer":{"socials":{"x":"https://twitter.com/cosmos","github":"https://github.com/cosmos","discord":"https://discord.gg/interchain","website":"https://cosmos.network"},"links":[{"header":"Documentation","items":[{"label":"Learn how IBC works","href":"/ibc/01-introduction/01-what-is-ibc"},{"label":"IBC CLI","href":"/ibc/05-ibc-cli/01-overview"},{"label":"IBC-Solidity","href":"/ibc/06-ibc-solidity-contracts/01-overview"},{"label":"IBC-Go","href":"/ibc-go/latest/intro"},{"label":"Specification","href":"/ibc/spec/ics-001-ics-standard/README"}]},{"header":"Repositories","items":[{"label":"cosmos/ibc","href":"https://github.com/cosmos/ibc"},{"label":"cosmos/ibc-go","href":"https://github.com/cosmos/ibc-go"},{"label":"cosmos/ibc-contracts","href":"https://github.com/cosmos/ibc-contracts"}]},{"header":"Security","items":[{"label":"Security audits","href":"/ibc/07-security/01-audits"},{"label":"Bug Bounty","href":"https://immunefi.com/bug-bounty/cosmos/information"}]}]},"icons":{"library":"lucide"},"styling":{"codeblocks":{"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}},"latex":false},"contextual":{"options":["copy","view","chatgpt","claude","perplexity","mcp","cursor","vscode"],"display":"header"},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"ibc-docs","hasAudioNarration":false,"actualSubdomain":"ibc-docs","customDomains":[],"gitSource":{"type":"github","owner":"cosmos","repo":"ibc","deployBranch":"main","contentDirectory":"docs","isPrivate":false,"mountPath":"","label":"","_id":"6ae38e8fd265945f8832a739"},"chroma":{"latestBuiltDeploymentHistoryId":"6ae38f56d265945f8832b6ee","collectionId":"e8081330-a92e-4d86-a023-d2707473bf51","liveDeploymentHistoryId":"6ae38f56d265945f8832b6ee","schemaVersion":"v3"},"entitlements":{},"buildId":"6ae393af0b369713606c9b5e","clientVersion":"0.0.4021","searchFilterCounts":[{"language":"default","tag":"Getting Started","count":2}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"/docs","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"per-site-search-delta","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-private-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"mintlify/style.css","content":"/* cyrillic-ext */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bh0NSDulI.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bh2dSDulI.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek-ext */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bh0dSDulI.woff2) format('woff2');\n unicode-range: U+1F00-1FFF;\n}\n/* greek */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bh3tSDulI.woff2) format('woff2');\n unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;\n}\n/* symbols2 */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bhZ_Wmh2uX.woff2) format('woff2');\n unicode-range: U+2000-2001, U+2004-2008, U+200A, U+23B8-23BD, U+2500-259F;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bh09SDulI.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bh3dSD.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bh0NSDulI.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bh2dSDulI.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek-ext */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bh0dSDulI.woff2) format('woff2');\n unicode-range: U+1F00-1FFF;\n}\n/* greek */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bh3tSDulI.woff2) format('woff2');\n unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;\n}\n/* symbols2 */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bhZ_Wmh2uX.woff2) format('woff2');\n unicode-range: U+2000-2001, U+2004-2008, U+200A, U+23B8-23BD, U+2500-259F;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bh09SDulI.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Fira Code';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/docs/_mintlify/assets/fonts/google/s/firacode/v27/uU9NCBsR6Z2vfE9aq3bh3dSD.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n:root{--background-light:255 255 255}.bg-primary\\/10,.dark .bg-primary\\/10,.dark\\:bg-primary-light\\/10:is(.dark *){background-color:var(--nav-accent, #40b3ff)}.bg-primary\\/10 .text-primary,.bg-primary\\/10.text-primary,.dark\\:bg-primary-light\\/10:is(.dark *),.dark\\:bg-primary-light\\/10:is(.dark *) .text-primary,.dark\\:bg-primary-light\\/10:is(.dark *).dark\\:text-primary-light{color:var(--nav-accent-ink, #0e0e0e)}@font-face{font-family:'The Future';src:url(/mintlify/assets/fonts/the-future-regular.woff2) format('woff2');font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:'The Future';src:url(/mintlify/assets/fonts/the-future-medium.woff2) format('woff2');font-weight:500;font-style:normal;font-display:swap}@font-face{font-family:'The Future';src:url(/mintlify/assets/fonts/the-future-bold.woff2) format('woff2');font-weight:700;font-style:normal;font-display:swap}@font-face{font-family:'The Future';src:url(/mintlify/assets/fonts/the-future-light.woff2) format('woff2');font-weight:300;font-style:normal;font-display:swap}body:has(#custom-index-content) #header,body:has(#custom-index-content) #navbar,body:has(#custom-index-content) #search-bar-entry,body:has(#custom-index-content) #search-bar-entry-mobile,body:has(#custom-index-content) .chat-assistant-floating-input,body:has(#custom-index-content) :has(>.chat-assistant-floating-input),body:has(#custom-index-content) button#search-bar-entry,body:has(#custom-index-content) button#search-bar-entry-mobile,body:has(#custom-index-content) header,body:has(#custom-index-content) nav[aria-label]{display:none!important;visibility:hidden!important;opacity:0!important;width:0!important;height:0!important;position:absolute!important;left:-99999px!important;pointer-events:none!important}body:has(#custom-index-content) #custom-index-content,body:has(#custom-index-content) #custom-index-content a,body:has(#custom-index-content) #custom-index-content h1,body:has(#custom-index-content) #custom-index-content h2,body:has(#custom-index-content) #custom-index-content h3,body:has(#custom-index-content) #custom-index-content p{font-family:'The Future',sans-serif}@media (max-width:768px){button[aria-label=\"More actions\"]{display:none!important}#custom-index-content{margin-top:-120px}}@media (min-width:769px) and (max-width:1023px){#custom-index-content{margin-top:-120px}}.prose .callout a,.prose .info a,.prose .note a,.prose .step a,.prose .steps a,.prose .tip a,.prose .warning a,.prose [role=listitem] a,.prose div[data-callout-type] a,.prose li a,.prose p a,.prose span a,.prose ul a{border-bottom-color:#0e0e0e!important;text-decoration-color:#0e0e0e!important}.dark .prose .callout a,.dark .prose .info a,.dark .prose .note a,.dark .prose .step a,.dark .prose .steps a,.dark .prose .tip a,.dark .prose .warning a,.dark .prose [role=listitem] a,.dark .prose div[data-callout-type] a,.dark .prose li a,.dark .prose p a,.dark .prose span a,.dark .prose ul a{border-bottom-color:#ccc!important;text-decoration-color:#ccc!important}.highlighted-card-bg{background-color:#ffb84d;position:relative;overflow:hidden;transition:box-shadow .3s ease-in-out}.highlighted-card-bg:hover{box-shadow:0 0 30px rgba(255,184,77,.5),0 0 60px rgba(255,184,77,.3),0 10px 40px rgba(255,184,77,.2)}.highlighted-card-bg::before{content:'';position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(45deg,transparent 30%,rgba(255,255,255,.4) 50%,transparent 70%);transform:translateX(-100%) translateY(-100%) rotate(45deg);transition:transform .6s ease-in-out}.highlighted-card-bg:hover::before{transform:translateX(100%) translateY(100%) rotate(45deg)}@layer utilities{body:has(#custom-index-content) #footer{display:flex!important}}code,pre,pre code{font-family:'Fira Code','Cascadia Code','JetBrains Mono',monospace!important}#navbar a>span.absolute.bg-primary-dark,header a>span.absolute.bg-primary-dark{background-color:var(--nav-accent, #40b3ff);transition:background-color 120ms ease}#navbar a:hover>span.absolute.bg-primary-dark,header a:hover>span.absolute.bg-primary-dark{background-color:color-mix(in srgb,var(--nav-accent, #40b3ff) 82%,white);opacity:1}#navbar a:has(>span.absolute.bg-primary-dark),#navbar a:has(>span.absolute.bg-primary-dark) *,header a:has(>span.absolute.bg-primary-dark),header a:has(>span.absolute.bg-primary-dark) *{color:var(--nav-accent-ink, #0e0e0e);font-weight:600}.nav-tabs-item{--tab-accent:#40b3ff;--tab-ink:#0e0e0e;transition:color 120ms ease}.nav-tabs-item::before{content:\"\";position:absolute;inset:9px -10px;border-radius:.5rem;background-color:transparent;transition:background-color 120ms ease;z-index:-1}.nav-tabs-item:hover::before{background-color:var(--tab-accent)}.nav-tabs-item:hover,.nav-tabs-item:hover *{color:var(--tab-ink)!important}.nav-tabs-item[href^=\"/ibc/05-ibc-cli/\"]{--tab-accent:#22e2a8;--tab-ink:#0e0e0e}.nav-tabs-item[href^=\"/ibc/06-ibc-solidity-contracts/\"]{--tab-accent:#7522b5;--tab-ink:#ffffff}.nav-tabs-item[href^=\"/ibc-go/\"]{--tab-accent:#4b47ca;--tab-ink:#ffffff}.nav-tabs-item[href^=\"/ibc/spec/\"]{--tab-accent:#ef5628;--tab-ink:#0e0e0e}img.nav-logo{height:3rem}"}],"page":{"pagePath":"ibc/04-light-clients/02-attestors","slug":"/ibc/04-light-clients/02-attestors","pageMetadata":{"title":"Attestors","description":"An attestor is a stateless off-chain service that signs statements about one chain's state, and an attestation light client trusts exactly the keys that sign.","href":"/ibc/04-light-clients/02-attestors"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"An attestor is a stateless off-chain service that signs statements about one chain’s state, and an attestation light client trusts exactly the keys that sign.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,em:`em`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,OptimizedImage,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!OptimizedImage)_missingMdxReference(`OptimizedImage`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`An attestor is an off-chain service that answers questions about one chain’s state with a signature. The `,_jsx(_components.a,{href:`/ibc/04-light-clients/01-attestation-light-client`,children:`attestation light client`}),` accepts a claim only when enough of its attestors have signed it, which makes a connection’s security exactly the keys that sign.`]}),`\n`,_jsx(_components.p,{children:`This page covers what an attestor reads and signs, the finality offset that bounds its answers, how a set of attestors binds to a client, and the keys an attestor signs with.`}),`\n`,_jsx(Heading,{level:`2`,id:`how-an-attestor-works`,children:`How an attestor works`}),`\n`,_jsx(_components.p,{children:`An attestor reads one chain and signs a statement about the chain’s state at a certain height upon request. The attestor is stateless: it keeps no store of its own, and it reads the chain through an RPC endpoint it trusts to report accurate state.`}),`\n`,_jsx(_components.p,{children:`The light client needs those signatures because it stores no commitment root. Every claim it accepts has to arrive signed by its attestor keys. A set of attestors watches one chain, and the client that trusts that set lives on the other.`}),`\n`,_jsx(_components.p,{children:`Attestation is pull-based. An attestor signs when a relayer asks, and the relayer aggregates the signatures it gathers into one proof.`}),`\n`,_jsx(OptimizedImage,{src:`https://mintcdn.com/ibc-docs/_IzGrVOELf0DsHtq/mintlify/images/ibc/ibc-attestors.png?fit=max\u0026auto=format\u0026n=_IzGrVOELf0DsHtq\u0026q=85\u0026s=ee2571bc6c8a76c0126120536d7beed2`,alt:`Relayer asking attestors for signed claims and submitting the proof`,\"data-path\":`mintlify/images/ibc/ibc-attestors.png`}),`\n`,_jsx(Heading,{level:`2`,id:`what-an-attestor-signs`,children:`What an attestor signs`}),`\n`,_jsx(_components.p,{children:`An attestor signs exactly two kinds of claim, both about a single height:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`A state attestation`}),` binds a height to that block’s timestamp.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`A packet attestation`}),` binds a height to a list of packet paths in the router store and their commitments, where a zero commitment asserts the path is empty.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`Below is an example of a packet attestation:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`11`,language:`solidity`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-high-contrast github-dark-high-contrast`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0a0c10`,color:`#0e1116`,\"--shiki-dark\":`#f0f3f6`},language:`solidity`,children:_jsxs(_components.code,{language:`solidity`,numberOfLines:`11`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#66707B`,\"--shiki-dark\":`#BDC4CC`},children:`// The claim: packet 1 on client-0 is committed at height 1337.`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:`PacketAttestation {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` height`}),_jsx(_components.span,{style:{color:`#A0111F`,\"--shiki-dark\":`#FF9492`},children:`:`}),_jsx(_components.span,{style:{color:`#023B95`,\"--shiki-dark\":`#91CBFF`},children:` 1337`}),_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` packets`}),_jsx(_components.span,{style:{color:`#A0111F`,\"--shiki-dark\":`#FF9492`},children:`:`}),_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` [`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` PacketCompact {`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#66707B`,\"--shiki-dark\":`#BDC4CC`},children:` // keccak256 of the store path: client id, a record-type byte, then the 8-byte sequence`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` path`}),_jsx(_components.span,{style:{color:`#A0111F`,\"--shiki-dark\":`#FF9492`},children:`:`}),_jsx(_components.span,{style:{color:`#023B95`,\"--shiki-dark\":`#91CBFF`},children:` keccak256`}),_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:`(hex`}),_jsx(_components.span,{style:{color:`#032563`,\"--shiki-dark\":`#ADDCFF`},children:`\"636c69656e742d30010000000000000001\"`}),_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:`),`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` commitment`}),_jsx(_components.span,{style:{color:`#A0111F`,\"--shiki-dark\":`#FF9492`},children:`:`}),_jsx(_components.span,{style:{color:`#023B95`,\"--shiki-dark\":`#91CBFF`},children:` 0xb691a1950f6fb0bbbcf4bdb16fe2c4d0aa7ef783eb7803073f475cb8164d9b7a`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` ]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:`}`})}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`A state attestation carries only the height and that block’s timestamp:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`solidity`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-high-contrast github-dark-high-contrast`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0a0c10`,color:`#0e1116`,\"--shiki-dark\":`#f0f3f6`},language:`solidity`,children:_jsxs(_components.code,{language:`solidity`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:`StateAttestation { height`}),_jsx(_components.span,{style:{color:`#A0111F`,\"--shiki-dark\":`#FF9492`},children:`:`}),_jsx(_components.span,{style:{color:`#023B95`,\"--shiki-dark\":`#91CBFF`},children:` 1337`}),_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:`, timestamp`}),_jsx(_components.span,{style:{color:`#A0111F`,\"--shiki-dark\":`#FF9492`},children:`:`}),_jsx(_components.span,{style:{color:`#023B95`,\"--shiki-dark\":`#91CBFF`},children:` 1754400000`}),_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` }`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`One attestor returns the encoded claim, the height it applies to, and a single signature, plus the block timestamp when the claim carries one. The relayer collects those answers and submits the encoded claim once, with the signatures alongside it:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`solidity`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-high-contrast github-dark-high-contrast`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0a0c10`,color:`#0e1116`,\"--shiki-dark\":`#f0f3f6`},language:`solidity`,children:_jsxs(_components.code,{language:`solidity`,numberOfLines:`4`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:`AttestationProof {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` attestationData`}),_jsx(_components.span,{style:{color:`#A0111F`,\"--shiki-dark\":`#FF9492`},children:`:`}),_jsx(_components.span,{style:{color:`#023B95`,\"--shiki-dark\":`#91CBFF`},children:` abi`}),_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:`.`}),_jsx(_components.span,{style:{color:`#622CBC`,\"--shiki-dark\":`#DBB7FF`},children:`encode`}),_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:`(PacketAttestation),`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` signatures`}),_jsx(_components.span,{style:{color:`#A0111F`,\"--shiki-dark\":`#FF9492`},children:`:`}),_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` [ `}),_jsx(_components.span,{style:{color:`#66707B`,\"--shiki-dark\":`#BDC4CC`},children:`/* 65 bytes each, r || s || v, threshold many required */`}),_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:` ]`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0E1116`,\"--shiki-dark\":`#F0F3F6`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Each signature covers `,_jsx(_components.code,{children:`sha256(tag || sha256(attestationData))`}),`, where the tag is `,_jsx(_components.code,{children:`0x01`}),` for a state attestation and `,_jsx(_components.code,{children:`0x02`}),` for a packet attestation.`]}),`\n`,_jsx(_components.p,{children:`Before signing, an attestor checks each claim against its own view of the chain. It refuses any height above its attestable height, which is set by a finality offset. For a packet attestation it recomputes each path and reads the value on chain: a packet commitment must exist and match, an acknowledgement must exist, and a receipt must be absent. One failing packet in a batch produces no attestation at all.`}),`\n`,_jsx(Heading,{level:`2`,id:`the-finality-offset`,children:`The finality offset`}),`\n`,_jsx(_components.p,{children:`Configured per attestor, the finality offset decides how far behind the chain head it will sign. It sets the attestable height, and a request above that height is refused rather than answered:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`An offset of zero attests up to the chain’s own `,_jsx(_components.code,{children:`finalized`}),` block. Omitting the field is the same input as writing `,_jsx(_components.code,{children:`0`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`A positive offset of `,_jsx(_components.em,{children:`n`}),` attests up to `,_jsx(_components.code,{children:`latest`}),` minus `,_jsx(_components.em,{children:`n`}),` blocks.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`A positive offset matters where a chain’s `,_jsx(_components.code,{children:`finalized`}),` tag lags far behind its head. On Ethereum proof of stake the tag runs roughly 12 to 15 minutes behind, and an offset of zero makes every relay wait out that lag.`]}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`Do not set the offset shallower than the chain’s practical finality. A reorg can make a quorum sign a second timestamp for a height it already signed, and conflicting timestamps at one height freeze the client for good.`})}),`\n`,_jsx(Heading,{level:`2`,id:`the-attestor-set`,children:`The attestor set`}),`\n`,_jsx(_components.p,{children:`An attestor set is the attestor addresses and the signature threshold that a light client accepts proofs from, which makes it the trust root of the connection. A connection has an attestation light client on each of its two chains, and each of those clients has a set of its own.`}),`\n`,_jsx(_components.p,{children:`The set itself lives on chain. The relayer’s configuration is a separate list of the attestors it can reach:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`On chain`}),`, the addresses and threshold are fixed when the client is deployed. The constructor rejects an empty set, a zero threshold, a threshold larger than the set, and duplicate addresses.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Off chain`}),`, the relayer’s configuration lists the attestors it can reach, in one flat `,_jsx(_components.code,{children:`attestors[]`}),` list that `,_jsx(_components.code,{children:`ibc attestor run`}),` reads as well. A `,_jsx(_components.code,{children:`type: local`}),` entry is an attestor the process runs itself, naming the chain it watches, a signer, and a finality offset. A `,_jsx(_components.code,{children:`type: remote`}),` entry carries only a name and a bare `,_jsx(_components.code,{children:`host:port`}),`. A remote attestor reports its own chain and signing address through an `,_jsx(_components.code,{children:`Info`}),` RPC when the relayer dials it.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`The configuration carries no threshold, and it does not say which client an attestor serves. The relayer resolves both against the chain at startup: it reads each client’s on-chain attestation set for its addresses and its threshold, keeps the configured attestors that watch the counterparty chain and appear in that set, and refuses to start if fewer match than the threshold requires.`}),`\n`,_jsx(_components.p,{children:`A deployed set never changes. No function adds, removes, or replaces an attestor, and no path changes the threshold, so a different set means deploying a new client.`}),`\n`,_jsx(Heading,{level:`2`,id:`rotating-attestors`,children:`Rotating attestors`}),`\n`,_jsxs(_components.p,{children:[`Attestor set rotation requires client migration on the router, which replaces the client contract under an existing client ID.\nFollow `,_jsx(_components.a,{href:`/ibc/05-ibc-cli/03-guides/06-rotate-an-attestor-set`,children:`Rotate an attestor set`}),` to deploy a replacement client and migrate the existing client ID.`]}),`\n`,_jsx(Heading,{level:`2`,id:`attestor-keys`,children:`Attestor keys`}),`\n`,_jsx(_components.p,{children:`An attestor signs with one ECDSA key per attestor entry, resolved through a named signer. The address of that key is what appears in a client’s set: to the client, the attestor is its key.`}),`\n`,_jsx(_components.p,{children:`A key lives in one of two places:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`A local keyfile on disk.`}),`\n`,_jsx(_components.li,{children:`A remote signing service that holds the key, reached over gRPC and addressed by a key id.`}),`\n`]}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`Use separate keys for independent clients and chains. Signatures are not bound to a chain, router, or verifying client.`})}),`\n`,_jsxs(_components.p,{children:[`Follow the `,_jsx(_components.a,{href:`/ibc/05-ibc-cli/03-guides/01-run-a-standalone-attestor`,children:`Run a standalone attestor`}),` guide to learn how to run one for yourself.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"codeStyling":{"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}},"config":{},"pageMetadata":{"title":"Attestors","description":"An attestor is a stateless off-chain service that signs statements about one chain's state, and an attestation light client trusts exactly the keys that sign.","href":"/ibc/04-light-clients/02-attestors"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"How an attestor works","slug":"how-an-attestor-works","depth":2,"children":[]},{"title":"What an attestor signs","slug":"what-an-attestor-signs","depth":2,"children":[]},{"title":"The finality offset","slug":"the-finality-offset","depth":2,"children":[]},{"title":"The attestor set","slug":"the-attestor-set","depth":2,"children":[]},{"title":"Rotating attestors","slug":"rotating-attestors","depth":2,"children":[]},{"title":"Attestor keys","slug":"attestor-keys","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":["/docs/_mintlify/custom/ibc-docs/1efa1b9f25769b22/custom.js"],"subdomain":"ibc-docs","siteName":"IBC Documentation","title":"Attestors - IBC Documentation","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-29T18:43:11.603Z","originalFileLocation":"ibc/04-light-clients/02-attestors.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"An attestor is a stateless off-chain service that signs statements about one chain\u0026#x27;s state, and an attestation light client trusts exactly the keys that sign.\">\u003cmeta data-mint-head name=\"application-name\" content=\"IBC Documentation\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/ibc-docs/M8QbcV1CzT5u-Qmv/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/docs/mintlify-assets/_mintlify/favicons/ibc-docs/M8QbcV1CzT5u-Qmv/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/ibc-docs/M8QbcV1CzT5u-Qmv/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/ibc-docs/M8QbcV1CzT5u-Qmv/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/ibc-docs/M8QbcV1CzT5u-Qmv/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/ibc-docs/M8QbcV1CzT5u-Qmv/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/ibc-docs/M8QbcV1CzT5u-Qmv/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/ibc-docs/M8QbcV1CzT5u-Qmv/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/ibc-docs/M8QbcV1CzT5u-Qmv/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Attestors - IBC Documentation\">\u003cmeta data-mint-head property=\"og:description\" content=\"An attestor is a stateless off-chain service that signs statements about one chain\u0026#x27;s state, and an attestation light client trusts exactly the keys that sign.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"IBC Documentation\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://ibc-docs.mintlify.dev/docs/ibc/04-light-clients/02-attestors\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://ibc-docs.mintlify.app/_mintlify/api/og/v2?division=Light+clients\u0026amp;title=Attestors\u0026amp;description=An+attestor+is+a+stateless+off-chain+service+that+signs+statements+about+one+chain%27s+state%2C+and+an+attestation+light+client+trusts+exactly+the+keys+that+sign.\u0026amp;theme=83cf7571a86e66a217192c59\u0026amp;signature=a0efe508bd147fed41c080994ab90e3d158b97a65607eb231ea393d6ba70f185\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Attestors - IBC Documentation\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"An attestor is a stateless off-chain service that signs statements about one chain\u0026#x27;s state, and an attestation light client trusts exactly the keys that sign.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://ibc-docs.mintlify.app/_mintlify/api/og/v2?division=Light+clients\u0026amp;title=Attestors\u0026amp;description=An+attestor+is+a+stateless+off-chain+service+that+signs+statements+about+one+chain%27s+state%2C+and+an+attestation+light+client+trusts+exactly+the+keys+that+sign.\u0026amp;theme=83cf7571a86e66a217192c59\u0026amp;signature=a0efe508bd147fed41c080994ab90e3d158b97a65607eb231ea393d6ba70f185\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/docs/mintlify-assets/_mintlify/favicons/ibc-docs/M8QbcV1CzT5u-Qmv/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"IBC Documentation\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#000000\">\u003clink data-mint-head rel=\"canonical\" href=\"https://ibc-docs.mintlify.dev/docs/ibc/04-light-clients/02-attestors\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/docs/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/docs/ibc/04-light-clients/02-attestors.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://ibc-docs.mintlify.dev/#organization\",\"name\":\"IBC Documentation\",\"url\":\"https://ibc-docs.mintlify.dev\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/ibc-docs/_IzGrVOELf0DsHtq/mintlify/assets/brand/ibc-wordmark-dark.svg?fit=max\u0026auto=format\u0026n=_IzGrVOELf0DsHtq\u0026q=85\u0026s=dd69509f8e278637cefba78620bc6f19\"}},{\"@type\":\"WebSite\",\"@id\":\"https://ibc-docs.mintlify.dev/docs#website\",\"name\":\"IBC Documentation\",\"url\":\"https://ibc-docs.mintlify.dev/docs\",\"publisher\":{\"@id\":\"https://ibc-docs.mintlify.dev/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://ibc-docs.mintlify.dev/docs/ibc/04-light-clients/02-attestors#webpage\",\"url\":\"https://ibc-docs.mintlify.dev/docs/ibc/04-light-clients/02-attestors\",\"name\":\"Attestors\",\"description\":\"An attestor is a stateless off-chain service that signs statements about one chain's state, and an attestation light client trusts exactly the keys that sign.\",\"dateModified\":\"2026-10-29T18:43:11.603Z\",\"isPartOf\":{\"@id\":\"https://ibc-docs.mintlify.dev/docs#website\"},\"breadcrumb\":{\"@id\":\"https://ibc-docs.mintlify.dev/docs/ibc/04-light-clients/02-attestors#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://ibc-docs.mintlify.dev/docs/ibc/04-light-clients/02-attestors#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Light clients\",\"item\":\"https://ibc-docs.mintlify.dev/docs/ibc/04-light-clients/01-attestation-light-client\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Attestors\",\"item\":\"https://ibc-docs.mintlify.dev/docs/ibc/04-light-clients/02-attestors\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://ibc-docs.mintlify.dev/docs/ibc/04-light-clients/02-attestors#article\",\"headline\":\"Attestors\",\"name\":\"Attestors\",\"description\":\"An attestor is a stateless off-chain service that signs statements about one chain's state, and an attestation light client trusts exactly the keys that sign.\",\"url\":\"https://ibc-docs.mintlify.dev/docs/ibc/04-light-clients/02-attestors\",\"mainEntityOfPage\":{\"@id\":\"https://ibc-docs.mintlify.dev/docs/ibc/04-light-clients/02-attestors#webpage\"},\"dateModified\":\"2026-10-29T18:43:11.603Z\",\"publisher\":{\"@id\":\"https://ibc-docs.mintlify.dev/#organization\"},\"isPartOf\":{\"@id\":\"https://ibc-docs.mintlify.dev/docs#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"IBC Documentation\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"IBC Documentation","nav":{"global":null,"tabs":[{"tab":"Learn","groups":[{"group":"Introduction","icon":"book-open","pages":[{"title":"IBC","sidebarTitle":"Home","href":""},{"title":"What is IBC?","href":"/ibc/01-introduction/01-what-is-ibc"}]},{"group":"How IBC works","icon":"workflow","pages":[{"title":"IBC overview","href":"/ibc/02-how-ibc-works/01-overview"},{"title":"Packets and applications","href":"/ibc/02-how-ibc-works/02-packets-and-applications"},{"title":"Core: router and store","href":"/ibc/02-how-ibc-works/03-core-router-and-store"},{"title":"Clients and counterparties","href":"/ibc/02-how-ibc-works/04-clients-and-counterparties"},{"title":"Relayer","href":"/ibc/02-how-ibc-works/05-relayer"},{"title":"Packet lifecycle","href":"/ibc/02-how-ibc-works/06-packet-lifecycle"}]},{"group":"Applications","icon":"blocks","pages":[{"title":"GMP: how it works","href":"/ibc/03-applications/01-gmp"},{"title":"IFT: how it works","href":"/ibc/03-applications/02-ift"}]},{"group":"Light clients","icon":"shield-check","pages":[{"title":"The attestation light client","description":"The attestation light client accepts a claim about the counterparty chain once a quorum of a fixed attestor set has signed it.","href":"/ibc/04-light-clients/01-attestation-light-client"},{"title":"Attestors","href":"/ibc/04-light-clients/02-attestors"},{"title":"The Besu QBFT and IBFT 2.0 light client","description":"The Besu light client verifies sealed Besu headers and Ethereum storage proofs, so a connection between two Besu QBFT or IBFT 2.0 chains needs no attestors.","href":"/ibc/04-light-clients/03-besu-light-client"}]},{"group":"Security","icon":"lock","pages":[{"title":"Security audits","href":"/ibc/07-security/01-audits"}]},{"group":"Repositories","icon":"folder-git-2","pages":[{"title":"cosmos/ibc","url":"https://github.com/cosmos/ibc","icon":"github","href":"/ibc/repos/learn-ibc"},{"title":"cosmos/ibc-go","url":"https://github.com/cosmos/ibc-go","icon":"github","href":"/ibc/repos/learn-ibc-go"},{"title":"cosmos/ibc-contracts","url":"https://github.com/cosmos/ibc-contracts","icon":"github","href":"/ibc/repos/learn-ibc-contracts"}]}]},{"tab":"IBC CLI","pages":[{"title":"IBC CLI","href":"/ibc/05-ibc-cli/01-overview"}]},{"tab":"IBC-Solidity","pages":[{"title":"IBC-Solidity","href":"/ibc/06-ibc-solidity-contracts/01-overview"}]},{"tab":"IBC-Go","versions":[{"version":"latest","groups":[{"group":"Introduction","icon":"book-open","pages":[{"title":"IBC Documentation","href":"/ibc-go/latest/intro"}]},{"group":"IBC Core","icon":"box","pages":[{"title":"Overview","href":"/ibc-go/latest/ibc/overview"},{"group":"Core Concepts","icon":"lightbulb","pages":[{"title":"Best Practices","href":"/ibc-go/latest/ibc/best-practices"},{"title":"Integration","href":"/ibc-go/latest/ibc/integration"},{"title":"Permissioning","href":"/ibc-go/latest/ibc/permissioning"},{"title":"Relayer","href":"/ibc-go/latest/ibc/relayer"}]},{"group":"Apps","icon":"app-window","pages":[{"title":"IBC v2 Applications","href":"/ibc-go/latest/ibc/apps/ibcv2apps"},{"title":"IBC Applications","href":"/ibc-go/latest/ibc/apps/apps"},{"title":"Implement IBCModule interface and callbacks","href":"/ibc-go/latest/ibc/apps/ibcmodule"},{"title":"Bind ports","href":"/ibc-go/latest/ibc/apps/bindports"},{"title":"Keeper","href":"/ibc-go/latest/ibc/apps/keeper"},{"title":"Define packets and acks","href":"/ibc-go/latest/ibc/apps/packets_acks"},{"title":"Routing","href":"/ibc-go/latest/ibc/apps/routing"},{"title":"Custom Address Codec","href":"/ibc-go/latest/ibc/apps/address-codec"}]},{"group":"Middleware","icon":"layers","pages":[{"title":"IBC middleware","href":"/ibc-go/latest/ibc/middleware/overview"},{"title":"Create a custom IBC middleware","href":"/ibc-go/latest/ibc/middleware/develop"},{"title":"Create and integrate IBC v2 middleware","href":"/ibc-go/latest/ibc/middleware/developIBCv2"},{"title":"Integrating IBC middleware into a chain","href":"/ibc-go/latest/ibc/middleware/integration"}]},{"group":"Upgrades","icon":"arrow-up","pages":[{"title":"Upgrading IBC Chains Overview","href":"/ibc-go/latest/ibc/upgrades/intro"},{"title":"How to Upgrade IBC Chains and their Clients","href":"/ibc-go/latest/ibc/upgrades/quick-guide"},{"title":"IBC Client Developer Guide to Upgrades","href":"/ibc-go/latest/ibc/upgrades/developer-guide"},{"title":"Genesis Restart Upgrades","href":"/ibc-go/latest/ibc/upgrades/genesis-restart"}]}]},{"group":"IBC Migrations","icon":"arrow-right-left","pages":[{"group":"Version Upgrades","icon":"git-branch","pages":[{"title":"IBC-Go v11.0 to v11.1","href":"/ibc-go/latest/migrations/v11-to-v11-1"},{"title":"IBC-Go v10 to v11.1","href":"/ibc-go/latest/migrations/v10-to-v11-1"},{"title":"IBC-Go v10 to v11","href":"/ibc-go/latest/migrations/v10-to-v11"},{"title":"IBC-Go v8.1 to v10","href":"/ibc-go/latest/migrations/v8_1-to-v10"},{"title":"IBC-Go v8 to v8.1","href":"/ibc-go/latest/migrations/v8-to-v8_1"},{"title":"IBC-Go v7 to v8","href":"/ibc-go/latest/migrations/v7-to-v8"},{"title":"IBC-Go v7.2 to v7.3","href":"/ibc-go/latest/migrations/v7_2-to-v7_3"},{"title":"IBC-Go v7 to v7.1","href":"/ibc-go/latest/migrations/v7-to-v7_1"},{"title":"IBC-Go v6 to v7","href":"/ibc-go/latest/migrations/v6-to-v7"},{"title":"IBC-Go v5 to v6","href":"/ibc-go/latest/migrations/v5-to-v6"},{"title":"IBC-Go v4 to v5","href":"/ibc-go/latest/migrations/v4-to-v5"},{"title":"IBC-Go v3 to v4","href":"/ibc-go/latest/migrations/v3-to-v4"},{"title":"IBC-Go v2 to v3","href":"/ibc-go/latest/migrations/v2-to-v3"},{"title":"IBC-Go v1 to v2","href":"/ibc-go/latest/migrations/v1-to-v2"}]},{"group":"Additional Migration Guides","icon":"map","pages":[{"title":"SDK v0.43 to IBC-Go v1","href":"/ibc-go/latest/migrations/sdk-to-v1"},{"title":"Support transfer of coins whose base denom contains slashes","href":"/ibc-go/latest/migrations/support-denoms-with-slashes"},{"title":"Support the new StackBuilder primitive for Wiring Middlewares in the chain application","href":"/ibc-go/latest/migrations/support-stackbuilder"}]}]},{"group":"IBC Light Clients","icon":"shield-check","pages":[{"group":"Developer Guide","icon":"code","pages":[{"title":"Overview","href":"/ibc-go/latest/light-clients/developer-guide/overview"},{"title":"Light Client Module interface","href":"/ibc-go/latest/light-clients/developer-guide/light-client-module"},{"title":"Client State interface","href":"/ibc-go/latest/light-clients/developer-guide/client-state"},{"title":"Consensus State interface","href":"/ibc-go/latest/light-clients/developer-guide/consensus-state"},{"title":"Handling Updates and Misbehaviour","href":"/ibc-go/latest/light-clients/developer-guide/updates-and-misbehaviour"},{"title":"Handling Upgrades","href":"/ibc-go/latest/light-clients/developer-guide/upgrades"},{"title":"Existence/Non-Existence Proofs","href":"/ibc-go/latest/light-clients/developer-guide/proofs"},{"title":"Handling Proposals","href":"/ibc-go/latest/light-clients/developer-guide/proposals"},{"title":"Setup","href":"/ibc-go/latest/light-clients/developer-guide/setup"},{"title":"Governance Proposals","href":"/ibc-go/latest/light-clients/proposals"}]},{"group":"Attestation","icon":"badge-check","pages":[{"title":"The attestation light client","href":"/ibc-go/latest/light-clients/attestation/attestation-light-client"}]},{"group":"Localhost","icon":"monitor","pages":[{"title":"Overview","href":"/ibc-go/latest/light-clients/localhost/overview"},{"title":"Integration","href":"/ibc-go/latest/light-clients/localhost/integration"},{"title":"ClientState","href":"/ibc-go/latest/light-clients/localhost/client-state"},{"title":"Connection","href":"/ibc-go/latest/light-clients/localhost/connection"},{"title":"State Verification","href":"/ibc-go/latest/light-clients/localhost/state-verification"}]},{"group":"Solo Machine","icon":"cpu","pages":[{"title":"Solomachine","href":"/ibc-go/latest/light-clients/solomachine/solomachine"},{"title":"Concepts","href":"/ibc-go/latest/light-clients/solomachine/concepts"},{"title":"State","href":"/ibc-go/latest/light-clients/solomachine/state"},{"title":"State Transitions","href":"/ibc-go/latest/light-clients/solomachine/state_transitions"}]},{"group":"Tendermint","icon":"boxes","pages":[{"title":"Overview","href":"/ibc-go/latest/light-clients/tendermint/overview"}]},{"group":"WASM","icon":"binary","pages":[{"title":"Overview","href":"/ibc-go/latest/light-clients/wasm/overview"},{"title":"Concepts","href":"/ibc-go/latest/light-clients/wasm/concepts"},{"title":"Integration","href":"/ibc-go/latest/light-clients/wasm/integration"},{"title":"Messages","href":"/ibc-go/latest/light-clients/wasm/messages"},{"title":"Governance","href":"/ibc-go/latest/light-clients/wasm/governance"},{"title":"Events","href":"/ibc-go/latest/light-clients/wasm/events"},{"title":"Contracts","href":"/ibc-go/latest/light-clients/wasm/contracts"},{"title":"Client","href":"/ibc-go/latest/light-clients/wasm/client"},{"title":"Migrations","href":"/ibc-go/latest/light-clients/wasm/migrations"}]}]},{"group":"IBC Apps","icon":"blocks","pages":[{"title":"General Message Passing (GMP)","href":"/ibc-go/latest/apps/gmp"},{"group":"Interchain Accounts","icon":"users","pages":[{"title":"Overview","href":"/ibc-go/latest/apps/interchain-accounts/overview"},{"title":"Development Use Cases","href":"/ibc-go/latest/apps/interchain-accounts/development"},{"title":"Authentication Modules","href":"/ibc-go/latest/apps/interchain-accounts/auth-modules"},{"title":"Integration","href":"/ibc-go/latest/apps/interchain-accounts/integration"},{"title":"Messages","href":"/ibc-go/latest/apps/interchain-accounts/messages"},{"title":"Parameters","href":"/ibc-go/latest/apps/interchain-accounts/parameters"},{"title":"Transaction Encoding","href":"/ibc-go/latest/apps/interchain-accounts/tx-encoding"},{"title":"Client","href":"/ibc-go/latest/apps/interchain-accounts/client"},{"title":"Active Channels","href":"/ibc-go/latest/apps/interchain-accounts/active-channels"},{"group":"Legacy","icon":"archive","pages":[{"title":"Authentication Modules","href":"/ibc-go/latest/apps/interchain-accounts/legacy/auth-modules"},{"title":"Integration","href":"/ibc-go/latest/apps/interchain-accounts/legacy/integration"},{"title":"Keeper API","href":"/ibc-go/latest/apps/interchain-accounts/legacy/keeper-api"}]}]},{"group":"Transfer","icon":"send","pages":[{"title":"Overview","href":"/ibc-go/latest/apps/transfer/overview"},{"title":"State","href":"/ibc-go/latest/apps/transfer/state"},{"title":"State Transitions","href":"/ibc-go/latest/apps/transfer/state-transitions"},{"title":"Messages","href":"/ibc-go/latest/apps/transfer/messages"},{"title":"Events","href":"/ibc-go/latest/apps/transfer/events"},{"title":"Metrics","href":"/ibc-go/latest/apps/transfer/metrics"},{"title":"Params","href":"/ibc-go/latest/apps/transfer/params"},{"title":"Authorizations","href":"/ibc-go/latest/apps/transfer/authorizations"},{"title":"Client","href":"/ibc-go/latest/apps/transfer/client"},{"title":"IBC v2 Transfer","href":"/ibc-go/latest/apps/transfer/IBCv2-transfer"}]}]},{"group":"IBC Middleware","icon":"layers","pages":[{"group":"Callbacks","icon":"repeat","pages":[{"title":"Overview","href":"/ibc-go/latest/middleware/callbacks/overview"},{"title":"Integration","href":"/ibc-go/latest/middleware/callbacks/integration"},{"title":"Interfaces","href":"/ibc-go/latest/middleware/callbacks/interfaces"},{"title":"Events","href":"/ibc-go/latest/middleware/callbacks/events"},{"title":"End Users","href":"/ibc-go/latest/middleware/callbacks/end-users"},{"title":"Gas Management","href":"/ibc-go/latest/middleware/callbacks/gas"},{"title":"Callbacks with IBC v2","href":"/ibc-go/latest/middleware/callbacks/callbacks-IBCv2"}]},{"group":"Packet Forward Middleware","icon":"forward","pages":[{"title":"Overview","href":"/ibc-go/latest/middleware/packet-forward-middleware/overview"},{"title":"Integration","href":"/ibc-go/latest/middleware/packet-forward-middleware/integration"},{"title":"Example Flows","href":"/ibc-go/latest/middleware/packet-forward-middleware/example-usage"}]},{"group":"Rate Limit Middleware","icon":"gauge","pages":[{"title":"Overview","href":"/ibc-go/latest/middleware/rate-limit-middleware/overview"},{"title":"Integration","href":"/ibc-go/latest/middleware/rate-limit-middleware/integration"},{"title":"Setting Rate Limits","href":"/ibc-go/latest/middleware/rate-limit-middleware/setting-limits"},{"title":"Migration","href":"/ibc-go/latest/middleware/rate-limit-middleware/migration"}]}]},{"group":"Security","icon":"lock","pages":[{"title":"Security Audits","href":"/ibc-go/latest/security-audits"}]},{"group":"Architecture Decision Records","icon":"scroll-text","pages":[{"title":"Architecture Decision Records (ADR)","href":"/ibc-go/latest/architecture/README"},{"title":"ADR 001: Coin Source Tracing","href":"/ibc-go/latest/architecture/adr-001-coin-source-tracing"},{"title":"ADR 002: Go Module Versioning","href":"/ibc-go/latest/architecture/adr-002-go-module-versioning"},{"title":"ADR 003: ICS-27 Acknowledgement Format","href":"/ibc-go/latest/architecture/adr-003-ics27-acknowledgement"},{"title":"ADR 004: Lock Fee Module Upon Escrow Out Of Balance","href":"/ibc-go/latest/architecture/adr-004-ics29-lock-fee-module"},{"title":"ADR 005: UpdateClient Events ClientState Consensus Heights","href":"/ibc-go/latest/architecture/adr-005-consensus-height-events"},{"title":"ADR 006: 02-Client Refactor","href":"/ibc-go/latest/architecture/adr-006-02-client-refactor"},{"title":"ADR 007: Solo Machine Sign Bytes","href":"/ibc-go/latest/architecture/adr-007-solomachine-signbytes"},{"title":"ADR 008: Callback to IBC Actors","href":"/ibc-go/latest/architecture/adr-008-app-caller-cbs"},{"title":"ADR 009: ICS27 Message Server Addition","href":"/ibc-go/latest/architecture/adr-009-v6-ics27-msgserver"},{"title":"ADR 010: IBC Light Clients As SDK Modules","href":"/ibc-go/latest/architecture/adr-010-light-clients-as-sdk-modules"},{"title":"ADR 011: ICS-20 Transfer State Entry For Total Amount Of Tokens In Escrow","href":"/ibc-go/latest/architecture/adr-011-transfer-total-escrow-state-entry"},{"title":"ADR 015: IBC Packet Receiver","href":"/ibc-go/latest/architecture/adr-015-ibc-packet-receiver"},{"title":"ADR 025: IBC Passive Channels","href":"/ibc-go/latest/architecture/adr-025-ibc-passive-channels"},{"title":"ADR 026: IBC Client Recovery Mechanisms","href":"/ibc-go/latest/architecture/adr-026-ibc-client-recovery-mechanisms"},{"title":"ADR 27: Add Support For Wasm Based Light Client","href":"/ibc-go/latest/architecture/adr-027-ibc-wasm"}]},{"group":"Changelog","icon":"rotate-ccw","pages":[{"title":"Changelog","mode":"wide","href":"/ibc-go/latest/changelog/release-notes"}]},{"group":"Repositories","icon":"folder-git-2","pages":[{"title":"cosmos/ibc-go","url":"https://github.com/cosmos/ibc-go","icon":"github","href":"/ibc-go/latest/repos/go-ibc-go"}]}]},{"version":"v10.1.x","pages":[{"title":"v10.1.x","href":"/ibc-go/v10.1.x/intro"}]}]},{"tab":"Specification","pages":[{"title":"Specification","href":"/ibc/spec/ics-001-ics-standard/README"}]}]},"title":"Attestors - IBC Documentation","buildId":"dpl_DGmhKsAzJdVqypJzon18vViniWRY","deploymentId":"dpl_DGmhKsAzJdVqypJzon18vViniWRY","dynamics":["a74be98ba7"],"chunks":["zoom-image-lightbox-B_gjFIjh.js","lightbox-handle-r17bVUz3.js"]}