WeaveDBの中身を暴きたい

ツイッターを見ているとWeaveDBというArweave上にファイルを保管する完全に分散的なデータベースが登場していた。
ついに来たかと思いつつ本当に動作するのか、実用的に使えるのか気になったのでソースコードを読んで、適当にメモって行く予定。

大きくリポジトリは大きく下の三つに分かれていた。
- src下のメインのコード
- sdk下のメインのコードにアクセスするコード
- console下の管理?に使うコード
まず、SDK側から読んでいく、気になったNPMパッケージがいくつかあった。
ramda 関数型プログラミングのためのユーティリティセット
arweave Arweaveの公式クライアント
warp-contracts なんか複雑そうだがArweaveの開発環境?らしい。SmartWeaveという開発環境?の実装らしい。ちょっと面白そうなので詳しく調べてみる

warp-contractsとはなんなのか
まず、warp-contractsはSmartWeaveというものの実装らしいので、それについて調べる
Arweaveプロトコルに基づくシンプルでスケーラブルなスマートコントラクト
遅延評価を使用して、契約実行の負担をネットワークノードからスマートコントラクトユーザーに移します。現在、SmartWeaveはJavaScriptをサポートしており、クライアントの修正されていない実行エンジンを使用しています。
Readmeを翻訳したもの。
この文面を素直に受け止めると画期的な気がするが、スマコンユーザーが契約実行をする
がよくわからない。

SmartWeaveについてもっと詳しく(しかも日本語で)Arweaveの公式サイトに載っていた。
ユーザがSmartWeaveコントラクトを操作すると、有効な状態遷移の連鎖の最後に到達するまで、dApp上の各トランザクションを評価します。コントラクトの終わりに到達すると、ユーザーはコントラクトへの呼び出しを評価し、結果として得られた状態遷移をArweaveネットワークに書き込みます。このプロセスは継続的に繰り返され、新しいユーザーはお互いのトランザクションを継続的に検証し、自分の状態遷移を追加していきます。
この仕組みは効率的なきがするけど、どうやってコンセンサスを形成するのかわからない。
なんにせよ、このSmartWeaveがWeaveDBの根幹を担ってる気がする。

sdkを読み進めていると、読み取り系のメソッドはコントラクトを直に読んでて、
書き込み系のメソッドは署名とかいろいろしてるっぽい。
書き込む際は内部でEIP712の署名を作成して、書き込むっぽい。
条件によって書き込むときにdryWrite
bundleInteraction
writeInteraction
などのコントラクトメソッドを叩いている。
なんのメソッドかわからないので、ぼちぼちWeave本体のコードをよむ。

WeaveDBのメインのコードを読んでたら、sdkとの間に挟まってるwrap-contracts
の機能が想ったより重かった。
なので、一旦wrap-contracts
のドキュメントを軽く読む

数日、文献を調べ続けていて参考になりそうなリンクを一旦まとめる,

デプロイスクリプト2
const fs = require("fs/promises");
const path = require("path");
const Arweave = require("arweave");
const { WarpNodeFactory } = require("warp-contracts");
const srcTxId = "G7aMmk1Fux6Dqw7M7CFoNQf5KZV2J1UCuZjfEn_VFVM";
const deploy = async () => {
const arweave = Arweave.init({
host: "arweave.net",
port: 443,
protocol: "https",
});
//@ts-ignore
const warp = WarpNodeFactory.memCachedBased(arweave).useWarpGateway().build();
const wallet = JSON.parse(
await fs.readFile(
path.join(__dirname, ".wallets/wallet-mainnet.json"),
"utf-8"
)
);
const walletAddress = await arweave.wallets.jwkToAddress(wallet);
const stateFromFile = JSON.parse(
await fs.readFile(
path.join(__dirname, "../dist/warp/initial-state.json"),
"utf8"
)
);
const initialState = {
...stateFromFile,
...{
owner: walletAddress,
},
};
const res = await warp.createContract.deployFromSourceTx(
{
wallet,
initState: JSON.stringify(initialState),
srcTxId,
},
true
);
console.log(res);
};
deploy()
.catch(console.error)
.finally(() => process.exit(0));

weavedbの仮の方ていぎ
/* eslint-disable */
interface Window {
ethereum: any | undefined;
}
declare let window: Window;
declare module "weavedb-sdk" {
export interface ArweaveConfig {
host?: string;
protocol?: string;
port?: string | number;
timeout?: number;
logging?: boolean;
network?: string;
}
export type SigningFunction = (tx: Transaction) => Promise<void>;
export interface ArWallet {
kty: string;
e: string;
n: string;
d?: string;
p?: string;
q?: string;
dp?: string;
dq?: string;
qi?: string;
}
export type WarpSigner = SigningFunction | ArweaveWallet | "use_wallet";
export interface EthWallet {
wallet: string;
privateKey: string;
}
export interface WeaveDBConfig {
arweave?: ArweaveConfig;
contractTxId: string; // maybe
wallet: WarpSigner;
name: string;
version: string;
EthWallet?: string | EthWallet; //maybe
web3?: any;
}
export type OP = {
//I don't know what this is
__op: string;
} & any;
export default class SDK {
constructor(config: WeaveDBConfig);
cget<T = any>(path: string, ...query: string[][]): Promise<T>;
add<T = any>(data: T, path: string, user: EthWallet): Promise<void>;
update<T = any>(
data: T,
path: string,
id: string,
user: EthWallet
): Promise<void>;
delete(path: string, id: string, user: EthWallet): Promise<void>;
ts(): OP;
signer(): OP;
createTempAddress(
address: string
): Promise<{ tx: any; identity: any; err: any }>;
}
}