Vai al contenuto
Accedi
‹ Indietro Esporta in PDFEsporta in Word

Documentazione tecnica

Documentazione tecnica

Versione dei formati: passaporto-evento/1, passaporto-prova/1, passaporto-chiavi/1. Una modifica alla forma canonica, all'algoritmo d'impronta o alla struttura dell'albero crea una versione nuova; le versioni precedenti restano documentate e verificabili.

1. Documento dell'evento (passaporto-evento/1)

Ogni evento di filiera è un documento JSON costruito dalle colonne dell'evento. Campi:

CampoContenuto
formatopassaporto-evento/1
prodotto, lottoidentificativo persistente del prodotto e, se c'è, del lotto
sequenzanumero progressivo dell'evento nella catena del prodotto (da 1)
precedenteimpronta dell'evento precedente dello stesso prodotto (null per il primo)
emittenteazienda che registra: id, ragione_sociale, piva
tipotipo di evento del catalogo (produzione, assemblaggio, collaudo, spedizione, passaggio_proprieta, rettifica…)
epciscorrispondenza GS1 EPCIS 2.0: type, action, bizStep, disposition
quando, fusoistante dell'evento in UTC (ISO 8601) e scostamento del fuso locale
doveluogo: nome, id
passaggioper i passaggi di proprietà: cedente e cessionario; altrimenti null
rettifica_diper le rettifiche: impronta dell'evento rettificato; altrimenti null
visibilitapubblico o riservato
nota, attributitesto libero e attributi propri del tipo di evento
riservatiimpegno sui dati riservati: keccak256(canonico({"dati": …, "sale": …})), oppure null. I dati riservati non stanno nel documento pubblico
allegatiper ogni file: nome, tipo, dimensione, sha256, visibilita
sale32 byte casuali per evento (esadecimale)

Sono esclusi i campi generati dopo il calcolo dell'impronta o che ne dipendono: impronta, firma, stato, lotto d'ancoraggio, prova, identificativi interni dell'evento, data di registrazione.

2. Forma canonica e impronta

3. Firma (attestazione)

Verifica con OpenSSL (la firma va prima convertita da r‖s a DER):

base64 -d pubblica.b64 > pubblica.der
openssl pkey -pubin -inform DER -in pubblica.der -out pubblica.pem
openssl dgst -sha256 -verify pubblica.pem -signature firma.der impronta.bin

4. Lotto d'ancoraggio e albero di Merkle

5. Contratto di registro

RegistroRadici (Solidity 0.8.26, sorgente e ABI nel pacchetto del prodotto):

function ancora(bytes32 radice, bytes32 lotto) external
function ancorataIl(address mittente, bytes32 radice) external view returns (uint64)
event RadiceAncorata(address indexed mittente, bytes32 indexed radice, bytes32 indexed lotto, uint64 quando)

Non ha proprietario, non ha funzioni amministrative, non è aggiornabile (nessun proxy), non riceve fondi. Ogni radice è legata all'indirizzo che l'ha registrata: la verifica chiede al contratto ancorataIl(mittente della piattaforma, radice).

ReteCatenaContrattoMittente (portafoglio operativo)Esploratore
Polygon Amoy (rete di prova)800020x9a28fEa6e92f1F0A9d7DeeF30377fEDB0cD01FD90x56C2Ba3837100b2227B77a3F08EA0FC1e2565C92https://amoy.polygonscan.com/address/0x9a28fEa6e92f1F0A9d7DeeF30377fEDB0cD01FD9

6. Pacchetto di prova (passaporto-prova/1)

Si scarica da ogni evento del passaporto («Scarica evento e prova») o da GET /e/{id}/prova.json:

