
Axiomの目標は、完全に匿名で、分散化された、検閲耐性のあるソーシャルメディアプラットフォームを提供することです。これを可能にするために、アーキテクチャはプロトコルとクライアントに厳密に分割されています。このリポジトリは、Ethereum Layer 2ネットワーク上のプロトコル、スマートコントラクト、および標準化されたデータ構造を定義しています。
42161https://arb1.arbitrum.io/rpc (または任意のカスタムAlchemy/Infuraエンドポイント)0xc11CFf8111e8b1F055eba095Efb679a38Abe6b63(注: AxiomはUUPSアップグレード可能プロキシアーキテクチャを採用しています。すべてのクライアント操作は常にこのプロキシアドレスに対して実行する必要があり、内部の実装コントラクトには決して直接アクセスしないでください。)
クライアントは、スマートコントラクトの状態変数からプロトコルの投稿を直接読み取ろうとしてはいけません(ガス節約のため、コンテンツは状態に保存されません)。代わりに、クライアントはブロックチェーンイベントをインデックスする必要があります。
プロトコルにデータを公開するには、クライアントはプロキシコントラクトのpublishAxiom関数を呼び出すオンチェーントランザクションを送信する必要があります。
Axiomの目標は、完全に匿名で分散型かつ検閲耐性のあるソーシャルメディアプラットフォームを提供することです。
これを可能にするため、アーキテクチャは厳密に分割されています。基盤(プロトコル)とクライアント(ソフトウェア)です。このリポジトリはその基盤、すなわちEthereum Layer 2ネットワーク上のスマートコントラクトと標準化されたデータ構造を定義します。
プロトコルはプラットフォームの基盤を確立します。
Axiomは、通信が制限されている国のユーザーに対して真の言論の自由を実現するように設計されています。プロトコルは3つのセキュリティレベルを区別します。ユーザーは自分の状況に適したセキュリティレベルを理解していることを前提としています。
すべてのレベルにおいて、オニオンルーティング(例: Tor)が厳格に必須です。商用のRPCプロバイダー(InfuraやAlchemyなど)と通信すると、送信元のIPアドレスが平文で漏洩します。反体制活動家にとって生命に関わるOPSECの脆弱性を防ぐため、クライアントはTorネットワークを介してのみRPCノードにトランザクションをルーティングする必要があります。
レベル3のメッセージでは、相互運用性を確保しセキュリティを損なわないために、すべてのクライアントが以下の暗号化標準を厳守する必要があります。
Axiomはハイブリッドペイロード配信(ABI分割)を利用します。スマートコントラクトに高コストなデータ形式の展開を強制しないために、データは送信前に分離されます。
uint8 _level)と初期化ベクトル(bytes _iv)はスマートコントラクトに直接パラメータとして渡されます。コントラクトがセキュリティルールを適用するためにこれらを必要とするためです。Axiomはバイト節約のために単一文字をキーとして使用します。作者(msg.sender)とタイムスタンプ(block.timestamp)は省略されます。これらはスマートコントラクトが改ざん不可能な形で抽出するためです。
t(Type): 整数。アクションの種類。c(Content): 文字列/バイト。テキスト、名前、または暗号文。h(ハッシュタグ/タグ): 配列。オプション。分類(サブチャネル)に使用。m(メッセージヒント): バイト(長さ2)。レベル3のみ。 ファジーバケットに使用される2バイトのHMACハッシュ。r(返信先): バイト。オプション。参照先の投稿のトランザクションハッシュ。tフィールド)0 = プロフィール更新(ウォレットアドレスをフィールドcの読み取り可能な名前にリンク)1 = 投稿(標準メッセージ)2 = 返信(rには元の投稿のハッシュが必要)3 = いいね(rには投稿のハッシュが必要)4 = いいね解除(タイプ3を取り消し)5 = リツイート/再投稿(rには投稿のハッシュが必要)6 = リツイート解除(タイプ5を取り消し)hフィールド)c)とまったく同様に暗号化されなければなりません。そのため、外部の観測者にはタグは完全に見えません(ダークルーティング)。mフィールド)レベル3ではタグが暗号化されるため、クライアントは理論上すべてのメッセージを復号しようと試みる必要があります(トライアル復号)。CPU負荷を防ぐため、Axiomはメッセージヒントを使用します。
HMAC-SHA256(AES_Key, IV)を計算し、最初の2バイトをmフィールドとしてCBORペイロードに配置します。Axiomはアイデンティティを完全に透過的に扱います。L2ウォレットアドレス(msg.sender)が唯一のソーシャルかつ金融上のアイデンティティです。 プロトコルは金融上のOPSECの責任を完全にユーザーに委ねます(例: ミキサーやブリッジを使用して匿名でガストークンを調達すること)。
プロフィール更新アクション(t: 0)は、選択されたセキュリティレベルによって異なる動作をします。
@Dissident99として公開の評判を築く)。AxiomはO(1)複雑性のオンチェーン検証に依存します。ガスコストを最小限に抑えるため、スマートコントラクトは基本的な暗号チェックのみを実行します。リソース集約的なコンテンツ検証はすべてクライアント(レイヤー2)にオフロードされます。
コントラクトは改ざん不可能な用心棒として機能します。ペイロードが厳格なルールに従わない場合、トランザクションはリバートされます。
// 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);
}
}
投稿がプロトコルルールに違反している場合、クライアントはそのメッセージを黙って破棄しなければなりません(ローカルドロップ)。
c)をスキャンします。URL、IPアドレス、典型的なメディアタグが検出された場合、その投稿は完全にブロックされます。AxiomはEthereum Layer 2(L2)ネットワーク(例: Arbitrum Nova)にデプロイされています。
モバイルデバイス(バッテリー寿命、ストレージ制限、Argon2idのWebAssembly制限など)への負荷を避けるため、Axiomは高性能なクライアントアーキテクチャを強制します。
クライアントはブロックチェーン全体の状態をダウンロードしません。スマートコントラクトのAxiomPostイベントをフィルタリングし、そこに含まれるすべての必要なデータ(Sender, Level, IV, CBOR, Timestamp)をプレーンテキストで取得します。
EthereumノードはEIP-4444に従い、過去のデータ(365日より古いイベント)を最終的に破棄するため、プロトコルはローカルのAxiom Coreがデータベースを永久に保存する分散アーカイブとして機能することを推奨します。
アーキテクチャが実際にどのように動作するかを示すために、完全なライフサイクルを説明します。
シナリオ: Aliceがサブチャネル「AxiomDev」にメッセージ「Meeting at 8 PM」を投稿したいと考えています。グループは事前にオフラインでパスワード「Secret123」に合意しています。
AliceのAxiom Coreが計算負荷の高い処理を担当します。
0x12ab34cd56ef789012ab34cd)。m: "0xa1b2")。レベルとIVはコントラクトに直接渡されるため、CBORオブジェクトからは除外されます。
内部JSON表現:
{
"t": 1,
"c": "0x8a4f...",
"h": ["0x9b5e..."],
"m": "0xa1b2"
}
このJSONは、ガス節約のために生のCBORバイト配列(0xa3617401...)に圧縮されます。
Aliceがコントラクト関数をトリガーします。重要: 呼び出しは厳密にTor経由でルーティングされます!
(L3とL1の例:)
// 例1: 暗号化されたレベル3投稿のためのコントラクト呼び出し
await axiomContract.publishAxiom(
3, // _level: 3
"0x12ab34cd56ef789012ab34cd", // _iv: 12バイトの16進文字列が必要
"0xa3617401616358208a4f..." // _cbor: パックされたCBORの16進文字列
);
// 例2: 公開レベル1投稿のためのコントラクト呼び出し
await axiomContract.publishAxiom(
1, // _level: 1
"0x", // _iv: 厳密に空のバイト配列
"0xa361740161634c48656c6c6f204178..." // _cbor: パックされたCBORの16進文字列
);
スマートコントラクトは次のイベントを発行します。
Event: AxiomPost(Sender: 0xAlice..., Level: 3, IV: 0x12ab..., CBOR: 0xa361..., Timestamp: 1710425890)
BobのAxiom Coreがブロックチェーンをリッスンし、イベントを受信します。
Level 3を検出し、CBORを展開してコンテンツ、タグ、およびヒントmにアクセスします。mをBobの保存されたパスワードと照合します。