Ayna sözleşmesini Solidity, TypeScript ve komut satırından okuyun
Ayna, bir hedef zincirde Solidus kimlik belgesi durumunu tutan sözleşmedir. Kimlik belgesi durumu köprüsü nedir sayfası bir durumun oraya nasıl ulaştığını anlatır. Veriyi görmeden bir koşulu denetleyin sayfası onu okuyan bir kapıyı gösterir. Bu sayfa onların altındaki başvurudur: her herkese açık okuma, imzası, Ethereum Sepolia üzerinde gerçek bir çağrı ve o okumanın davet ettiği hata. Her okuma zincir dışında ücretsizdir. Hedef, imzalanan şeyin içindedir sayfası yazma tarafını kapsar.
Görünümlere bir bakış
| görünüm | döndürür | şunun için kullanın |
|---|---|---|
latestExport(gateKey) |
bir aktarım kimliği ya da sıfırlar | bir sahip, tür ve veren için güncel aktarımı bulmak |
exportOf(exportId) |
bir ExportRecord |
tek bir aktarımın durumunu ve son kullanma zamanını okumak |
issuerAccredited(issuerDidHash) |
bir bool | veren bayrağını denetlemek |
lastHeartbeat() |
bir HeartbeatRecord |
köprünün hâlâ canlı olup olmadığını anlamak |
nextDomainSeq() |
bir uint64 |
aynanın bir sonraki kabul ettiği sıra numarasını görmek |
threshold() |
bir uint8 |
bir mesajın kaç doğrulayıcı imzasına ihtiyacı olduğunu görmek |
validators() |
bir address[] |
imzalayanları listelemek |
localDomain() |
bir uint32 |
hangi zinciri okuduğunuzu doğrulamak |
solidusChainId() |
bir uint64 |
imzaların bağlandığı Solidus zincir kimliğini okumak |
mirrorOf(domain), kayıt defterinde |
bir adres | bir alan için ayna sözleşmesini bulmak |
İmzalar, aynanın Solidity arayüzlerinden gelir:
struct ExportRecord {
bytes32 issuerDidHash;
bytes32 credentialTypeHash;
bytes32 holder;
uint8 status;
uint64 validUntil;
uint64 solidusHeight;
}
struct HeartbeatRecord {
uint64 solidusTimestamp;
uint64 solidusHeight;
bytes32 globalRoot;
}
function solidusChainId() external view returns (uint64);
function localDomain() external view returns (uint32);
function nextDomainSeq() external view returns (uint64);
function exportOf(bytes32 exportId) external view returns (ExportRecord memory);
function latestExport(bytes32 gateKey) external view returns (bytes32 exportId);
function issuerAccredited(bytes32 issuerDidHash) external view returns (bool);
function lastHeartbeat() external view returns (HeartbeatRecord memory);
function validators() external view returns (address[] memory);
function threshold() external view returns (uint8);
function mirrorOf(uint32 solidusDomain) external view returns (address);
Bir kez kurun
ROUTES=$(curl -sL https://bridge.solidus.network/v1/routes)
MIRROR=$(echo "$ROUTES" | jq -r '.chains[] | select(.key=="sepolia") | .contracts.mirror')
REGISTRY=$(echo "$ROUTES" | jq -r '.chains[] | select(.key=="sepolia") | .contracts.registry')
RPC=https://rpc.solidus.network/bridge/11155111
c() { cast call "$@" --rpc-url $RPC --nonce 0; }
RPC adresi, tek bir hedef alan için bir JSON-RPC vekilidir. Foundry'nin cast 1.7.1 sürümü vekilin reddettiği bir istek gönderdi (eth_getTransactionCount is not proxied), bu yüzden yardımcı işlev --nonce 0 geçirir. cast ayrıca büyük değerlerin ardından köşeli parantez içinde yuvarlanmış bir sayı basar. Aşağıdaki her çıktı 2026-10-08 tarihinde, 16:50 ile 16:57 UTC arasında çalıştırıldı.
Arama anahtarı
latestExport bir sahip değil, bir kapı anahtarı alır. Anahtar, art arda, ayraç olmadan ve şu sırayla paketlenmiş üç 32 baytlık değerin keccak256 hash'idir: sahip anahtarı, belge türü hash'i, veren hash'i. Belge türü hash'i, türün adının UTF-8 metni olarak keccak256 değeridir; örneğin KycL2. Veren hash'i, verenin DID'inin UTF-8 metni olarak keccak256 değeridir.
Sahip anahtarı 32 bayttır. Bir EVM adresi 20 bayttır, bu yüzden sola doldurulur: on iki sıfır bayt, sonra adres. Sağdan doldurursanız farklı bir anahtar elde edersiniz. Ayna o zaman, aktarımı olmayan bir sahip için yaptığı gibi sıfırlarla cevap verir; yani hata, eksik bir kimlik belgesi gibi görünür. Solidity'de:
bytes32 holder = bytes32(uint256(uint160(account)));
bytes32 key = keccak256(abi.encodePacked(holder, credentialTypeHash, issuerDidHash));
Görünümler, tek tek
latestExport
Bir anahtar için güncel aktarımın kimliğini, yoksa 32 sıfır bayt döndürür. İşaretçi yalnızca etkin bir aktarıma geçer; bu yüzden eski bir aktarımı iptal etmek, daha yeni belgesi geçerli olan bir sahip için kapıyı kapatmaz. Sıfır olmayan bir kimlik, geçerli demek değildir. Sonra kaydı okuyun. Aşağıdaki çalışılmış örnek onu çağırır.
exportOf
c $MIRROR 'exportOf(bytes32)((bytes32,bytes32,bytes32,uint8,uint64,uint64))' 0x0000000000000000000000000000000000000000000000000000000000000001
# (0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0, 0, 0)
status 1 etkin, 2 iptal edilmiş, 3 süresi dolmuş ya da 4 bağı kaldırılmış anlamına gelir. validUntil Unix saniyesidir ve 0, süresiz demektir. Bilinmeyen bir kimlik geri almaz. Sıfırlar döndürür ve saklanmış bir kaydın durumu hiçbir zaman 0 değildir, bunu test edin. Saklanan durum, validUntil geçtiğinde değişmez. Onu block.timestamp ile kendiniz karşılaştırın.
issuerAccredited
c $MIRROR 'issuerAccredited(bytes32)(bool)' $(cast keccak 'did:example:issuer')
# false
Bayrak, belge türüne göre değil veren başınadır. Herhangi bir kimlik belgesi durum mesajı ya da veren durum mesajı onu ayarlayabilir ve en son gelen kazanır. false hem "bu vereni hiç duymadım" hem de "yetkili değil" durumunu kapsar.
lastHeartbeat
c $MIRROR 'lastHeartbeat()((uint64,uint64,bytes32))'
# (1791478392 [1.791e9], 5661264 [5.661e6], 0xebc2a7f366f1b04ac4553f7af879047cfd6646866891d4a3ec0517c424f93423)
solidusTimestamp Solidus saatinde saniyedir ve 1791478392 değeri 16:53:12 UTC eder. Sıfır zaman damgası, ayarlanmamış varsayılandır ve kapı onu bayat olarak bildirir. İki zincir ayrı saat tutar, bu yüzden zaman damgası block.timestamp değerinin ilerisinde olabilir. Solidity'de asla block.timestamp - solidusTimestamp yazmayın. Taşma yapar ve geri alır. Kapı bunun yerine toplar: solidusTimestamp + maxAge < block.timestamp.
nextDomainSeq
c $MIRROR 'nextDomainSeq()(uint64)'
# 1280
Bu, aynanın bir sonraki kabul ettiği sıra numarasıdır. Her türden mesajı, kalp atışları dahil, sayar; bu yüzden kimlik belgesi sayısı değildir. Blok etiketine dikkat edin. Saat 16:55 UTC'de vekil latest için 1280, safe için 1279 ve finalized için 1278 döndürdü.
threshold ve validators
c $MIRROR 'threshold()(uint8)'
# 3
c $MIRROR 'validators()(address[])'
# [0xf6d4f63070cdD3F1e9C1c405b179703c128bfeCa, 0x99a89F2762F2E858df197AD4F24389BFF86ec272, 0xa4E099D7ffc0a840961266B96bCbaAbD5cC30F46, 0xfF01595dE6B8AC7789010559bA52881056411612]
Bir mesajı dört doğrulayıcıdan üçünün imzalaması gerekir. validators() dağıtımda verilen sırayı döndürür, sıralanmış bir sıra değil. Yukarıdaki ilk adres ikincisinden büyüktür. İmzalar imzalayan adresine göre artan sırada sıralanmalıdır, bu yüzden onları kurmadan önce sıralayın. İki değer de değişemez. Yerine geçen, kayıt defterinin arkasında yeni bir aynadır.
localDomain ve solidusChainId
c $MIRROR 'localDomain()(uint32)'
# 11155111 [1.115e7]
c $MIRROR 'solidusChainId()(uint64)'
# 50002 [5e4]
localDomain bu zincirin alanıdır ve Sepolia, Fuji ve Arc'ta zincir kimliğine eşittir. Sepolia, Fuji ve Arc tek bir ayna adresini paylaşır, bu yüzden adres size hiçbir şey söylemez. localDomain söyler. solidusChainId, her imzanın bağlandığı Solidus test ağı zincir kimliğidir.
mirrorOf
c $REGISTRY 'mirrorOf(uint32)(address)' 11155111
# 0x0a5a0d19206f436d67B7b87BF4c889d5b769517A
c $REGISTRY 'mirrorOf(uint32)(address)' 1
# 0x0000000000000000000000000000000000000000
Kayıt defteri bir alanı ayna sözleşmesine eşler. Bilinmeyen bir alan sıfır adresini verir ve kayıt defteri bir alanı başka bir yere yönlendirebilir, bu yüzden aynayı çağrı anında okuyun ve koda gömmeyin.
Çalışılmış örnek: bir kapı anahtarı, bir okuma
Sahip 0x…00a1, tür KycL2 ve veren did:example:issuer örnek DID'idir.
HOLDER=$(cast pad --left --len 32 0x00000000000000000000000000000000000000a1)
TYPE=$(cast keccak KycL2)
ISSUER=$(cast keccak 'did:example:issuer')
KEY=$(cast keccak $(cast concat-hex $HOLDER $TYPE $ISSUER))
echo $KEY
# 0xa37189faccb65a299afc7bed05ce71d25d38af9228a2713230a7124962145440
c $MIRROR 'latestExport(bytes32)(bytes32)' $KEY
# 0x0000000000000000000000000000000000000000000000000000000000000000
Ayna o anahtar altında hiçbir aktarım tutmaz, bu yüzden sıfırlarla cevap verir. Bir kapı bunu 1 numaralı neden, yani aktarım yok olarak bildirir. Sahibi sağdan doldurmak bunun yerine 0x4e2ff44747153e8d41b8d8ff5dc6fa97643e43025000a13310e8eb5cadb9a4a0 verir.
TypeScript'ten okumak
Yayımlanmış @solidus-network/bridge paketi (2026-10-08 tarihinde 0.2.0) MIRROR_ABI, gateKey, holderFromEvmAddress, credentialTypeHash ve issuerDidHash dışa aktarır. MIRROR_ABI dört görünümü kapsar: latestExport, exportOf, issuerAccredited ve lastHeartbeat. Diğerleri için aşağıdaki gibi kendi ABI parçanızı geçirin. gateKey, sahip 32 bayt değilse hata fırlatır; bu da doldurulmamış adresi yakalar.
import { createPublicClient, http, parseAbi } from 'viem'
import { MIRROR_ABI, credentialTypeHash, gateKey, holderFromEvmAddress, issuerDidHash } from '@solidus-network/bridge'
const mirror = '0x0a5a0d19206f436d67B7b87BF4c889d5b769517A'
const client = createPublicClient({ transport: http('https://rpc.solidus.network/bridge/11155111') })
const key = gateKey(
holderFromEvmAddress('0x00000000000000000000000000000000000000a1'),
credentialTypeHash('KycL2'),
issuerDidHash('did:example:issuer'),
)
const exportId = await client.readContract({ address: mirror, abi: MIRROR_ABI, functionName: 'latestExport', args: [key] })
const nextSeq = await client.readContract({
address: mirror,
abi: parseAbi(['function nextDomainSeq() view returns (uint64)']),
functionName: 'nextDomainSeq',
})
2026-10-08 tarihinde çalıştırıldığında bu, cast ile aynı anahtarı verdi: 0xa37189fa…5440, sıfır değerli bir exportId ve 1280n değerinde bir nextSeq.
Tek komutla görün
Üç EVM aynasının üçüne de hangi alana hizmet ettiklerini sorun. Adres hepsinde aynıdır.
for d in 11155111 43113 5042002; do
echo "$d $(cast call 0x0a5a0d19206f436d67B7b87BF4c889d5b769517A 'localDomain()(uint32)' --rpc-url https://rpc.solidus.network/bridge/$d --nonce 0 | cut -d' ' -f1)"
done
# 11155111 11155111
# 43113 43113
# 5042002 5042002
Adresleri listeleyen rota uç noktası Bridge API başvurusunda. Entegrasyon adımları geliştiriciler sayfasında, canlı zincir sağlığı durum sayfasında ve kısa cevaplar SSS sayfasında.
Okumaya devam edin
- Bir akıllı sözleşme işlevini, arkasındaki veriyi görmeden bir kimlik belgesine nasıl bağlarsınız
- Hedef, imzalanan şeyin içindedir; bu yüzden bir imza başka bir zincirde yeniden kullanılamaz
- Doğrulayıcıların bir durum mesajını nasıl imzaladığı ve bir ağ geçidinin onu başka bir zincire nasıl ilettiği
- Verify'ın düzenlediği bir kimlik belgesini başka bir zincire aktarma ve Solidus'un yolda neleri denetlediği