{"formato": "passaporto-prova/1",
 "evento": {"canonico": "…", "impronta": "0x…", "oscurato": false},
 "attestazione": {"tipo_firma": "ecdsa-p256-sha256", "firma": "0x…", "chiave": "0x…", "pubblica": "…"},
 "prova": {"foglia": "0x…", "fratelli": ["0x…"], "radice": "0x…"},
 "registro_chiavi": {"documento": "…", "impronta": "0x…", "fratelli": ["0x…"]},
 "ancoraggio": {"rete": "…", "catena_id": 80002, "contratto": "0x…", "mittente": "0x…", "transazione": "0x…", "blocco": 0, "lotto_in_catena": "0x…"}}

7. Verificare a mano

1. keccak256(UTF-8(evento.canonico)) deve dare evento.impronta.

2. La firma attestazione.firma deve essere valida sull'impronta con attestazione.pubblica; keccak256(DER della chiave) deve dare attestazione.chiave.

3. foglia = keccak256(keccak256(impronta ‖ keccak256(firma))) deve essere prova.foglia.

4. Partendo dalla foglia, per ogni fratello: h = keccak256(min(h, fratello) ‖ max(h, fratello)). Il risultato deve essere prova.radice.

5. Stesso procedimento per il registro delle chiavi: da keccak256(keccak256(etichetta ‖ registro_chiavi.impronta)) con registro_chiavi.fratelli si deve arrivare alla stessa radice; la chiave della firma deve comparire nel documento del registro, intestata all'emittente dell'evento.

6. Sulla rete pubblica: ancorataIl(mittente, radice) sul contratto deve dare un istante diverso da zero; in alternativa si apre la transazione sull'esploratore e si legge l'evento RadiceAncorata.

Strumenti pronti: verificatore in un solo file HTML (https://dactacore.com/verificatore), script a riga di comando senza dipendenze (verifica.py), vettori di prova (https://dactacore.com/verificatore/vettori.json).

8. Stati di un evento

registrato (firmato, non ancora in un lotto) → in_ancoraggio (lotto chiuso, transazione da inviare o in attesa di conferme) → confermato (numero di conferme configurato) → finalizzato (blocco definitivo). Lo stato non è scritto sull'evento: si legge dal lotto che lo contiene. Se la catena si riorganizza il lotto torna in ancoraggio e viene ritrasmesso.

9. Solo in aggiunta

Le tabelle di eventi, attestazioni, foglie dei lotti e registro delle operazioni rifiutano UPDATE, DELETE e TRUNCATE a livello di database (trigger), per qualunque utente applicativo. Unica eccezione dichiarata: l'oscuramento del contenuto di un evento per il diritto alla cancellazione, che svuota i campi di contenuto e lascia impronta, sale, catena e firma.

10. API per i sistemi aziendali

Base: https://dactacore.com/api/v1 · descrizione OpenAPI: https://dactacore.com/api/v1/openapi.json · autenticazione: Authorization: Bearer <token dell'azienda>.

Metodo e percorsoCosa fa
GET /api/v1/prodottielenco dei prodotti dell'azienda
POST /api/v1/prodotticrea un prodotto (nome, modello, categoria, gtin, descrizione, dati_pubblici, dati_riservati)
POST /api/v1/prodotti/{pid}/lotticrea un lotto o un numero di serie (codice, seriale, quantita)
POST /api/v1/eventiregistra un evento (prodotto, lotto, tipo, quando, fuso, luogo, nota, attributi, riservati, visibilita, allegati, cessionario_id, rettifica_di)
GET /api/v1/eventi/{id}l'evento con lo stato dell'ancoraggio
GET /api/v1/eventi/{id}/provail pacchetto di prova

Esempio:

curl -X POST https://dactacore.com/api/v1/eventi -H "Authorization: Bearer ppk_…" -H "Idempotency-Key: ddt-2026-000123" \
  -H "Content-Type: application/json" \
  -d '{"prodotto": "7K2M9Q4X8TD3A", "tipo": "spedizione", "quando": "2026-11-12T08:30:00Z", "fuso": "+01:00", "luogo": "Magazzino", "attributi": {"colli": 2}}'