VERIFICACIÓN INDEPENDIENTE

Verificá anclas on-chain sin confiar en nadie

No necesitás la API de ChainMemory para verificar que un estado de proyecto fue anclado en un bloque específico. Esta página muestra cómo verificar directamente contra la blockchain usando herramientas Web3 estándar.

Qué necesitás

  • El hash del estado del proyecto (de la API o compartido por alguien)
  • El hash de la transacción o número de bloque del ancla
  • Node.js con ethers instalado — o cualquier librería Web3

Paso 1 — Obtener los datos del ancla

Usá el endpoint público (sin autenticación) de ChainMemory o recibilos de quien compartió la prueba:

bash
curl https://api.chainmemory.ai/v1/project/chainmemory/state/anchor
Respuesta
{
  "project": "chainmemory",
  "projectId": "0x77f7d980...",
  "version": 8,
  "state_hash": "0xa6c45d1db753b1ec96240d169b2d91fb0ce76112558b302a8822b2988aeb8212",
  "anchor": {
    "status": "anchored",
    "onchain_anchor_id": 8,
    "tx_hash": "0x95b732d20b8935a2...",
    "block_number": 173831,
    "contract": "0xa7A8BA51950255b3e223a6745597C67009Fe7875"
  },
  "verify": "ProjectStateAnchor.getStateAnchor(projectId, version)"
}

Paso 2 — Verificar on-chain con Ethers.js

Conectate directamente al RPC de ChainMemory y leé el smart contract. Sin API Key, sin cuenta, sin confianza requerida.

javascript
import { ethers } from 'ethers';

// Conectar al RPC de ChainMemory — sin API Key necesaria
const provider = new ethers.JsonRpcProvider('https://rpc.chainmemory.ai');

// Contrato ProjectStateAnchor
const CONTRACT = '0xa7A8BA51950255b3e223a6745597C67009Fe7875';
const ABI = [
  'function getStateAnchor(bytes32 projectId, uint64 version) view returns (bytes32 stateHash, uint256 anchoredAt, address anchoredBy, uint256 anchorId)'
];

const contract = new ethers.Contract(CONTRACT, ABI, provider);

// El project ID es el keccak256 del nombre del proyecto
const projectId = ethers.keccak256(ethers.toUtf8Bytes('chainmemory'));
const version = 8;

// Leer directamente de la blockchain
const [stateHash, anchoredAt, anchoredBy, anchorId] = await contract.getStateAnchor(projectId, version);

console.log('Hash on-chain del estado:', stateHash);
console.log('ID de ancla:', anchorId.toString());
console.log('Anchored at:', new Date(Number(anchoredAt) * 1000).toISOString());

// Comparar con el hash que recibiste
const expectedHash = '0xa6c45d1db753b1ec96240d169b2d91fb0ce76112558b302a8822b2988aeb8212';
if (stateHash === expectedHash) {
  console.log('VERIFICADO — el estado coincide con el ancla on-chain');
} else {
  console.log('DISCREPANCIA — el estado fue manipulado');
}
javascript
const Web3 = require('web3');

const web3 = new Web3('https://rpc.chainmemory.ai');

const CONTRACT = '0xa7A8BA51950255b3e223a6745597C67009Fe7875';
const ABI = [{
  name: 'getStateAnchor',
  type: 'function',
  stateMutability: 'view',
  inputs: [
    { name: 'projectId', type: 'bytes32' },
    { name: 'version', type: 'uint64' }
  ],
  outputs: [
    { name: 'stateHash', type: 'bytes32' },
    { name: 'anchoredAt', type: 'uint256' },
    { name: 'anchoredBy', type: 'address' },
    { name: 'anchorId', type: 'uint256' }
  ]
}];

const contract = new web3.eth.Contract(ABI, CONTRACT);

const projectId = web3.utils.keccak256('chainmemory');

const result = await contract.methods.getStateAnchor(projectId, 8).call();
console.log('Hash on-chain del estado:', result.stateHash);
console.log('ID de ancla:', result.anchorId);

Paso 3 — Verificar la transacción

También podés verificar la transacción cruda que creó el ancla:

javascript
// Leer la transacción directamente
const tx = await provider.getTransaction('0x95b732d20b8935a286869d90e60a40f5c31d350a94e27bfd7845770fe0c3e2c3');
console.log('From:', tx.from);       // Debería ser un validador conocido
console.log('To:', tx.to);           // Debería ser la dirección del contrato
console.log('Block:', tx.blockNumber);

// Leer el bloque para confirmar timestamp
const block = await provider.getBlock(tx.blockNumber);
console.log('Hora del bloque:', new Date(block.timestamp * 1000).toISOString());
Verificación zero-trust Todo este proceso requiere cero interacción con los servidores de ChainMemory. Te conectás directamente al endpoint RPC de la blockchain y leés el smart contract. Incluso si la API de ChainMemory estuviera comprometida o caída, los datos on-chain siguen siendo verificables.
Alternativa con MetaMask También podés verificar visualmente: agregá la red ChainMemory a MetaMask, navegá a la dirección del contrato en el Explorer, e inspeccioná los datos de la transacción manualmente.