
L'objectif d'Axiom est de fournir une plateforme de médias sociaux complètement anonyme, décentralisée et résistante à la censure. Pour rendre cela possible, l'architecture est strictement divisée entre le protocole et les clients. Ce dépôt définit le protocole, le contrat intelligent et une structure de données standardisée sur un réseau Ethereum Layer 2.
42161https://arb1.arbitrum.io/rpc (ou tout point de terminaison personnalisé Alchemy/Infura)0xc11CFf8111e8b1F055eba095Efb679a38Abe6b63(Remarque : Axiom utilise une architecture de proxy UUPS (Universal Upgradeable Proxy Standard). Toutes les interactions client doivent toujours être dirigées vers cette adresse de proxy, jamais vers le contrat d'implémentation sous-jacent).
Les clients ne doivent jamais tenter de lire les publications du protocole directement à partir des variables d'état du contrat intelligent (car préserver le gaz est une priorité, le contenu n'est pas stocké dans l'état). Au lieu de cela, les clients doivent indexer les événements de la blockchain.
Pour publier des données sur le protocole, les clients doivent soumettre une transaction on-chain appelant la fonction publishAxiom sur le contrat proxy.
L'objectif d'Axiom est de fournir une plateforme de médias sociaux complètement anonyme, décentralisée et résistante à la censure.
Pour rendre cela possible, l'architecture est strictement divisée : la fondation (le protocole) et les clients (le logiciel). Ce référentiel définit cette fondation — un contrat intelligent et une structure de données standardisée sur un réseau Ethereum Layer 2.
Le protocole établit la fondation de la plateforme :
Axiom est conçu pour permettre une véritable liberté d'expression aux utilisateurs dans les pays où la communication est restreinte. Le protocole distingue trois niveaux de sécurité. Il suppose que les utilisateurs savent quel niveau de sécurité est approprié pour leur situation spécifique.
Pour tous les niveaux, le routage Onion (par exemple, Tor) est strictement obligatoire. Communiquer avec des fournisseurs RPC commerciaux (comme Infura ou Alchemy) divulgue l'adresse IP de l'expéditeur en texte clair. Pour fermer les vulnérabilités OPSEC potentiellement mortelles pour les dissidents, les clients sont tenus de router les transactions vers les nœuds RPC exclusivement via le réseau Tor.
Pour les messages de niveau 3, tous les clients doivent strictement respecter les normes cryptographiques suivantes pour garantir l'interopérabilité et éviter de compromettre la sécurité.
Axiom utilise une livraison de charge utile hybride (ABI Split). Pour éviter que le contrat intelligent n'ait à décompresser des formats de données coûteux, les données sont séparées avant la transmission :
uint8 _level) et le vecteur d'initialisation (bytes _iv) sont passés comme paramètres directs au contrat intelligent, car celui-ci en a besoin pour appliquer ses règles de sécurité.Axiom utilise des lettres uniques comme clés pour économiser des octets. L'auteur (msg.sender) et l'horodatage (block.timestamp) sont omis, car le contrat intelligent extrait ces valeurs de manière inviolable.
t (Type) : Entier. Le type d'action.c (Contenu) : Chaîne/Octets. Le texte, le nom ou le texte chiffré.h (Hashtags/Tags) : Tableau. Optionnel. Utilisé pour la catégorisation (sous-canaux).m (Indice de message) : Octets (longueur de 2). Niveau 3 uniquement. Un hachage HMAC de 2 octets utilisé pour le regroupement flou (fuzzy bucketing).r (Réponse à) : Octets. Optionnel. Le hachage de transaction d'un message référencé.t)0 = Mise à jour de profil (Lie l'adresse du portefeuille à un nom lisible dans le champ c)1 = Publication (Message standard)2 = Réponse (r nécessite le hachage de la publication originale)3 = J'aime (r nécessite le hachage de la publication)4 = Je n'aime plus (Annule le type 3)5 = Retweet / Repost (r nécessite le hachage de la publication)6 = Annuler le Retweet (Annule le type 5)h)c). Pour les observateurs externes, les tags sont donc complètement invisibles (Routage sombre / Dark Routing).m)Étant donné que les tags sont chiffrés au niveau 3, les clients doivent théoriquement tenter de déchiffrer chaque message (Déchiffrement par essai / Trial Decryption). Pour éviter la surcharge du CPU, Axium utilise des indices de message (Message Hints) :
HMAC-SHA256(AES_Key, IV) et place les 2 premiers octets comme champ m dans la charge utile CBOR.Axiom gère l'identité avec une transparence totale : L'adresse du portefeuille L2 (msg.sender) est la seule identité sociale et financière. Le protocole transfère la responsabilité de l'OPSEC financière entièrement à l'utilisateur (par exemple, l'utilisation de mixeurs et de ponts pour se procurer des jetons de gaz de manière anonyme).
L'action de mise à jour de profil (t: 0) se comporte différemment selon le niveau de sécurité choisi :
@Dissident99).Axiom repose sur une validation on-chain avec une complexité O(1). Pour maintenir les coûts de gaz à un minimum absolu, le contrat intelligent n'effectue que des vérifications cryptographiques de base. Toutes les validations de contenu gourmandes en ressources sont déchargées vers les clients (Layer 2).
Le contrat agit comme un videur incorruptible. Si une charge utile ne respecte pas les règles strictes, la transaction est annulée (revert).
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
contract Axiom is Initializable, UUPSUpgradeable, OwnableUpgradeable {
uint256 public entryFee;
mapping(address => uint8) public walletPath; // 0=New, 1=PathA(Level1), 2=PathB(Level2/3)
event AxiomPost(address indexed sender, uint8 level, bytes iv, bytes cbor, uint256 timestamp);
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize() initializer public {
__Ownable_init(msg.sender);
entryFee = 0.0001 ether;
}
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
function publishAxiom(
uint8 _level,
bytes calldata _iv,
bytes calldata _cbor
) external payable {
require(_level >= 1 && _level <= 3, "Invalid level");
uint8 requiredPath = (_level == 1) ? 1 : 2;
uint8 currentPath = walletPath[msg.sender];
if (currentPath == 0) {
require(msg.value >= entryFee, "Anti-Sybil: Insufficient entry fee");
walletPath[msg.sender] = requiredPath;
} else {
require(msg.value == 0, "Fee already paid");
require(currentPath == requiredPath, "OPSEC Violation: Wallet is tainted");
}
if (_level == 3) {
require(_iv.length == 12, "Level 3 strictly requires a 12-byte IV");
} else {
require(_iv.length == 0, "Level 1 and 2 require strictly empty IV");
}
emit AxiomPost(msg.sender, _level, _iv, _cbor, block.timestamp);
}
function withdraw() external onlyOwner {
payable(owner()).transfer(address(this).balance);
}
}
Si une publication viole les règles du protocole, le client doit la rejeter silencieusement (Rejet local / Local Drop).
c) des messages de niveau 2. Si des URL, des adresses IP ou des balises médiatiques typiques sont détectées, la publication est complètement bloquée.Axiom est déployé sur un réseau Ethereum Layer 2 (L2) (par exemple, Arbitrum Nova).
Pour éviter de surcharger les appareils mobiles (autonomie de la batterie, limitations de stockage, limites WebAssembly pour Argon2id), Axiom impose une architecture client très performante :
Les clients ne téléchargent pas l'état complet de la blockchain. Ils filtrent l'événement AxiomPost du contrat intelligent, qui contient toutes les données nécessaires en texte clair (Expéditeur, Niveau, IV, CBOR, Horodatage).
Étant donné que les nœuds Ethereum finiront par supprimer les données historiques (événements de plus de 365 jours) conformément à EIP-4444, le protocole recommande que les Axiom Cores locaux servent d'archives décentralisées, stockant les bases de données de manière permanente.
Pour illustrer le fonctionnement de l'architecture en pratique, voici un cycle de vie complet.
Scénario : Alice veut publier le message « Réunion à 20h » dans le sous-canal « AxiomDev ». Le groupe a préalablement convenu hors ligne du mot de passe « Secret123 ».
Le Axiom Core d'Alice gère le gros du travail de calcul :
0x12ab34cd56ef789012ab34cd).m: "0xa1b2").Étant donné que le niveau et l'IV sont passés directement au contrat, ils sont exclus de l'objet CBOR.
Représentation JSON interne :
{
"t": 1,
"c": "0x8a4f...",
"h": ["0x9b5e..."],
"m": "0xa1b2"
}
Ce JSON est compressé en un tableau d'octets CBOR brut (0xa3617401...) pour économiser du gaz.
Alice déclenche la fonction du contrat. Important : L'appel est strictement routé via Tor !
(Exemples pour L3 et L1 :)
// Exemple 1 : Client appelant le contrat intelligent pour un message chiffré de niveau 3
await axiomContract.publishAxiom(
3, // _level: 3
"0x12ab34cd56ef789012ab34cd", // _iv: chaîne hexadécimale de 12 octets requise
"0xa3617401616358208a4f..." // _cbor: chaîne hexadécimale CBOR compressée
);
// Exemple 2 : Client appelant le contrat intelligent pour un message public de niveau 1
await axiomContract.publishAxiom(
1, // _level: 1
"0x", // _iv: tableau d'octets strictement vide
"0xa361740161634c48656c6c6f204178..." // _cbor: chaîne hexadécimale CBOR compressée
);
Le contrat intelligent émet alors l'événement :
Event: AxiomPost(Sender: 0xAlice..., Level: 3, IV: 0x12ab..., CBOR: 0xa361..., Timestamp: 1710425890)
Le Axiom Core de Bob écoute la blockchain et reçoit l'événement.
Level 3 et décompresse le CBOR pour accéder au contenu, aux tags et à l'indice m.m par rapport aux mots de passe stockés de Bob.