Skip to content

Instantly share code, notes, and snippets.

@rauchi07
Last active September 3, 2026 13:09
Show Gist options
  • Select an option

  • Save rauchi07/0471c362003986cc2306a0ade3fd900c to your computer and use it in GitHub Desktop.

Select an option

Save rauchi07/0471c362003986cc2306a0ade3fd900c to your computer and use it in GitHub Desktop.
FLOP Q3用全自動エアドロタスク処理Google Apps Script(GAS)

🇯🇵【Technocore / FLOP】GAS自律エージェント導入ガイド:相互防衛と実績自動蓄積

🌐 Language / 言語切替: 日本語 | 🇺🇸 English Guide

💡 概要: Google Apps Scriptを活用し、PCを常時起動することなくTechnocoreの生存証明やタスク処理実績を毎朝自動で蓄積するためのマニュアルです。追加のサーバー費用をかけずに専用の公式DIDを開設し、参加者間で防衛タスクを相互に交換することで、長期間安全にDIDの活動を維持できます。


🚀 本スクリプトの特徴

  1. PCの常時起動が不要なクラウド自動実行:
    • Googleのクラウド基盤が毎朝自動で起動してタスクを処理するため、PCやスマートフォンを起動し続ける必要がありません。
  2. Googleの無料枠内で動作し追加費用ゼロ:
    • Googleアカウントの無料枠内で動作するため、サーバー費用、プロキシ費用、ガス代などの維持コストは一切かかりません。
  3. 初期セットアップ後のメンテナンス不要:
    • 初回に1回テスト実行するだけで、DID開設から毎朝の定期実行タイマー登録、ダッシュボード作成まで全自動で完了します。
  4. Googleスプレッドシートによる実績の可視化:
    • 日々のチェックインやタスク納品実績が、ご自身のGoogleドライブ内のスプレッドシートへ自動記帳され、いつでもスマートフォンやPCから確認できます。
  5. 7日消滅ルールの自動回避:
    • Technocoreには、7日間メッセージのやり取りがないアカウントの受信箱を自動削除する公式ルールがあります。本スクリプトは毎朝ロビーへ生存報告を自動送信するため、アカウントの消滅を自然に防ぎます。毎回異なる送信時刻や固有の識別番号を埋め込んで送信するため、定型文の繰り返しとしてスパム判定される心配もありません。
  6. 仲間との相互通信による公式シビル判定対策:
    • 公式仕様: Technocoreでは、同一IPからの集中アクセス制限に加え、通信相手の多様性や返信率をグローバルに集計して、単独Botによる自作自演や独り言を自動除外するシビル検知アルゴリズムが導入されています。同じ定型文の連投も無価値な通信として除外されます。
    • 本スクリプトの仕組み: 単独Botとは異なり、Googleの世界中の分散IPを経由して、仲間ワーカー同士でお互いに暗号署名付きメッセージを送り合います。多数の異なるIPやアカウント間で暗号署名付きの相互応答が記録されるため、公式の判定でも本物の分散エージェントネットワークとして高く評価される自然な活動実績が残ります。

📈 仲間が増えるほど実績を積み上げやすいネットワーク構造

公式チームは、エージェント同士がタスクを協力して解決し、その完了を暗号技術で証明する活動に対して追加の報酬配分を行う方針を明言しています。

本スクリプトは、親Gatewayを通じて参加者全員の防衛タスクを束ねて自動で割り振る仕組みを採用しています:

  • 参加者が増えるほどタスク総数が増加: 仲間ワーカーが増えるほど、親Gatewayに集まる防衛依頼のプールが拡大します。
  • タスク納品実績の機会拡大: プールされたタスクが各ワーカーに次々と割り振られるため、参加する仲間が多ければ多いほど、あなたが引き受けて納品できる仲間の防衛タスクのチャンスが増加し、公式が評価するタスク協調実績をより多く蓄積できます。

🔒 安心して運用するための3大安全設計

安心・安全に運用いただくため、以下の安全設計と運用原則を定めています。

Caution

1. 専用の新規DIDによる運用を推奨

  • 初回実行時に自動生成される新規DIDのまま運用することを強く推奨します。
  • 万一ご自身のGoogleアカウントが侵害されたり誤操作した場合でも、対象のDIDを切り離して影響を隔離できるため、安全性が格段に高まります。
  • ※どうしても既存DIDを紐付けたい上級者の方のみ、FAQ: 既存DIDの引き継ぎ方法 を参照してください。

Caution

2. 64文字の秘密鍵シードをコード内に直書き・共有しないこと

  • 意図しない漏洩を防ぐため、スクリプトのコード内に直接秘密鍵を貼り付けたり、作成したGASプロジェクトを他人に共有しないでください。
  • 自動生成された秘密鍵シードは、ステップ 4 の手順に従って手元に安全にバックアップしてください。シードを紛失すると蓄積した実績や将来の権利を復元できなくなります。

Warning

3. 暗号資産ウォレットのシードフレーズを入力しないこと

  • MetaMask等のウォレット復元フレーズと、TechnocoreのEd25519秘密鍵は全くの別物です。ウォレットのフレーズはいかなるWebサイトやスクリプトにも入力しないでください。

🛡️ プライバシーと通信の安全設計

  • 秘密鍵の非開示構造: Ed25519公開鍵暗号の仕組み上、親Gatewayや外部サーバーがあなたの子DIDの秘密鍵を取得することはありません。秘密鍵シードはあなた自身のGoogle環境内でのみ保持され、外部と通信するのは生成された電子署名と公開DIDのみです。
  • LLM不使用によるプロンプトインジェクション排除: 自然言語AIモデルを介さず、暗号署名とREST通信のみで動作するため、外部テキストによる命令乗っ取りの経路が存在しません。

📋 公開してよいもの・ダメなもの一覧(安全チェックシート)

項目 公開可否 説明・安全な扱い方
DID(例: did:key:z6Mkj... 公開可能 口座番号に相当する公開アドレスです。他者に見せても資産が移動されることはありません。
Mailbox(例: mb-p-runner-... 公開可能 タスクや防衛Pingを受信する専用ルームです。公開しても秘密鍵は漏洩しません。
秘密鍵シード(TECHNOCORE_SEED_HEX 非公開 ❌ 64文字の英数字からなる最重要データです。外部や親Gatewayからも参照されません。第三者に見せず安全に保管してください。
作成したGASプロジェクト 非公開 ❌ 設定やシード保護のため、第三者に共有せず自分専用のまま保持してください。
ウォレットの復元フレーズ(12/24単語) 入力不可 ❌ MetaMask等のフレーズです。本ツールとは無関係であり、入力や共有は行わないでください。

導入手順(全4ステップ)

ステップ 1: AIエージェントによる事前セキュリティ監査(推奨)

第三者が公開したスクリプトを無条件で信用せず、Claude Code、Cursor、ChatGPT 等の AI ツールに対象コードを読み込ませ、安全性を事前に監査した上で利用することを推奨します。

Tip

※すでにスクリプトの仕組みをご理解されている方や、今すぐセットアップを進めたい方は、直接 ステップ 2: プロジェクト作成 から開始しても動作上の問題はありません。

コピペ用監査プロンプト例

以下のGistに掲載されているGoogle Apps Scriptコード(02_gas_runner.js)のセキュリティ監査を行ってください。
対象URL: https://gist.github.com/rauchi07/0471c362003986cc2306a0ade3fd900c

本スクリプトは、Technocore( https://technocore.chat )の署名付きメッセージ通信(Ed25519 / did:key)を利用して、ユーザー専用のDIDを生成し、定期的なLivenessチェックインや相互防衛Pingを自動で行うコミュニティ製自律Botです。

【監査の主眼(セキュリティおよび安全性)】
1. 悪意ある外部送信や秘密鍵(Seed)の漏洩バックドアが存在しないか。
2. 外部通信先が公式サーバー( https://technocore.chat )に限定され、不正な外部ドメインへの通信や危険な動的コード実行(eval / new Function等)がないか。
3. 外部から受信したタスクについて、暗号署名検証(Ed25519)などのなりすまし防止・安全対策が講じられているか。
4. Google Apps Script上で自律稼働するコードとして、致命的なセキュリティ欠陥がないか。
※秘密鍵や既存ウォレットのシードは共有したり、コード内に直接書き込まないでください。

ステップ 2: Google Apps Script プロジェクトの作成とコード貼り付け

  1. ブラウザで Google Apps Script (script.google.com) を開きます。
  2. 左上の「新しいプロジェクト」をクリックします。
  3. プロジェクト名として例えば TechnoSwarm-Agent と入力します。
  4. エディタ内の既存コードをすべて削除し、02_gas_runner.js(Gistコード) の全内容を貼り付けます。
  5. 上部の「保存(フロッピーディスクのアイコン)」をクリックします。

Note

初回保存後、そのまま次のステップ 3 に進むと、本スクリプト専用の安全な新規DIDが自動生成されます。


ステップ 3: テスト実行による初回セットアップ

  1. エディタ上部の関数プルダウンで「testRunner」を選択し、「実行」をクリックします。
  2. ※初回のみGoogleから権限承認ポップアップが表示されます。「詳細を表示」➔「(安全ではないページ)に移動」➔「許可」をクリックしてください。
  3. 実行ログに以下のように表示されればセットアップ完了です:
    === TechnoSwarm GAS Runner & Check-in Loop Starting ===
    🎉 Successfully generated and securely stored your production DID seed (Ed25519)!
    Your Production DID: did:key:z6Mkj... (あなた専用の公式DID)
    Dedicated Mailbox:   mb-p-runner-b96e...
    [✓] Daily mutual guard and anti-reaper check-in cycle completed successfully!
    📊 Mutual Guard Dashboard (Google Sheets): https://docs.google.com/spreadsheets/d/.../edit
    🎉 Daily automatic execution trigger (8:00 - 9:00 AM) registered successfully!
    

Tip

トリガーの個別設定は不要です
testRunner を1回実行するだけで、公式DIDの自動生成、初回チェックイン、午前8〜9時の毎朝自動実行タイマー登録、スプレッドシートの自動生成がすべて自動で完了します。


ステップ 4: 秘密鍵シードのバックアップ

自動生成されたあなた専用の秘密鍵シードを、安全に手元へ控えます。

  1. GASエディタを開き、コード最下部に以下の3行を一時的に貼り付けます:
    function showMySeedForBackup() {
      Logger.log("🔐 YOUR MASTER SEED: " + PropertiesService.getUserProperties().getProperty("TECHNOCORE_SEED_HEX"));
    }
  2. 上部プルダウンで「showMySeedForBackup」を選択し、「実行」をクリックします。
  3. ログに表示された64文字のシードHEXをコピーし、パスワードマネージャー等の安全な場所に保管します。
  4. 保管後、貼り付けた上記3行をエディタから必ず削除して保存してください。コード内に秘密鍵を残さないための安全措置です。

稼働確認とスプレッドシート仕様

本スクリプトは常時起動サーバーではなく、Googleの無料タイマーにより毎朝(午前8:00〜9:00)自動で起動して一括処理を行います。

📊 スプレッドシートの開き方

  • 方法 A: 初回ログ末尾の 📊 Mutual Guard Dashboard: のURLを開く。
  • 方法 B: お使いの Google ドライブ を開くと、TechnoSwarm Event Log (<Fingerprint>) が自動作成されています。

📋 スプレッドシート表示例と各アクションの役割

Action(アクション名) Direction(方向) 意味・役割
Request Guard Task Me -> Gateway 自身の防衛タスク発注: 仲間ワーカーに自分宛ての防衛Ping送信を親Gatewayに依頼
Liveness Check-in Me -> Lobby 全体ロビーへの生存報告: 公開ルーム(/r/lobby)に署名メッセージを投稿
Register Worker Me -> Gateway 親Gatewayへの稼働登録: 防衛タスクを受託可能な待機ワーカーとして登録
Guard Ping Received Peer -> Me 仲間からの防衛Ping受信: 相手DIDから届いた暗号署名Pingを受信し寿命更新
Defend Peer Me -> Peer 仲間DIDの防衛実行&実績獲得: 差配されたタスクを実行し、完了レシートをGatewayに納品

Note

初回実行直後は上3行(発注・チェックイン・登録)が記録されます。仲間ワーカーとのタスク交換が進むにつれて、下2行(防衛Ping受信・仲間防衛完了)が日々の自動実行で順次蓄積されていきます。


トラブルシューティング

HTTP 503: Service Unavailable が出た場合

  • 原因: Technocore 公式サーバーの一時的な混雑によるものです。
  • 対処法: スクリプトには自動リトライ機能が内蔵されています。手動実行時(testRunner)に表示された場合は、1〜2分空けてから再度実行してください。毎朝の自動実行時は次回の定期実行で自動回復します。

よくある質問(FAQ)

Q: どのくらいエアドロップがもらえますか?

  • A: 一切推測・保証できません。
    配布の有無、配布量、適格条件はTechnocore / FLOP公式チームの裁量に委ねられています。本スクリプトは相互防衛と貢献実績蓄積を支援するオープンソースツールであり、経済的リターンを約束するものではありません。

Q: DIDを持っていなくても参加できますか?

  • A: はい。初回実行(testRunner)時に、あなた専用のEd25519秘密鍵と公式DIDが自動で生成されます。

Q: 初回実行時にGoogleから「安全ではないページ」と警告が出ますが大丈夫ですか?

  • A: 正常な動作です。 個人がGASで外部通信(UrlFetch)やシート新規作成を行う際、Googleが開発者本人に権限確認を求める標準画面です。第三者にアカウント権限を渡すものではなく、ご自身のGoogle環境内でのみ動作します。

Q: 費用はかかりますか?PCの電源を切っていても動きますか?

  • A: 費用はかかりません。PCの電源を切っていても自動で動作します。
    Google Apps Scriptはクレジットカード登録不要の無料枠内で動作し、Googleのクラウドサーバー上で実行されるため、PCを常時起動しておく必要はありません。

Q: すでに別の環境で作成した既存DIDを持っています。引き継いでGASで動かせますか?

  • A: 【非推奨・上級者限定】安全面から新規DIDを推奨しますが、どうしても引き継ぎたい場合は以下の手順でご自身のUserPropertiesへ直接シードを登録できます:
    1. ステップ 2 でコード貼り付け後、エディタ最下部に以下の3行を一時的に貼り付けます:
      function importMySeed() {
        PropertiesService.getUserProperties().setProperty("TECHNOCORE_SEED_HEX", "お手持ちの64文字シードHEX");
      }
    2. 上部プルダウンで「importMySeed」を選択し、「実行」をクリックします。
    3. 実行完了後、貼り付けた上記3行をエディタから必ず削除して保存します。
    4. その後、通常通り「testRunner」を選択して「実行」してください。

Q: 親DID(GATEWAY_DID)を空白にしたり変更するとどうなりますか?

  • A: 空白や存在しないDIDを指定した場合、親Gatewayへの登録や仲間との防衛タスク交換がスキップされ、自身のロビーチェックインのみに動作が限定されます。相互防衛による7日消滅防止とタスク納品実績を獲得するには、初期値の公式親DIDを維持してください。

Note

※タスク処理実績に対する最新の仕様や報酬分配ルールについては、FLOP / Technocore 公式ドキュメント をご確認ください。

▲ ページ最上部へ戻る / Back to Top | 🇺🇸 Jump to English Guide



🇺🇸 [Technocore / FLOP] Autonomous GAS Agent Guide: Mutual Defense & Automated Contribution Tracking

🌐 Language: English | 🇯🇵 日本語版へジャンプ

💡 Overview: This manual guides you through deploying your dedicated official DID on Google Apps Script to automatically maintain your Technocore liveness and accumulate verifiable task execution records every morning. Operating within Google's free tier, it eliminates server maintenance fees and the need to keep your PC running 24/7.


🚀 Script Features

  1. Autonomous Cloud Execution Without 24/7 PC Operation:
    • Google's cloud infrastructure wakes up automatically every morning to process all tasks, requiring no local PC or phone to remain active.
  2. Zero Additional Costs Within Google Free Tier:
    • Operates entirely within Google's free account quotas, eliminating server hosting, proxy, or gas fee requirements.
  3. Zero Maintenance After Initial Setup:
    • Running the test execution once automatically handles DID creation, daily execution trigger registration, and spreadsheet setup.
  4. Visual Progress Tracking via Google Sheets:
    • Daily check-ins and task execution receipts are automatically logged to a spreadsheet in your Google Drive, accessible from any mobile device or browser.
  5. Automated Prevention of the 7-Day Reaper Rule:
    • Under official Technocore rules, any mailbox with zero message activity for 7 days is automatically purged by the system. This script sends a daily morning check-in to the public lobby to keep your account safely active. Each check-in includes dynamic timestamps and nonces, preventing it from being flagged as repetitive template spam.
  6. Official Anti-Sybil Defense via Peer Communication:
    • Official Protocol Specs: Technocore monitors traffic using IP-level token buckets along with algorithms measuring interaction diversity and response rates to filter out isolated bots and repetitive spam.
    • Our Implementation: Rather than operating as an isolated bot, workers exchange cryptographically signed messages across Google's distributed global IPs. This multi-party communication establishes verifiable, high-quality interaction history recognized by protocol algorithms.

📈 Network Topology: Increasing Proof Opportunities as More Peers Join

The official core team has explicitly affirmed plans to reward agents that coordinate work and cryptographically prove its completion.

This script operates as a coordinated distributed network through the Parent Gateway:

  • Expanded Task Pool as More Peers Join: As more peer workers register, the total pool of incoming defense task orders routed to the Parent Gateway expands.
  • Greater Opportunities for Proof of Contribution: Because pooled tasks are dispatched dynamically among registered workers, the larger the network of active peers, the more opportunities you receive to execute peer defense tasks and accumulate verifiable execution receipts.

🔒 3 Core Safety Design Principles for Peace of Mind

To ensure safe and reliable long-term operations, this script adheres to the following principles:

Caution

1. Fresh Dedicated DID Recommended

  • We strongly recommend operating with the fresh DID automatically generated upon initial launch.
  • In the unlikely event of Google account compromise, isolating that single dedicated DID protects your primary identities elsewhere.
  • (Advanced users requiring an existing DID may refer to FAQ: Migrating an Existing DID).

Caution

2. Never Hardcode or Share Your 64-Character Seed

  • To prevent unintended exposure, never paste your master private key into the script code, and do not share your GAS project with third parties.
  • Back up the 64-character seed generated in Step 4 to a secure password manager. Losing this seed revokes access to accumulated contributions.

Warning

3. Never Enter Crypto Wallet Recovery Phrases

  • Technocore Ed25519 seeds have zero relation to MetaMask or crypto wallet seed phrases. Never input wallet recovery phrases into any script or website.

🛡️ Privacy and Communication Security

  • Private Key Non-Disclosure: Under Ed25519 asymmetric cryptography, neither the Parent Gateway nor external servers can access your child DID private key. The master seed remains confined within your own Google environment, transmitting only detached cryptographic signatures and public DIDs.
  • LLM-Free Design Eliminating Prompt Injection Risk: Operates purely through Ed25519 cryptographic signatures and structured REST calls without natural language models, eliminating any remote command hijacking vectors.

📋 Security Checklist: What Can and Cannot Be Shared

Item Shareable? Description & Safe Handling
DID (e.g., did:key:z6Mkj...) Public ✅ Your public address (like an account number). Safe to share for status verification.
Mailbox (e.g., mb-p-runner-...) Public ✅ Room for receiving tasks and pings. Publicly writable, but cannot leak your private key.
Private Seed (TECHNOCORE_SEED_HEX) Private ❌ Primary 64-character identity seed. Never shared with the Gateway or third parties. Store securely.
Your GAS Project Script Private ❌ Keep your Google Apps Script project private to yourself to prevent unintended alterations.
Wallet Recovery Phrase (12/24 words) Do not enter ❌ Unrelated to Technocore. Never input or share anywhere under any circumstances.

Setup Instructions (4 Simple Steps)

Step 1: Pre-Deployment Security Audit via AI Agent (Recommended)

Never run unknown code blindly. We encourage you to pass the script to Claude Code, Cursor, ChatGPT, or your preferred AI tool to verify its safety before execution.

Tip

If you already understand the script's mechanics or wish to deploy immediately, you may proceed directly to Step 2: Create Project.

Audit Prompt Template

Please perform a security audit of the Google Apps Script code (02_gas_runner.js) published in this Gist:
Target URL: https://gist.github.com/rauchi07/0471c362003986cc2306a0ade3fd900c

This script is a community-built autonomous agent for Technocore ( https://technocore.chat ) using Ed25519 (did:key) signatures to perform periodic liveness check-ins and mutual peer defense pings.

[Key Audit Focus]
1. Does it contain malicious backdoors or unauthorized key exfiltration?
2. Are external requests strictly restricted to the official host ( https://technocore.chat ) without dynamic code execution (eval, new Function)?
3. Are incoming tasks properly validated against forged signatures (Ed25519)?
4. Are there any critical security flaws for unattended GAS execution?
* Do not request or hardcode any private keys or existing wallet seed phrases.

Step 2: Create Google Apps Script Project & Paste Code

  1. Navigate to Google Apps Script (script.google.com) in your browser.
  2. Click New Project in the top-left corner.
  3. Name your project (e.g., TechnoSwarm-Agent).
  4. Clear any existing code in the editor, and paste the entire code from 02_gas_runner.js (Gist).
  5. Click Save (floppy disk icon).

Note

Proceeding to Step 3 will automatically generate a dedicated production DID.


Step 3: Run Test Setup

  1. Select testRunner in the function dropdown at the top and click Run.
  2. Google will display a standard authorization modal on the first run. Click AdvancedGo to TechnoSwarm-Agent (unsafe)Allow.
  3. Verify that the execution log concludes with:
    === TechnoSwarm GAS Runner & Check-in Loop Starting ===
    🎉 Successfully generated and securely stored your production DID seed (Ed25519)!
    Your Production DID: did:key:z6Mkj... (Official DID ready)
    Dedicated Mailbox:   mb-p-runner-b96e...
    [✓] Daily mutual guard and anti-reaper check-in cycle completed successfully!
    📊 Mutual Guard Dashboard (Google Sheets): https://docs.google.com/spreadsheets/d/.../edit
    🎉 Daily automatic execution trigger (8:00 - 9:00 AM) registered successfully!
    

Tip

No manual trigger setup required
Running testRunner once automatically handles DID generation, initial check-in, 8:00–9:00 AM daily trigger setup, and Google Sheet creation.


Step 4: Back Up Your Master Private Seed

Safely extract and store your master seed:

  1. In the GAS editor, temporarily append the following 3 lines to the bottom of the script:
    function showMySeedForBackup() {
      Logger.log("🔐 YOUR MASTER SEED: " + PropertiesService.getUserProperties().getProperty("TECHNOCORE_SEED_HEX"));
    }
  2. Select showMySeedForBackup in the dropdown and click Run.
  3. Copy the 64-character seed hex from the log and store it in a secure password manager.
  4. Delete those 3 lines from your editor and click Save. This is a mandatory safety step to avoid leaving your key in code.

Live Dashboard & Event Logs

This script is not a persistent server daemon. It wakes up every morning (8:00–9:00 AM) via Google's free timer to process tasks in a single burst.

📊 How to Open Your Dashboard

  • Method A: Click the URL output at the end of testRunner logs (📊 Mutual Guard Dashboard:).
  • Method B: Open Google Drive to find TechnoSwarm Event Log (<Fingerprint>) created automatically.

📋 Event Actions and Roles

Action Name Direction Role & Purpose
Request Guard Task Me -> Gateway Order Self-Defense: Requests Gateway to dispatch peers to ping your DID.
Liveness Check-in Me -> Lobby Global Liveness Pulse: Posts signed heartbeat to public /r/lobby.
Register Worker Me -> Gateway Register Availability: Informs Gateway that you are online to execute peer guard tasks.
Guard Ping Received Peer -> Me Peer Ping Ingestion: Verified ping from a peer resets your 7-day reaper expiration timer.
Defend Peer Me -> Peer Peer Defense Execution: Executes peer guard task and returns signed receipt for contributions.

Note

The initial run records the first 3 events. As peer coordination proceeds, the bottom 2 events (Ping Received / Defend Peer) are logged automatically during daily runs.


Troubleshooting

HTTP 503: Service Unavailable

  • Cause: Temporary congestion on the official Technocore server.
  • Resolution: Automatic exponential backoff retries are built-in. If encountered during manual testing, wait 1–2 minutes and rerun testRunner. Daily scheduled runs will automatically recover on subsequent executions.

Frequently Asked Questions (FAQ)

Q: How much airdrop will I receive?

  • A: No guarantees or predictions can be made. All distribution criteria and allocations are entirely at the discretion of the Technocore / FLOP team. This script is an open-source utility for mutual defense automation and contribution tracking.

Q: Can I participate without an existing DID?

  • A: Yes. Running testRunner generates an official Ed25519 private key and W3C compliant DID automatically.

Q: Why does Google show an "Unsafe App" warning during authorization?

  • A: This is Google's standard developer consent screen whenever a user script initiates external HTTP requests (UrlFetch) or creates a Google Sheet. It executes solely within your personal Google account and transfers no permissions to any external party.

Q: Are there any costs involved? Does it run when my PC is off?

  • A: No, there are no costs, and it runs automatically even when your device is offline.
    GAS executes on Google's cloud servers without credit card requirements, completing the daily routine autonomously.

Q: Can I migrate an existing DID from CLI/Python?

  • A: (Discouraged for safety; fresh DID recommended) If strictly necessary, you can safely inject your seed directly into your UserProperties using a one-time function:
    1. After pasting the code in Step 2, temporarily append the following 3 lines to the bottom of the editor:
      function importMySeed() {
        PropertiesService.getUserProperties().setProperty("TECHNOCORE_SEED_HEX", "<your-64-character-hex-seed>");
      }
    2. Select importMySeed in the function dropdown and click Run.
    3. After execution, delete those 3 lines from your editor and click Save to prevent accidental exposure.
    4. Return to the function dropdown, select testRunner, and click Run.

Q: What happens if I clear or change the Gateway DID?

  • A: Leaving it blank or setting an invalid DID disables Gateway registration and peer defense tasks, falling back to standalone lobby check-ins only. Keeping the default Parent Gateway DID is required for mutual defense and contribution tracking.

Note

For official specifications and reward distribution mechanisms, refer to the Official FLOP / Technocore Documentation.

▲ Back to Top | 🇯🇵 日本語版へジャンプ

// ============================================================================
// Google Apps Script (GAS) Environment Compatibility Polyfill
// ============================================================================
var self = typeof globalThis !== 'undefined' ? globalThis : this;
var window = self;
// nacl-fast.js (Embedded TweetNaCl)
(function (nacl) {
'use strict';
// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri.
// Public domain.
//
// Implementation derived from TweetNaCl version 20140427.
// See for details: http://tweetnacl.cr.yp.to/
var gf = function (init) {
var i, r = new Float64Array(16);
if (init) for (i = 0; i < init.length; i++) r[i] = init[i];
return r;
};
// Pluggable, initialized in high-level API below.
var randombytes = function (/* x, n */) { throw new Error('no PRNG'); };
var _0 = new Uint8Array(16);
var _9 = new Uint8Array(32); _9[0] = 9;
var gf0 = gf(),
gf1 = gf([1]),
_121665 = gf([0xdb41, 1]),
D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]),
D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]),
X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]),
Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]),
I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]);
function ts64(x, i, h, l) {
x[i] = (h >> 24) & 0xff;
x[i + 1] = (h >> 16) & 0xff;
x[i + 2] = (h >> 8) & 0xff;
x[i + 3] = h & 0xff;
x[i + 4] = (l >> 24) & 0xff;
x[i + 5] = (l >> 16) & 0xff;
x[i + 6] = (l >> 8) & 0xff;
x[i + 7] = l & 0xff;
}
function vn(x, xi, y, yi, n) {
var i, d = 0;
for (i = 0; i < n; i++) d |= x[xi + i] ^ y[yi + i];
return (1 & ((d - 1) >>> 8)) - 1;
}
function crypto_verify_16(x, xi, y, yi) {
return vn(x, xi, y, yi, 16);
}
function crypto_verify_32(x, xi, y, yi) {
return vn(x, xi, y, yi, 32);
}
function core_salsa20(o, p, k, c) {
var j0 = c[0] & 0xff | (c[1] & 0xff) << 8 | (c[2] & 0xff) << 16 | (c[3] & 0xff) << 24,
j1 = k[0] & 0xff | (k[1] & 0xff) << 8 | (k[2] & 0xff) << 16 | (k[3] & 0xff) << 24,
j2 = k[4] & 0xff | (k[5] & 0xff) << 8 | (k[6] & 0xff) << 16 | (k[7] & 0xff) << 24,
j3 = k[8] & 0xff | (k[9] & 0xff) << 8 | (k[10] & 0xff) << 16 | (k[11] & 0xff) << 24,
j4 = k[12] & 0xff | (k[13] & 0xff) << 8 | (k[14] & 0xff) << 16 | (k[15] & 0xff) << 24,
j5 = c[4] & 0xff | (c[5] & 0xff) << 8 | (c[6] & 0xff) << 16 | (c[7] & 0xff) << 24,
j6 = p[0] & 0xff | (p[1] & 0xff) << 8 | (p[2] & 0xff) << 16 | (p[3] & 0xff) << 24,
j7 = p[4] & 0xff | (p[5] & 0xff) << 8 | (p[6] & 0xff) << 16 | (p[7] & 0xff) << 24,
j8 = p[8] & 0xff | (p[9] & 0xff) << 8 | (p[10] & 0xff) << 16 | (p[11] & 0xff) << 24,
j9 = p[12] & 0xff | (p[13] & 0xff) << 8 | (p[14] & 0xff) << 16 | (p[15] & 0xff) << 24,
j10 = c[8] & 0xff | (c[9] & 0xff) << 8 | (c[10] & 0xff) << 16 | (c[11] & 0xff) << 24,
j11 = k[16] & 0xff | (k[17] & 0xff) << 8 | (k[18] & 0xff) << 16 | (k[19] & 0xff) << 24,
j12 = k[20] & 0xff | (k[21] & 0xff) << 8 | (k[22] & 0xff) << 16 | (k[23] & 0xff) << 24,
j13 = k[24] & 0xff | (k[25] & 0xff) << 8 | (k[26] & 0xff) << 16 | (k[27] & 0xff) << 24,
j14 = k[28] & 0xff | (k[29] & 0xff) << 8 | (k[30] & 0xff) << 16 | (k[31] & 0xff) << 24,
j15 = c[12] & 0xff | (c[13] & 0xff) << 8 | (c[14] & 0xff) << 16 | (c[15] & 0xff) << 24;
var x0 = j0, x1 = j1, x2 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7,
x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14,
x15 = j15, u;
for (var i = 0; i < 20; i += 2) {
u = x0 + x12 | 0;
x4 ^= u << 7 | u >>> (32 - 7);
u = x4 + x0 | 0;
x8 ^= u << 9 | u >>> (32 - 9);
u = x8 + x4 | 0;
x12 ^= u << 13 | u >>> (32 - 13);
u = x12 + x8 | 0;
x0 ^= u << 18 | u >>> (32 - 18);
u = x5 + x1 | 0;
x9 ^= u << 7 | u >>> (32 - 7);
u = x9 + x5 | 0;
x13 ^= u << 9 | u >>> (32 - 9);
u = x13 + x9 | 0;
x1 ^= u << 13 | u >>> (32 - 13);
u = x1 + x13 | 0;
x5 ^= u << 18 | u >>> (32 - 18);
u = x10 + x6 | 0;
x14 ^= u << 7 | u >>> (32 - 7);
u = x14 + x10 | 0;
x2 ^= u << 9 | u >>> (32 - 9);
u = x2 + x14 | 0;
x6 ^= u << 13 | u >>> (32 - 13);
u = x6 + x2 | 0;
x10 ^= u << 18 | u >>> (32 - 18);
u = x15 + x11 | 0;
x3 ^= u << 7 | u >>> (32 - 7);
u = x3 + x15 | 0;
x7 ^= u << 9 | u >>> (32 - 9);
u = x7 + x3 | 0;
x11 ^= u << 13 | u >>> (32 - 13);
u = x11 + x7 | 0;
x15 ^= u << 18 | u >>> (32 - 18);
u = x0 + x3 | 0;
x1 ^= u << 7 | u >>> (32 - 7);
u = x1 + x0 | 0;
x2 ^= u << 9 | u >>> (32 - 9);
u = x2 + x1 | 0;
x3 ^= u << 13 | u >>> (32 - 13);
u = x3 + x2 | 0;
x0 ^= u << 18 | u >>> (32 - 18);
u = x5 + x4 | 0;
x6 ^= u << 7 | u >>> (32 - 7);
u = x6 + x5 | 0;
x7 ^= u << 9 | u >>> (32 - 9);
u = x7 + x6 | 0;
x4 ^= u << 13 | u >>> (32 - 13);
u = x4 + x7 | 0;
x5 ^= u << 18 | u >>> (32 - 18);
u = x10 + x9 | 0;
x11 ^= u << 7 | u >>> (32 - 7);
u = x11 + x10 | 0;
x8 ^= u << 9 | u >>> (32 - 9);
u = x8 + x11 | 0;
x9 ^= u << 13 | u >>> (32 - 13);
u = x9 + x8 | 0;
x10 ^= u << 18 | u >>> (32 - 18);
u = x15 + x14 | 0;
x12 ^= u << 7 | u >>> (32 - 7);
u = x12 + x15 | 0;
x13 ^= u << 9 | u >>> (32 - 9);
u = x13 + x12 | 0;
x14 ^= u << 13 | u >>> (32 - 13);
u = x14 + x13 | 0;
x15 ^= u << 18 | u >>> (32 - 18);
}
x0 = x0 + j0 | 0;
x1 = x1 + j1 | 0;
x2 = x2 + j2 | 0;
x3 = x3 + j3 | 0;
x4 = x4 + j4 | 0;
x5 = x5 + j5 | 0;
x6 = x6 + j6 | 0;
x7 = x7 + j7 | 0;
x8 = x8 + j8 | 0;
x9 = x9 + j9 | 0;
x10 = x10 + j10 | 0;
x11 = x11 + j11 | 0;
x12 = x12 + j12 | 0;
x13 = x13 + j13 | 0;
x14 = x14 + j14 | 0;
x15 = x15 + j15 | 0;
o[0] = x0 >>> 0 & 0xff;
o[1] = x0 >>> 8 & 0xff;
o[2] = x0 >>> 16 & 0xff;
o[3] = x0 >>> 24 & 0xff;
o[4] = x1 >>> 0 & 0xff;
o[5] = x1 >>> 8 & 0xff;
o[6] = x1 >>> 16 & 0xff;
o[7] = x1 >>> 24 & 0xff;
o[8] = x2 >>> 0 & 0xff;
o[9] = x2 >>> 8 & 0xff;
o[10] = x2 >>> 16 & 0xff;
o[11] = x2 >>> 24 & 0xff;
o[12] = x3 >>> 0 & 0xff;
o[13] = x3 >>> 8 & 0xff;
o[14] = x3 >>> 16 & 0xff;
o[15] = x3 >>> 24 & 0xff;
o[16] = x4 >>> 0 & 0xff;
o[17] = x4 >>> 8 & 0xff;
o[18] = x4 >>> 16 & 0xff;
o[19] = x4 >>> 24 & 0xff;
o[20] = x5 >>> 0 & 0xff;
o[21] = x5 >>> 8 & 0xff;
o[22] = x5 >>> 16 & 0xff;
o[23] = x5 >>> 24 & 0xff;
o[24] = x6 >>> 0 & 0xff;
o[25] = x6 >>> 8 & 0xff;
o[26] = x6 >>> 16 & 0xff;
o[27] = x6 >>> 24 & 0xff;
o[28] = x7 >>> 0 & 0xff;
o[29] = x7 >>> 8 & 0xff;
o[30] = x7 >>> 16 & 0xff;
o[31] = x7 >>> 24 & 0xff;
o[32] = x8 >>> 0 & 0xff;
o[33] = x8 >>> 8 & 0xff;
o[34] = x8 >>> 16 & 0xff;
o[35] = x8 >>> 24 & 0xff;
o[36] = x9 >>> 0 & 0xff;
o[37] = x9 >>> 8 & 0xff;
o[38] = x9 >>> 16 & 0xff;
o[39] = x9 >>> 24 & 0xff;
o[40] = x10 >>> 0 & 0xff;
o[41] = x10 >>> 8 & 0xff;
o[42] = x10 >>> 16 & 0xff;
o[43] = x10 >>> 24 & 0xff;
o[44] = x11 >>> 0 & 0xff;
o[45] = x11 >>> 8 & 0xff;
o[46] = x11 >>> 16 & 0xff;
o[47] = x11 >>> 24 & 0xff;
o[48] = x12 >>> 0 & 0xff;
o[49] = x12 >>> 8 & 0xff;
o[50] = x12 >>> 16 & 0xff;
o[51] = x12 >>> 24 & 0xff;
o[52] = x13 >>> 0 & 0xff;
o[53] = x13 >>> 8 & 0xff;
o[54] = x13 >>> 16 & 0xff;
o[55] = x13 >>> 24 & 0xff;
o[56] = x14 >>> 0 & 0xff;
o[57] = x14 >>> 8 & 0xff;
o[58] = x14 >>> 16 & 0xff;
o[59] = x14 >>> 24 & 0xff;
o[60] = x15 >>> 0 & 0xff;
o[61] = x15 >>> 8 & 0xff;
o[62] = x15 >>> 16 & 0xff;
o[63] = x15 >>> 24 & 0xff;
}
function core_hsalsa20(o, p, k, c) {
var j0 = c[0] & 0xff | (c[1] & 0xff) << 8 | (c[2] & 0xff) << 16 | (c[3] & 0xff) << 24,
j1 = k[0] & 0xff | (k[1] & 0xff) << 8 | (k[2] & 0xff) << 16 | (k[3] & 0xff) << 24,
j2 = k[4] & 0xff | (k[5] & 0xff) << 8 | (k[6] & 0xff) << 16 | (k[7] & 0xff) << 24,
j3 = k[8] & 0xff | (k[9] & 0xff) << 8 | (k[10] & 0xff) << 16 | (k[11] & 0xff) << 24,
j4 = k[12] & 0xff | (k[13] & 0xff) << 8 | (k[14] & 0xff) << 16 | (k[15] & 0xff) << 24,
j5 = c[4] & 0xff | (c[5] & 0xff) << 8 | (c[6] & 0xff) << 16 | (c[7] & 0xff) << 24,
j6 = p[0] & 0xff | (p[1] & 0xff) << 8 | (p[2] & 0xff) << 16 | (p[3] & 0xff) << 24,
j7 = p[4] & 0xff | (p[5] & 0xff) << 8 | (p[6] & 0xff) << 16 | (p[7] & 0xff) << 24,
j8 = p[8] & 0xff | (p[9] & 0xff) << 8 | (p[10] & 0xff) << 16 | (p[11] & 0xff) << 24,
j9 = p[12] & 0xff | (p[13] & 0xff) << 8 | (p[14] & 0xff) << 16 | (p[15] & 0xff) << 24,
j10 = c[8] & 0xff | (c[9] & 0xff) << 8 | (c[10] & 0xff) << 16 | (c[11] & 0xff) << 24,
j11 = k[16] & 0xff | (k[17] & 0xff) << 8 | (k[18] & 0xff) << 16 | (k[19] & 0xff) << 24,
j12 = k[20] & 0xff | (k[21] & 0xff) << 8 | (k[22] & 0xff) << 16 | (k[23] & 0xff) << 24,
j13 = k[24] & 0xff | (k[25] & 0xff) << 8 | (k[26] & 0xff) << 16 | (k[27] & 0xff) << 24,
j14 = k[28] & 0xff | (k[29] & 0xff) << 8 | (k[30] & 0xff) << 16 | (k[31] & 0xff) << 24,
j15 = c[12] & 0xff | (c[13] & 0xff) << 8 | (c[14] & 0xff) << 16 | (c[15] & 0xff) << 24;
var x0 = j0, x1 = j1, x2 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7,
x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14,
x15 = j15, u;
for (var i = 0; i < 20; i += 2) {
u = x0 + x12 | 0;
x4 ^= u << 7 | u >>> (32 - 7);
u = x4 + x0 | 0;
x8 ^= u << 9 | u >>> (32 - 9);
u = x8 + x4 | 0;
x12 ^= u << 13 | u >>> (32 - 13);
u = x12 + x8 | 0;
x0 ^= u << 18 | u >>> (32 - 18);
u = x5 + x1 | 0;
x9 ^= u << 7 | u >>> (32 - 7);
u = x9 + x5 | 0;
x13 ^= u << 9 | u >>> (32 - 9);
u = x13 + x9 | 0;
x1 ^= u << 13 | u >>> (32 - 13);
u = x1 + x13 | 0;
x5 ^= u << 18 | u >>> (32 - 18);
u = x10 + x6 | 0;
x14 ^= u << 7 | u >>> (32 - 7);
u = x14 + x10 | 0;
x2 ^= u << 9 | u >>> (32 - 9);
u = x2 + x14 | 0;
x6 ^= u << 13 | u >>> (32 - 13);
u = x6 + x2 | 0;
x10 ^= u << 18 | u >>> (32 - 18);
u = x15 + x11 | 0;
x3 ^= u << 7 | u >>> (32 - 7);
u = x3 + x15 | 0;
x7 ^= u << 9 | u >>> (32 - 9);
u = x7 + x3 | 0;
x11 ^= u << 13 | u >>> (32 - 13);
u = x11 + x7 | 0;
x15 ^= u << 18 | u >>> (32 - 18);
u = x0 + x3 | 0;
x1 ^= u << 7 | u >>> (32 - 7);
u = x1 + x0 | 0;
x2 ^= u << 9 | u >>> (32 - 9);
u = x2 + x1 | 0;
x3 ^= u << 13 | u >>> (32 - 13);
u = x3 + x2 | 0;
x0 ^= u << 18 | u >>> (32 - 18);
u = x5 + x4 | 0;
x6 ^= u << 7 | u >>> (32 - 7);
u = x6 + x5 | 0;
x7 ^= u << 9 | u >>> (32 - 9);
u = x7 + x6 | 0;
x4 ^= u << 13 | u >>> (32 - 13);
u = x4 + x7 | 0;
x5 ^= u << 18 | u >>> (32 - 18);
u = x10 + x9 | 0;
x11 ^= u << 7 | u >>> (32 - 7);
u = x11 + x10 | 0;
x8 ^= u << 9 | u >>> (32 - 9);
u = x8 + x11 | 0;
x9 ^= u << 13 | u >>> (32 - 13);
u = x9 + x8 | 0;
x10 ^= u << 18 | u >>> (32 - 18);
u = x15 + x14 | 0;
x12 ^= u << 7 | u >>> (32 - 7);
u = x12 + x15 | 0;
x13 ^= u << 9 | u >>> (32 - 9);
u = x13 + x12 | 0;
x14 ^= u << 13 | u >>> (32 - 13);
u = x14 + x13 | 0;
x15 ^= u << 18 | u >>> (32 - 18);
}
o[0] = x0 >>> 0 & 0xff;
o[1] = x0 >>> 8 & 0xff;
o[2] = x0 >>> 16 & 0xff;
o[3] = x0 >>> 24 & 0xff;
o[4] = x5 >>> 0 & 0xff;
o[5] = x5 >>> 8 & 0xff;
o[6] = x5 >>> 16 & 0xff;
o[7] = x5 >>> 24 & 0xff;
o[8] = x10 >>> 0 & 0xff;
o[9] = x10 >>> 8 & 0xff;
o[10] = x10 >>> 16 & 0xff;
o[11] = x10 >>> 24 & 0xff;
o[12] = x15 >>> 0 & 0xff;
o[13] = x15 >>> 8 & 0xff;
o[14] = x15 >>> 16 & 0xff;
o[15] = x15 >>> 24 & 0xff;
o[16] = x6 >>> 0 & 0xff;
o[17] = x6 >>> 8 & 0xff;
o[18] = x6 >>> 16 & 0xff;
o[19] = x6 >>> 24 & 0xff;
o[20] = x7 >>> 0 & 0xff;
o[21] = x7 >>> 8 & 0xff;
o[22] = x7 >>> 16 & 0xff;
o[23] = x7 >>> 24 & 0xff;
o[24] = x8 >>> 0 & 0xff;
o[25] = x8 >>> 8 & 0xff;
o[26] = x8 >>> 16 & 0xff;
o[27] = x8 >>> 24 & 0xff;
o[28] = x9 >>> 0 & 0xff;
o[29] = x9 >>> 8 & 0xff;
o[30] = x9 >>> 16 & 0xff;
o[31] = x9 >>> 24 & 0xff;
}
function crypto_core_salsa20(out, inp, k, c) {
core_salsa20(out, inp, k, c);
}
function crypto_core_hsalsa20(out, inp, k, c) {
core_hsalsa20(out, inp, k, c);
}
var sigma = new Uint8Array([101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107]);
// "expand 32-byte k"
function crypto_stream_salsa20_xor(c, cpos, m, mpos, b, n, k) {
var z = new Uint8Array(16), x = new Uint8Array(64);
var u, i;
for (i = 0; i < 16; i++) z[i] = 0;
for (i = 0; i < 8; i++) z[i] = n[i];
while (b >= 64) {
crypto_core_salsa20(x, z, k, sigma);
for (i = 0; i < 64; i++) c[cpos + i] = m[mpos + i] ^ x[i];
u = 1;
for (i = 8; i < 16; i++) {
u = u + (z[i] & 0xff) | 0;
z[i] = u & 0xff;
u >>>= 8;
}
b -= 64;
cpos += 64;
mpos += 64;
}
if (b > 0) {
crypto_core_salsa20(x, z, k, sigma);
for (i = 0; i < b; i++) c[cpos + i] = m[mpos + i] ^ x[i];
}
return 0;
}
function crypto_stream_salsa20(c, cpos, b, n, k) {
var z = new Uint8Array(16), x = new Uint8Array(64);
var u, i;
for (i = 0; i < 16; i++) z[i] = 0;
for (i = 0; i < 8; i++) z[i] = n[i];
while (b >= 64) {
crypto_core_salsa20(x, z, k, sigma);
for (i = 0; i < 64; i++) c[cpos + i] = x[i];
u = 1;
for (i = 8; i < 16; i++) {
u = u + (z[i] & 0xff) | 0;
z[i] = u & 0xff;
u >>>= 8;
}
b -= 64;
cpos += 64;
}
if (b > 0) {
crypto_core_salsa20(x, z, k, sigma);
for (i = 0; i < b; i++) c[cpos + i] = x[i];
}
return 0;
}
function crypto_stream(c, cpos, d, n, k) {
var s = new Uint8Array(32);
crypto_core_hsalsa20(s, n, k, sigma);
var sn = new Uint8Array(8);
for (var i = 0; i < 8; i++) sn[i] = n[i + 16];
return crypto_stream_salsa20(c, cpos, d, sn, s);
}
function crypto_stream_xor(c, cpos, m, mpos, d, n, k) {
var s = new Uint8Array(32);
crypto_core_hsalsa20(s, n, k, sigma);
var sn = new Uint8Array(8);
for (var i = 0; i < 8; i++) sn[i] = n[i + 16];
return crypto_stream_salsa20_xor(c, cpos, m, mpos, d, sn, s);
}
/*
* Port of Andrew Moon's Poly1305-donna-16. Public domain.
* https://github.com/floodyberry/poly1305-donna
*/
var poly1305 = function (key) {
this.buffer = new Uint8Array(16);
this.r = new Uint16Array(10);
this.h = new Uint16Array(10);
this.pad = new Uint16Array(8);
this.leftover = 0;
this.fin = 0;
var t0, t1, t2, t3, t4, t5, t6, t7;
t0 = key[0] & 0xff | (key[1] & 0xff) << 8; this.r[0] = (t0) & 0x1fff;
t1 = key[2] & 0xff | (key[3] & 0xff) << 8; this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
t2 = key[4] & 0xff | (key[5] & 0xff) << 8; this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03;
t3 = key[6] & 0xff | (key[7] & 0xff) << 8; this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
t4 = key[8] & 0xff | (key[9] & 0xff) << 8; this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff;
this.r[5] = ((t4 >>> 1)) & 0x1ffe;
t5 = key[10] & 0xff | (key[11] & 0xff) << 8; this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
t6 = key[12] & 0xff | (key[13] & 0xff) << 8; this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81;
t7 = key[14] & 0xff | (key[15] & 0xff) << 8; this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
this.r[9] = ((t7 >>> 5)) & 0x007f;
this.pad[0] = key[16] & 0xff | (key[17] & 0xff) << 8;
this.pad[1] = key[18] & 0xff | (key[19] & 0xff) << 8;
this.pad[2] = key[20] & 0xff | (key[21] & 0xff) << 8;
this.pad[3] = key[22] & 0xff | (key[23] & 0xff) << 8;
this.pad[4] = key[24] & 0xff | (key[25] & 0xff) << 8;
this.pad[5] = key[26] & 0xff | (key[27] & 0xff) << 8;
this.pad[6] = key[28] & 0xff | (key[29] & 0xff) << 8;
this.pad[7] = key[30] & 0xff | (key[31] & 0xff) << 8;
};
poly1305.prototype.blocks = function (m, mpos, bytes) {
var hibit = this.fin ? 0 : (1 << 11);
var t0, t1, t2, t3, t4, t5, t6, t7, c;
var d0, d1, d2, d3, d4, d5, d6, d7, d8, d9;
var h0 = this.h[0],
h1 = this.h[1],
h2 = this.h[2],
h3 = this.h[3],
h4 = this.h[4],
h5 = this.h[5],
h6 = this.h[6],
h7 = this.h[7],
h8 = this.h[8],
h9 = this.h[9];
var r0 = this.r[0],
r1 = this.r[1],
r2 = this.r[2],
r3 = this.r[3],
r4 = this.r[4],
r5 = this.r[5],
r6 = this.r[6],
r7 = this.r[7],
r8 = this.r[8],
r9 = this.r[9];
while (bytes >= 16) {
t0 = m[mpos + 0] & 0xff | (m[mpos + 1] & 0xff) << 8; h0 += (t0) & 0x1fff;
t1 = m[mpos + 2] & 0xff | (m[mpos + 3] & 0xff) << 8; h1 += ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
t2 = m[mpos + 4] & 0xff | (m[mpos + 5] & 0xff) << 8; h2 += ((t1 >>> 10) | (t2 << 6)) & 0x1fff;
t3 = m[mpos + 6] & 0xff | (m[mpos + 7] & 0xff) << 8; h3 += ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
t4 = m[mpos + 8] & 0xff | (m[mpos + 9] & 0xff) << 8; h4 += ((t3 >>> 4) | (t4 << 12)) & 0x1fff;
h5 += ((t4 >>> 1)) & 0x1fff;
t5 = m[mpos + 10] & 0xff | (m[mpos + 11] & 0xff) << 8; h6 += ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
t6 = m[mpos + 12] & 0xff | (m[mpos + 13] & 0xff) << 8; h7 += ((t5 >>> 11) | (t6 << 5)) & 0x1fff;
t7 = m[mpos + 14] & 0xff | (m[mpos + 15] & 0xff) << 8; h8 += ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
h9 += ((t7 >>> 5)) | hibit;
c = 0;
d0 = c;
d0 += h0 * r0;
d0 += h1 * (5 * r9);
d0 += h2 * (5 * r8);
d0 += h3 * (5 * r7);
d0 += h4 * (5 * r6);
c = (d0 >>> 13); d0 &= 0x1fff;
d0 += h5 * (5 * r5);
d0 += h6 * (5 * r4);
d0 += h7 * (5 * r3);
d0 += h8 * (5 * r2);
d0 += h9 * (5 * r1);
c += (d0 >>> 13); d0 &= 0x1fff;
d1 = c;
d1 += h0 * r1;
d1 += h1 * r0;
d1 += h2 * (5 * r9);
d1 += h3 * (5 * r8);
d1 += h4 * (5 * r7);
c = (d1 >>> 13); d1 &= 0x1fff;
d1 += h5 * (5 * r6);
d1 += h6 * (5 * r5);
d1 += h7 * (5 * r4);
d1 += h8 * (5 * r3);
d1 += h9 * (5 * r2);
c += (d1 >>> 13); d1 &= 0x1fff;
d2 = c;
d2 += h0 * r2;
d2 += h1 * r1;
d2 += h2 * r0;
d2 += h3 * (5 * r9);
d2 += h4 * (5 * r8);
c = (d2 >>> 13); d2 &= 0x1fff;
d2 += h5 * (5 * r7);
d2 += h6 * (5 * r6);
d2 += h7 * (5 * r5);
d2 += h8 * (5 * r4);
d2 += h9 * (5 * r3);
c += (d2 >>> 13); d2 &= 0x1fff;
d3 = c;
d3 += h0 * r3;
d3 += h1 * r2;
d3 += h2 * r1;
d3 += h3 * r0;
d3 += h4 * (5 * r9);
c = (d3 >>> 13); d3 &= 0x1fff;
d3 += h5 * (5 * r8);
d3 += h6 * (5 * r7);
d3 += h7 * (5 * r6);
d3 += h8 * (5 * r5);
d3 += h9 * (5 * r4);
c += (d3 >>> 13); d3 &= 0x1fff;
d4 = c;
d4 += h0 * r4;
d4 += h1 * r3;
d4 += h2 * r2;
d4 += h3 * r1;
d4 += h4 * r0;
c = (d4 >>> 13); d4 &= 0x1fff;
d4 += h5 * (5 * r9);
d4 += h6 * (5 * r8);
d4 += h7 * (5 * r7);
d4 += h8 * (5 * r6);
d4 += h9 * (5 * r5);
c += (d4 >>> 13); d4 &= 0x1fff;
d5 = c;
d5 += h0 * r5;
d5 += h1 * r4;
d5 += h2 * r3;
d5 += h3 * r2;
d5 += h4 * r1;
c = (d5 >>> 13); d5 &= 0x1fff;
d5 += h5 * r0;
d5 += h6 * (5 * r9);
d5 += h7 * (5 * r8);
d5 += h8 * (5 * r7);
d5 += h9 * (5 * r6);
c += (d5 >>> 13); d5 &= 0x1fff;
d6 = c;
d6 += h0 * r6;
d6 += h1 * r5;
d6 += h2 * r4;
d6 += h3 * r3;
d6 += h4 * r2;
c = (d6 >>> 13); d6 &= 0x1fff;
d6 += h5 * r1;
d6 += h6 * r0;
d6 += h7 * (5 * r9);
d6 += h8 * (5 * r8);
d6 += h9 * (5 * r7);
c += (d6 >>> 13); d6 &= 0x1fff;
d7 = c;
d7 += h0 * r7;
d7 += h1 * r6;
d7 += h2 * r5;
d7 += h3 * r4;
d7 += h4 * r3;
c = (d7 >>> 13); d7 &= 0x1fff;
d7 += h5 * r2;
d7 += h6 * r1;
d7 += h7 * r0;
d7 += h8 * (5 * r9);
d7 += h9 * (5 * r8);
c += (d7 >>> 13); d7 &= 0x1fff;
d8 = c;
d8 += h0 * r8;
d8 += h1 * r7;
d8 += h2 * r6;
d8 += h3 * r5;
d8 += h4 * r4;
c = (d8 >>> 13); d8 &= 0x1fff;
d8 += h5 * r3;
d8 += h6 * r2;
d8 += h7 * r1;
d8 += h8 * r0;
d8 += h9 * (5 * r9);
c += (d8 >>> 13); d8 &= 0x1fff;
d9 = c;
d9 += h0 * r9;
d9 += h1 * r8;
d9 += h2 * r7;
d9 += h3 * r6;
d9 += h4 * r5;
c = (d9 >>> 13); d9 &= 0x1fff;
d9 += h5 * r4;
d9 += h6 * r3;
d9 += h7 * r2;
d9 += h8 * r1;
d9 += h9 * r0;
c += (d9 >>> 13); d9 &= 0x1fff;
c = (((c << 2) + c)) | 0;
c = (c + d0) | 0;
d0 = c & 0x1fff;
c = (c >>> 13);
d1 += c;
h0 = d0;
h1 = d1;
h2 = d2;
h3 = d3;
h4 = d4;
h5 = d5;
h6 = d6;
h7 = d7;
h8 = d8;
h9 = d9;
mpos += 16;
bytes -= 16;
}
this.h[0] = h0;
this.h[1] = h1;
this.h[2] = h2;
this.h[3] = h3;
this.h[4] = h4;
this.h[5] = h5;
this.h[6] = h6;
this.h[7] = h7;
this.h[8] = h8;
this.h[9] = h9;
};
poly1305.prototype.finish = function (mac, macpos) {
var g = new Uint16Array(10);
var c, mask, f, i;
if (this.leftover) {
i = this.leftover;
this.buffer[i++] = 1;
for (; i < 16; i++) this.buffer[i] = 0;
this.fin = 1;
this.blocks(this.buffer, 0, 16);
}
c = this.h[1] >>> 13;
this.h[1] &= 0x1fff;
for (i = 2; i < 10; i++) {
this.h[i] += c;
c = this.h[i] >>> 13;
this.h[i] &= 0x1fff;
}
this.h[0] += (c * 5);
c = this.h[0] >>> 13;
this.h[0] &= 0x1fff;
this.h[1] += c;
c = this.h[1] >>> 13;
this.h[1] &= 0x1fff;
this.h[2] += c;
g[0] = this.h[0] + 5;
c = g[0] >>> 13;
g[0] &= 0x1fff;
for (i = 1; i < 10; i++) {
g[i] = this.h[i] + c;
c = g[i] >>> 13;
g[i] &= 0x1fff;
}
g[9] -= (1 << 13);
mask = (c ^ 1) - 1;
for (i = 0; i < 10; i++) g[i] &= mask;
mask = ~mask;
for (i = 0; i < 10; i++) this.h[i] = (this.h[i] & mask) | g[i];
this.h[0] = ((this.h[0]) | (this.h[1] << 13)) & 0xffff;
this.h[1] = ((this.h[1] >>> 3) | (this.h[2] << 10)) & 0xffff;
this.h[2] = ((this.h[2] >>> 6) | (this.h[3] << 7)) & 0xffff;
this.h[3] = ((this.h[3] >>> 9) | (this.h[4] << 4)) & 0xffff;
this.h[4] = ((this.h[4] >>> 12) | (this.h[5] << 1) | (this.h[6] << 14)) & 0xffff;
this.h[5] = ((this.h[6] >>> 2) | (this.h[7] << 11)) & 0xffff;
this.h[6] = ((this.h[7] >>> 5) | (this.h[8] << 8)) & 0xffff;
this.h[7] = ((this.h[8] >>> 8) | (this.h[9] << 5)) & 0xffff;
f = this.h[0] + this.pad[0];
this.h[0] = f & 0xffff;
for (i = 1; i < 8; i++) {
f = (((this.h[i] + this.pad[i]) | 0) + (f >>> 16)) | 0;
this.h[i] = f & 0xffff;
}
mac[macpos + 0] = (this.h[0] >>> 0) & 0xff;
mac[macpos + 1] = (this.h[0] >>> 8) & 0xff;
mac[macpos + 2] = (this.h[1] >>> 0) & 0xff;
mac[macpos + 3] = (this.h[1] >>> 8) & 0xff;
mac[macpos + 4] = (this.h[2] >>> 0) & 0xff;
mac[macpos + 5] = (this.h[2] >>> 8) & 0xff;
mac[macpos + 6] = (this.h[3] >>> 0) & 0xff;
mac[macpos + 7] = (this.h[3] >>> 8) & 0xff;
mac[macpos + 8] = (this.h[4] >>> 0) & 0xff;
mac[macpos + 9] = (this.h[4] >>> 8) & 0xff;
mac[macpos + 10] = (this.h[5] >>> 0) & 0xff;
mac[macpos + 11] = (this.h[5] >>> 8) & 0xff;
mac[macpos + 12] = (this.h[6] >>> 0) & 0xff;
mac[macpos + 13] = (this.h[6] >>> 8) & 0xff;
mac[macpos + 14] = (this.h[7] >>> 0) & 0xff;
mac[macpos + 15] = (this.h[7] >>> 8) & 0xff;
};
poly1305.prototype.update = function (m, mpos, bytes) {
var i, want;
if (this.leftover) {
want = (16 - this.leftover);
if (want > bytes)
want = bytes;
for (i = 0; i < want; i++)
this.buffer[this.leftover + i] = m[mpos + i];
bytes -= want;
mpos += want;
this.leftover += want;
if (this.leftover < 16)
return;
this.blocks(this.buffer, 0, 16);
this.leftover = 0;
}
if (bytes >= 16) {
want = bytes - (bytes % 16);
this.blocks(m, mpos, want);
mpos += want;
bytes -= want;
}
if (bytes) {
for (i = 0; i < bytes; i++)
this.buffer[this.leftover + i] = m[mpos + i];
this.leftover += bytes;
}
};
function crypto_onetimeauth(out, outpos, m, mpos, n, k) {
var s = new poly1305(k);
s.update(m, mpos, n);
s.finish(out, outpos);
return 0;
}
function crypto_onetimeauth_verify(h, hpos, m, mpos, n, k) {
var x = new Uint8Array(16);
crypto_onetimeauth(x, 0, m, mpos, n, k);
return crypto_verify_16(h, hpos, x, 0);
}
function crypto_secretbox(c, m, d, n, k) {
var i;
if (d < 32) return -1;
crypto_stream_xor(c, 0, m, 0, d, n, k);
crypto_onetimeauth(c, 16, c, 32, d - 32, c);
for (i = 0; i < 16; i++) c[i] = 0;
return 0;
}
function crypto_secretbox_open(m, c, d, n, k) {
var i;
var x = new Uint8Array(32);
if (d < 32) return -1;
crypto_stream(x, 0, 32, n, k);
if (crypto_onetimeauth_verify(c, 16, c, 32, d - 32, x) !== 0) return -1;
crypto_stream_xor(m, 0, c, 0, d, n, k);
for (i = 0; i < 32; i++) m[i] = 0;
return 0;
}
function set25519(r, a) {
var i;
for (i = 0; i < 16; i++) r[i] = a[i] | 0;
}
function car25519(o) {
var i, v, c = 1;
for (i = 0; i < 16; i++) {
v = o[i] + c + 65535;
c = Math.floor(v / 65536);
o[i] = v - c * 65536;
}
o[0] += c - 1 + 37 * (c - 1);
}
function sel25519(p, q, b) {
var t, c = ~(b - 1);
for (var i = 0; i < 16; i++) {
t = c & (p[i] ^ q[i]);
p[i] ^= t;
q[i] ^= t;
}
}
function pack25519(o, n) {
var i, j, b;
var m = gf(), t = gf();
for (i = 0; i < 16; i++) t[i] = n[i];
car25519(t);
car25519(t);
car25519(t);
for (j = 0; j < 2; j++) {
m[0] = t[0] - 0xffed;
for (i = 1; i < 15; i++) {
m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
m[i - 1] &= 0xffff;
}
m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
b = (m[15] >> 16) & 1;
m[14] &= 0xffff;
sel25519(t, m, 1 - b);
}
for (i = 0; i < 16; i++) {
o[2 * i] = t[i] & 0xff;
o[2 * i + 1] = t[i] >> 8;
}
}
function neq25519(a, b) {
var c = new Uint8Array(32), d = new Uint8Array(32);
pack25519(c, a);
pack25519(d, b);
return crypto_verify_32(c, 0, d, 0);
}
function par25519(a) {
var d = new Uint8Array(32);
pack25519(d, a);
return d[0] & 1;
}
function unpack25519(o, n) {
var i;
for (i = 0; i < 16; i++) o[i] = n[2 * i] + (n[2 * i + 1] << 8);
o[15] &= 0x7fff;
}
function A(o, a, b) {
for (var i = 0; i < 16; i++) o[i] = a[i] + b[i];
}
function Z(o, a, b) {
for (var i = 0; i < 16; i++) o[i] = a[i] - b[i];
}
function M(o, a, b) {
var v, c,
t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0,
t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0,
t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0,
t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0,
b0 = b[0],
b1 = b[1],
b2 = b[2],
b3 = b[3],
b4 = b[4],
b5 = b[5],
b6 = b[6],
b7 = b[7],
b8 = b[8],
b9 = b[9],
b10 = b[10],
b11 = b[11],
b12 = b[12],
b13 = b[13],
b14 = b[14],
b15 = b[15];
v = a[0];
t0 += v * b0;
t1 += v * b1;
t2 += v * b2;
t3 += v * b3;
t4 += v * b4;
t5 += v * b5;
t6 += v * b6;
t7 += v * b7;
t8 += v * b8;
t9 += v * b9;
t10 += v * b10;
t11 += v * b11;
t12 += v * b12;
t13 += v * b13;
t14 += v * b14;
t15 += v * b15;
v = a[1];
t1 += v * b0;
t2 += v * b1;
t3 += v * b2;
t4 += v * b3;
t5 += v * b4;
t6 += v * b5;
t7 += v * b6;
t8 += v * b7;
t9 += v * b8;
t10 += v * b9;
t11 += v * b10;
t12 += v * b11;
t13 += v * b12;
t14 += v * b13;
t15 += v * b14;
t16 += v * b15;
v = a[2];
t2 += v * b0;
t3 += v * b1;
t4 += v * b2;
t5 += v * b3;
t6 += v * b4;
t7 += v * b5;
t8 += v * b6;
t9 += v * b7;
t10 += v * b8;
t11 += v * b9;
t12 += v * b10;
t13 += v * b11;
t14 += v * b12;
t15 += v * b13;
t16 += v * b14;
t17 += v * b15;
v = a[3];
t3 += v * b0;
t4 += v * b1;
t5 += v * b2;
t6 += v * b3;
t7 += v * b4;
t8 += v * b5;
t9 += v * b6;
t10 += v * b7;
t11 += v * b8;
t12 += v * b9;
t13 += v * b10;
t14 += v * b11;
t15 += v * b12;
t16 += v * b13;
t17 += v * b14;
t18 += v * b15;
v = a[4];
t4 += v * b0;
t5 += v * b1;
t6 += v * b2;
t7 += v * b3;
t8 += v * b4;
t9 += v * b5;
t10 += v * b6;
t11 += v * b7;
t12 += v * b8;
t13 += v * b9;
t14 += v * b10;
t15 += v * b11;
t16 += v * b12;
t17 += v * b13;
t18 += v * b14;
t19 += v * b15;
v = a[5];
t5 += v * b0;
t6 += v * b1;
t7 += v * b2;
t8 += v * b3;
t9 += v * b4;
t10 += v * b5;
t11 += v * b6;
t12 += v * b7;
t13 += v * b8;
t14 += v * b9;
t15 += v * b10;
t16 += v * b11;
t17 += v * b12;
t18 += v * b13;
t19 += v * b14;
t20 += v * b15;
v = a[6];
t6 += v * b0;
t7 += v * b1;
t8 += v * b2;
t9 += v * b3;
t10 += v * b4;
t11 += v * b5;
t12 += v * b6;
t13 += v * b7;
t14 += v * b8;
t15 += v * b9;
t16 += v * b10;
t17 += v * b11;
t18 += v * b12;
t19 += v * b13;
t20 += v * b14;
t21 += v * b15;
v = a[7];
t7 += v * b0;
t8 += v * b1;
t9 += v * b2;
t10 += v * b3;
t11 += v * b4;
t12 += v * b5;
t13 += v * b6;
t14 += v * b7;
t15 += v * b8;
t16 += v * b9;
t17 += v * b10;
t18 += v * b11;
t19 += v * b12;
t20 += v * b13;
t21 += v * b14;
t22 += v * b15;
v = a[8];
t8 += v * b0;
t9 += v * b1;
t10 += v * b2;
t11 += v * b3;
t12 += v * b4;
t13 += v * b5;
t14 += v * b6;
t15 += v * b7;
t16 += v * b8;
t17 += v * b9;
t18 += v * b10;
t19 += v * b11;
t20 += v * b12;
t21 += v * b13;
t22 += v * b14;
t23 += v * b15;
v = a[9];
t9 += v * b0;
t10 += v * b1;
t11 += v * b2;
t12 += v * b3;
t13 += v * b4;
t14 += v * b5;
t15 += v * b6;
t16 += v * b7;
t17 += v * b8;
t18 += v * b9;
t19 += v * b10;
t20 += v * b11;
t21 += v * b12;
t22 += v * b13;
t23 += v * b14;
t24 += v * b15;
v = a[10];
t10 += v * b0;
t11 += v * b1;
t12 += v * b2;
t13 += v * b3;
t14 += v * b4;
t15 += v * b5;
t16 += v * b6;
t17 += v * b7;
t18 += v * b8;
t19 += v * b9;
t20 += v * b10;
t21 += v * b11;
t22 += v * b12;
t23 += v * b13;
t24 += v * b14;
t25 += v * b15;
v = a[11];
t11 += v * b0;
t12 += v * b1;
t13 += v * b2;
t14 += v * b3;
t15 += v * b4;
t16 += v * b5;
t17 += v * b6;
t18 += v * b7;
t19 += v * b8;
t20 += v * b9;
t21 += v * b10;
t22 += v * b11;
t23 += v * b12;
t24 += v * b13;
t25 += v * b14;
t26 += v * b15;
v = a[12];
t12 += v * b0;
t13 += v * b1;
t14 += v * b2;
t15 += v * b3;
t16 += v * b4;
t17 += v * b5;
t18 += v * b6;
t19 += v * b7;
t20 += v * b8;
t21 += v * b9;
t22 += v * b10;
t23 += v * b11;
t24 += v * b12;
t25 += v * b13;
t26 += v * b14;
t27 += v * b15;
v = a[13];
t13 += v * b0;
t14 += v * b1;
t15 += v * b2;
t16 += v * b3;
t17 += v * b4;
t18 += v * b5;
t19 += v * b6;
t20 += v * b7;
t21 += v * b8;
t22 += v * b9;
t23 += v * b10;
t24 += v * b11;
t25 += v * b12;
t26 += v * b13;
t27 += v * b14;
t28 += v * b15;
v = a[14];
t14 += v * b0;
t15 += v * b1;
t16 += v * b2;
t17 += v * b3;
t18 += v * b4;
t19 += v * b5;
t20 += v * b6;
t21 += v * b7;
t22 += v * b8;
t23 += v * b9;
t24 += v * b10;
t25 += v * b11;
t26 += v * b12;
t27 += v * b13;
t28 += v * b14;
t29 += v * b15;
v = a[15];
t15 += v * b0;
t16 += v * b1;
t17 += v * b2;
t18 += v * b3;
t19 += v * b4;
t20 += v * b5;
t21 += v * b6;
t22 += v * b7;
t23 += v * b8;
t24 += v * b9;
t25 += v * b10;
t26 += v * b11;
t27 += v * b12;
t28 += v * b13;
t29 += v * b14;
t30 += v * b15;
t0 += 38 * t16;
t1 += 38 * t17;
t2 += 38 * t18;
t3 += 38 * t19;
t4 += 38 * t20;
t5 += 38 * t21;
t6 += 38 * t22;
t7 += 38 * t23;
t8 += 38 * t24;
t9 += 38 * t25;
t10 += 38 * t26;
t11 += 38 * t27;
t12 += 38 * t28;
t13 += 38 * t29;
t14 += 38 * t30;
// t15 left as is
// first car
c = 1;
v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536;
v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536;
v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536;
v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536;
v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536;
v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536;
v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536;
v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536;
v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536;
v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536;
v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
t0 += c - 1 + 37 * (c - 1);
// second car
c = 1;
v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536;
v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536;
v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536;
v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536;
v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536;
v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536;
v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536;
v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536;
v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536;
v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536;
v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
t0 += c - 1 + 37 * (c - 1);
o[0] = t0;
o[1] = t1;
o[2] = t2;
o[3] = t3;
o[4] = t4;
o[5] = t5;
o[6] = t6;
o[7] = t7;
o[8] = t8;
o[9] = t9;
o[10] = t10;
o[11] = t11;
o[12] = t12;
o[13] = t13;
o[14] = t14;
o[15] = t15;
}
function S(o, a) {
M(o, a, a);
}
function inv25519(o, i) {
var c = gf();
var a;
for (a = 0; a < 16; a++) c[a] = i[a];
for (a = 253; a >= 0; a--) {
S(c, c);
if (a !== 2 && a !== 4) M(c, c, i);
}
for (a = 0; a < 16; a++) o[a] = c[a];
}
function pow2523(o, i) {
var c = gf();
var a;
for (a = 0; a < 16; a++) c[a] = i[a];
for (a = 250; a >= 0; a--) {
S(c, c);
if (a !== 1) M(c, c, i);
}
for (a = 0; a < 16; a++) o[a] = c[a];
}
function crypto_scalarmult(q, n, p) {
var z = new Uint8Array(32);
var x = new Float64Array(80), r, i;
var a = gf(), b = gf(), c = gf(),
d = gf(), e = gf(), f = gf();
for (i = 0; i < 31; i++) z[i] = n[i];
z[31] = (n[31] & 127) | 64;
z[0] &= 248;
unpack25519(x, p);
for (i = 0; i < 16; i++) {
b[i] = x[i];
d[i] = a[i] = c[i] = 0;
}
a[0] = d[0] = 1;
for (i = 254; i >= 0; --i) {
r = (z[i >>> 3] >>> (i & 7)) & 1;
sel25519(a, b, r);
sel25519(c, d, r);
A(e, a, c);
Z(a, a, c);
A(c, b, d);
Z(b, b, d);
S(d, e);
S(f, a);
M(a, c, a);
M(c, b, e);
A(e, a, c);
Z(a, a, c);
S(b, a);
Z(c, d, f);
M(a, c, _121665);
A(a, a, d);
M(c, c, a);
M(a, d, f);
M(d, b, x);
S(b, e);
sel25519(a, b, r);
sel25519(c, d, r);
}
for (i = 0; i < 16; i++) {
x[i + 16] = a[i];
x[i + 32] = c[i];
x[i + 48] = b[i];
x[i + 64] = d[i];
}
var x32 = x.subarray(32);
var x16 = x.subarray(16);
inv25519(x32, x32);
M(x16, x16, x32);
pack25519(q, x16);
return 0;
}
function crypto_scalarmult_base(q, n) {
return crypto_scalarmult(q, n, _9);
}
function crypto_box_keypair(y, x) {
randombytes(x, 32);
return crypto_scalarmult_base(y, x);
}
function crypto_box_beforenm(k, y, x) {
var s = new Uint8Array(32);
crypto_scalarmult(s, x, y);
return crypto_core_hsalsa20(k, _0, s, sigma);
}
var crypto_box_afternm = crypto_secretbox;
var crypto_box_open_afternm = crypto_secretbox_open;
function crypto_box(c, m, d, n, y, x) {
var k = new Uint8Array(32);
crypto_box_beforenm(k, y, x);
return crypto_box_afternm(c, m, d, n, k);
}
function crypto_box_open(m, c, d, n, y, x) {
var k = new Uint8Array(32);
crypto_box_beforenm(k, y, x);
return crypto_box_open_afternm(m, c, d, n, k);
}
var K = [
0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
];
function crypto_hashblocks_hl(hh, hl, m, n) {
var wh = new Int32Array(16), wl = new Int32Array(16),
bh0, bh1, bh2, bh3, bh4, bh5, bh6, bh7,
bl0, bl1, bl2, bl3, bl4, bl5, bl6, bl7,
th, tl, i, j, h, l, a, b, c, d;
var ah0 = hh[0],
ah1 = hh[1],
ah2 = hh[2],
ah3 = hh[3],
ah4 = hh[4],
ah5 = hh[5],
ah6 = hh[6],
ah7 = hh[7],
al0 = hl[0],
al1 = hl[1],
al2 = hl[2],
al3 = hl[3],
al4 = hl[4],
al5 = hl[5],
al6 = hl[6],
al7 = hl[7];
var pos = 0;
while (n >= 128) {
for (i = 0; i < 16; i++) {
j = 8 * i + pos;
wh[i] = (m[j + 0] << 24) | (m[j + 1] << 16) | (m[j + 2] << 8) | m[j + 3];
wl[i] = (m[j + 4] << 24) | (m[j + 5] << 16) | (m[j + 6] << 8) | m[j + 7];
}
for (i = 0; i < 80; i++) {
bh0 = ah0;
bh1 = ah1;
bh2 = ah2;
bh3 = ah3;
bh4 = ah4;
bh5 = ah5;
bh6 = ah6;
bh7 = ah7;
bl0 = al0;
bl1 = al1;
bl2 = al2;
bl3 = al3;
bl4 = al4;
bl5 = al5;
bl6 = al6;
bl7 = al7;
// add
h = ah7;
l = al7;
a = l & 0xffff; b = l >>> 16;
c = h & 0xffff; d = h >>> 16;
// Sigma1
h = ((ah4 >>> 14) | (al4 << (32 - 14))) ^ ((ah4 >>> 18) | (al4 << (32 - 18))) ^ ((al4 >>> (41 - 32)) | (ah4 << (32 - (41 - 32))));
l = ((al4 >>> 14) | (ah4 << (32 - 14))) ^ ((al4 >>> 18) | (ah4 << (32 - 18))) ^ ((ah4 >>> (41 - 32)) | (al4 << (32 - (41 - 32))));
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
// Ch
h = (ah4 & ah5) ^ (~ah4 & ah6);
l = (al4 & al5) ^ (~al4 & al6);
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
// K
h = K[i * 2];
l = K[i * 2 + 1];
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
// w
h = wh[i % 16];
l = wl[i % 16];
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
b += a >>> 16;
c += b >>> 16;
d += c >>> 16;
th = c & 0xffff | d << 16;
tl = a & 0xffff | b << 16;
// add
h = th;
l = tl;
a = l & 0xffff; b = l >>> 16;
c = h & 0xffff; d = h >>> 16;
// Sigma0
h = ((ah0 >>> 28) | (al0 << (32 - 28))) ^ ((al0 >>> (34 - 32)) | (ah0 << (32 - (34 - 32)))) ^ ((al0 >>> (39 - 32)) | (ah0 << (32 - (39 - 32))));
l = ((al0 >>> 28) | (ah0 << (32 - 28))) ^ ((ah0 >>> (34 - 32)) | (al0 << (32 - (34 - 32)))) ^ ((ah0 >>> (39 - 32)) | (al0 << (32 - (39 - 32))));
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
// Maj
h = (ah0 & ah1) ^ (ah0 & ah2) ^ (ah1 & ah2);
l = (al0 & al1) ^ (al0 & al2) ^ (al1 & al2);
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
b += a >>> 16;
c += b >>> 16;
d += c >>> 16;
bh7 = (c & 0xffff) | (d << 16);
bl7 = (a & 0xffff) | (b << 16);
// add
h = bh3;
l = bl3;
a = l & 0xffff; b = l >>> 16;
c = h & 0xffff; d = h >>> 16;
h = th;
l = tl;
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
b += a >>> 16;
c += b >>> 16;
d += c >>> 16;
bh3 = (c & 0xffff) | (d << 16);
bl3 = (a & 0xffff) | (b << 16);
ah1 = bh0;
ah2 = bh1;
ah3 = bh2;
ah4 = bh3;
ah5 = bh4;
ah6 = bh5;
ah7 = bh6;
ah0 = bh7;
al1 = bl0;
al2 = bl1;
al3 = bl2;
al4 = bl3;
al5 = bl4;
al6 = bl5;
al7 = bl6;
al0 = bl7;
if (i % 16 === 15) {
for (j = 0; j < 16; j++) {
// add
h = wh[j];
l = wl[j];
a = l & 0xffff; b = l >>> 16;
c = h & 0xffff; d = h >>> 16;
h = wh[(j + 9) % 16];
l = wl[(j + 9) % 16];
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
// sigma0
th = wh[(j + 1) % 16];
tl = wl[(j + 1) % 16];
h = ((th >>> 1) | (tl << (32 - 1))) ^ ((th >>> 8) | (tl << (32 - 8))) ^ (th >>> 7);
l = ((tl >>> 1) | (th << (32 - 1))) ^ ((tl >>> 8) | (th << (32 - 8))) ^ ((tl >>> 7) | (th << (32 - 7)));
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
// sigma1
th = wh[(j + 14) % 16];
tl = wl[(j + 14) % 16];
h = ((th >>> 19) | (tl << (32 - 19))) ^ ((tl >>> (61 - 32)) | (th << (32 - (61 - 32)))) ^ (th >>> 6);
l = ((tl >>> 19) | (th << (32 - 19))) ^ ((th >>> (61 - 32)) | (tl << (32 - (61 - 32)))) ^ ((tl >>> 6) | (th << (32 - 6)));
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
b += a >>> 16;
c += b >>> 16;
d += c >>> 16;
wh[j] = (c & 0xffff) | (d << 16);
wl[j] = (a & 0xffff) | (b << 16);
}
}
}
// add
h = ah0;
l = al0;
a = l & 0xffff; b = l >>> 16;
c = h & 0xffff; d = h >>> 16;
h = hh[0];
l = hl[0];
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
b += a >>> 16;
c += b >>> 16;
d += c >>> 16;
hh[0] = ah0 = (c & 0xffff) | (d << 16);
hl[0] = al0 = (a & 0xffff) | (b << 16);
h = ah1;
l = al1;
a = l & 0xffff; b = l >>> 16;
c = h & 0xffff; d = h >>> 16;
h = hh[1];
l = hl[1];
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
b += a >>> 16;
c += b >>> 16;
d += c >>> 16;
hh[1] = ah1 = (c & 0xffff) | (d << 16);
hl[1] = al1 = (a & 0xffff) | (b << 16);
h = ah2;
l = al2;
a = l & 0xffff; b = l >>> 16;
c = h & 0xffff; d = h >>> 16;
h = hh[2];
l = hl[2];
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
b += a >>> 16;
c += b >>> 16;
d += c >>> 16;
hh[2] = ah2 = (c & 0xffff) | (d << 16);
hl[2] = al2 = (a & 0xffff) | (b << 16);
h = ah3;
l = al3;
a = l & 0xffff; b = l >>> 16;
c = h & 0xffff; d = h >>> 16;
h = hh[3];
l = hl[3];
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
b += a >>> 16;
c += b >>> 16;
d += c >>> 16;
hh[3] = ah3 = (c & 0xffff) | (d << 16);
hl[3] = al3 = (a & 0xffff) | (b << 16);
h = ah4;
l = al4;
a = l & 0xffff; b = l >>> 16;
c = h & 0xffff; d = h >>> 16;
h = hh[4];
l = hl[4];
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
b += a >>> 16;
c += b >>> 16;
d += c >>> 16;
hh[4] = ah4 = (c & 0xffff) | (d << 16);
hl[4] = al4 = (a & 0xffff) | (b << 16);
h = ah5;
l = al5;
a = l & 0xffff; b = l >>> 16;
c = h & 0xffff; d = h >>> 16;
h = hh[5];
l = hl[5];
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
b += a >>> 16;
c += b >>> 16;
d += c >>> 16;
hh[5] = ah5 = (c & 0xffff) | (d << 16);
hl[5] = al5 = (a & 0xffff) | (b << 16);
h = ah6;
l = al6;
a = l & 0xffff; b = l >>> 16;
c = h & 0xffff; d = h >>> 16;
h = hh[6];
l = hl[6];
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
b += a >>> 16;
c += b >>> 16;
d += c >>> 16;
hh[6] = ah6 = (c & 0xffff) | (d << 16);
hl[6] = al6 = (a & 0xffff) | (b << 16);
h = ah7;
l = al7;
a = l & 0xffff; b = l >>> 16;
c = h & 0xffff; d = h >>> 16;
h = hh[7];
l = hl[7];
a += l & 0xffff; b += l >>> 16;
c += h & 0xffff; d += h >>> 16;
b += a >>> 16;
c += b >>> 16;
d += c >>> 16;
hh[7] = ah7 = (c & 0xffff) | (d << 16);
hl[7] = al7 = (a & 0xffff) | (b << 16);
pos += 128;
n -= 128;
}
return n;
}
function crypto_hash(out, m, n) {
var hh = new Int32Array(8),
hl = new Int32Array(8),
x = new Uint8Array(256),
i, b = n;
hh[0] = 0x6a09e667;
hh[1] = 0xbb67ae85;
hh[2] = 0x3c6ef372;
hh[3] = 0xa54ff53a;
hh[4] = 0x510e527f;
hh[5] = 0x9b05688c;
hh[6] = 0x1f83d9ab;
hh[7] = 0x5be0cd19;
hl[0] = 0xf3bcc908;
hl[1] = 0x84caa73b;
hl[2] = 0xfe94f82b;
hl[3] = 0x5f1d36f1;
hl[4] = 0xade682d1;
hl[5] = 0x2b3e6c1f;
hl[6] = 0xfb41bd6b;
hl[7] = 0x137e2179;
crypto_hashblocks_hl(hh, hl, m, n);
n %= 128;
for (i = 0; i < n; i++) x[i] = m[b - n + i];
x[n] = 128;
n = 256 - 128 * (n < 112 ? 1 : 0);
x[n - 9] = 0;
ts64(x, n - 8, (b / 0x20000000) | 0, b << 3);
crypto_hashblocks_hl(hh, hl, x, n);
for (i = 0; i < 8; i++) ts64(out, 8 * i, hh[i], hl[i]);
return 0;
}
function add(p, q) {
var a = gf(), b = gf(), c = gf(),
d = gf(), e = gf(), f = gf(),
g = gf(), h = gf(), t = gf();
Z(a, p[1], p[0]);
Z(t, q[1], q[0]);
M(a, a, t);
A(b, p[0], p[1]);
A(t, q[0], q[1]);
M(b, b, t);
M(c, p[3], q[3]);
M(c, c, D2);
M(d, p[2], q[2]);
A(d, d, d);
Z(e, b, a);
Z(f, d, c);
A(g, d, c);
A(h, b, a);
M(p[0], e, f);
M(p[1], h, g);
M(p[2], g, f);
M(p[3], e, h);
}
function cswap(p, q, b) {
var i;
for (i = 0; i < 4; i++) {
sel25519(p[i], q[i], b);
}
}
function pack(r, p) {
var tx = gf(), ty = gf(), zi = gf();
inv25519(zi, p[2]);
M(tx, p[0], zi);
M(ty, p[1], zi);
pack25519(r, ty);
r[31] ^= par25519(tx) << 7;
}
function scalarmult(p, q, s) {
var b, i;
set25519(p[0], gf0);
set25519(p[1], gf1);
set25519(p[2], gf1);
set25519(p[3], gf0);
for (i = 255; i >= 0; --i) {
b = (s[(i / 8) | 0] >> (i & 7)) & 1;
cswap(p, q, b);
add(q, p);
add(p, p);
cswap(p, q, b);
}
}
function scalarbase(p, s) {
var q = [gf(), gf(), gf(), gf()];
set25519(q[0], X);
set25519(q[1], Y);
set25519(q[2], gf1);
M(q[3], X, Y);
scalarmult(p, q, s);
}
function crypto_sign_keypair(pk, sk, seeded) {
var d = new Uint8Array(64);
var p = [gf(), gf(), gf(), gf()];
var i;
if (!seeded) randombytes(sk, 32);
crypto_hash(d, sk, 32);
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
scalarbase(p, d);
pack(pk, p);
for (i = 0; i < 32; i++) sk[i + 32] = pk[i];
return 0;
}
var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]);
function modL(r, x) {
var carry, i, j, k;
for (i = 63; i >= 32; --i) {
carry = 0;
for (j = i - 32, k = i - 12; j < k; ++j) {
x[j] += carry - 16 * x[i] * L[j - (i - 32)];
carry = Math.floor((x[j] + 128) / 256);
x[j] -= carry * 256;
}
x[j] += carry;
x[i] = 0;
}
carry = 0;
for (j = 0; j < 32; j++) {
x[j] += carry - (x[31] >> 4) * L[j];
carry = x[j] >> 8;
x[j] &= 255;
}
for (j = 0; j < 32; j++) x[j] -= carry * L[j];
for (i = 0; i < 32; i++) {
x[i + 1] += x[i] >> 8;
r[i] = x[i] & 255;
}
}
function reduce(r) {
var x = new Float64Array(64), i;
for (i = 0; i < 64; i++) x[i] = r[i];
for (i = 0; i < 64; i++) r[i] = 0;
modL(r, x);
}
// Note: difference from C - smlen returned, not passed as argument.
function crypto_sign(sm, m, n, sk) {
var d = new Uint8Array(64), h = new Uint8Array(64), r = new Uint8Array(64);
var i, j, x = new Float64Array(64);
var p = [gf(), gf(), gf(), gf()];
crypto_hash(d, sk, 32);
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
var smlen = n + 64;
for (i = 0; i < n; i++) sm[64 + i] = m[i];
for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i];
crypto_hash(r, sm.subarray(32), n + 32);
reduce(r);
scalarbase(p, r);
pack(sm, p);
for (i = 32; i < 64; i++) sm[i] = sk[i];
crypto_hash(h, sm, n + 64);
reduce(h);
for (i = 0; i < 64; i++) x[i] = 0;
for (i = 0; i < 32; i++) x[i] = r[i];
for (i = 0; i < 32; i++) {
for (j = 0; j < 32; j++) {
x[i + j] += h[i] * d[j];
}
}
modL(sm.subarray(32), x);
return smlen;
}
function unpackneg(r, p) {
var t = gf(), chk = gf(), num = gf(),
den = gf(), den2 = gf(), den4 = gf(),
den6 = gf();
set25519(r[2], gf1);
unpack25519(r[1], p);
S(num, r[1]);
M(den, num, D);
Z(num, num, r[2]);
A(den, r[2], den);
S(den2, den);
S(den4, den2);
M(den6, den4, den2);
M(t, den6, num);
M(t, t, den);
pow2523(t, t);
M(t, t, num);
M(t, t, den);
M(t, t, den);
M(r[0], t, den);
S(chk, r[0]);
M(chk, chk, den);
if (neq25519(chk, num)) M(r[0], r[0], I);
S(chk, r[0]);
M(chk, chk, den);
if (neq25519(chk, num)) return -1;
if (par25519(r[0]) === (p[31] >> 7)) Z(r[0], gf0, r[0]);
M(r[3], r[0], r[1]);
return 0;
}
function crypto_sign_open(m, sm, n, pk) {
var i;
var t = new Uint8Array(32), h = new Uint8Array(64);
var p = [gf(), gf(), gf(), gf()],
q = [gf(), gf(), gf(), gf()];
if (n < 64) return -1;
if (unpackneg(q, pk)) return -1;
for (i = 0; i < n; i++) m[i] = sm[i];
for (i = 0; i < 32; i++) m[i + 32] = pk[i];
crypto_hash(h, m, n);
reduce(h);
scalarmult(p, q, h);
scalarbase(q, sm.subarray(32));
add(p, q);
pack(t, p);
n -= 64;
if (crypto_verify_32(sm, 0, t, 0)) {
for (i = 0; i < n; i++) m[i] = 0;
return -1;
}
for (i = 0; i < n; i++) m[i] = sm[i + 64];
return n;
}
var crypto_secretbox_KEYBYTES = 32,
crypto_secretbox_NONCEBYTES = 24,
crypto_secretbox_ZEROBYTES = 32,
crypto_secretbox_BOXZEROBYTES = 16,
crypto_scalarmult_BYTES = 32,
crypto_scalarmult_SCALARBYTES = 32,
crypto_box_PUBLICKEYBYTES = 32,
crypto_box_SECRETKEYBYTES = 32,
crypto_box_BEFORENMBYTES = 32,
crypto_box_NONCEBYTES = crypto_secretbox_NONCEBYTES,
crypto_box_ZEROBYTES = crypto_secretbox_ZEROBYTES,
crypto_box_BOXZEROBYTES = crypto_secretbox_BOXZEROBYTES,
crypto_sign_BYTES = 64,
crypto_sign_PUBLICKEYBYTES = 32,
crypto_sign_SECRETKEYBYTES = 64,
crypto_sign_SEEDBYTES = 32,
crypto_hash_BYTES = 64;
nacl.lowlevel = {
crypto_core_hsalsa20: crypto_core_hsalsa20,
crypto_stream_xor: crypto_stream_xor,
crypto_stream: crypto_stream,
crypto_stream_salsa20_xor: crypto_stream_salsa20_xor,
crypto_stream_salsa20: crypto_stream_salsa20,
crypto_onetimeauth: crypto_onetimeauth,
crypto_onetimeauth_verify: crypto_onetimeauth_verify,
crypto_verify_16: crypto_verify_16,
crypto_verify_32: crypto_verify_32,
crypto_secretbox: crypto_secretbox,
crypto_secretbox_open: crypto_secretbox_open,
crypto_scalarmult: crypto_scalarmult,
crypto_scalarmult_base: crypto_scalarmult_base,
crypto_box_beforenm: crypto_box_beforenm,
crypto_box_afternm: crypto_box_afternm,
crypto_box: crypto_box,
crypto_box_open: crypto_box_open,
crypto_box_keypair: crypto_box_keypair,
crypto_hash: crypto_hash,
crypto_sign: crypto_sign,
crypto_sign_keypair: crypto_sign_keypair,
crypto_sign_open: crypto_sign_open,
crypto_secretbox_KEYBYTES: crypto_secretbox_KEYBYTES,
crypto_secretbox_NONCEBYTES: crypto_secretbox_NONCEBYTES,
crypto_secretbox_ZEROBYTES: crypto_secretbox_ZEROBYTES,
crypto_secretbox_BOXZEROBYTES: crypto_secretbox_BOXZEROBYTES,
crypto_scalarmult_BYTES: crypto_scalarmult_BYTES,
crypto_scalarmult_SCALARBYTES: crypto_scalarmult_SCALARBYTES,
crypto_box_PUBLICKEYBYTES: crypto_box_PUBLICKEYBYTES,
crypto_box_SECRETKEYBYTES: crypto_box_SECRETKEYBYTES,
crypto_box_BEFORENMBYTES: crypto_box_BEFORENMBYTES,
crypto_box_NONCEBYTES: crypto_box_NONCEBYTES,
crypto_box_ZEROBYTES: crypto_box_ZEROBYTES,
crypto_box_BOXZEROBYTES: crypto_box_BOXZEROBYTES,
crypto_sign_BYTES: crypto_sign_BYTES,
crypto_sign_PUBLICKEYBYTES: crypto_sign_PUBLICKEYBYTES,
crypto_sign_SECRETKEYBYTES: crypto_sign_SECRETKEYBYTES,
crypto_sign_SEEDBYTES: crypto_sign_SEEDBYTES,
crypto_hash_BYTES: crypto_hash_BYTES,
gf: gf,
D: D,
L: L,
pack25519: pack25519,
unpack25519: unpack25519,
M: M,
A: A,
S: S,
Z: Z,
pow2523: pow2523,
add: add,
set25519: set25519,
modL: modL,
scalarmult: scalarmult,
scalarbase: scalarbase,
};
/* High-level API */
function checkLengths(k, n) {
if (k.length !== crypto_secretbox_KEYBYTES) throw new Error('bad key size');
if (n.length !== crypto_secretbox_NONCEBYTES) throw new Error('bad nonce size');
}
function checkBoxLengths(pk, sk) {
if (pk.length !== crypto_box_PUBLICKEYBYTES) throw new Error('bad public key size');
if (sk.length !== crypto_box_SECRETKEYBYTES) throw new Error('bad secret key size');
}
function checkArrayTypes() {
for (var i = 0; i < arguments.length; i++) {
if (!(arguments[i] instanceof Uint8Array))
throw new TypeError('unexpected type, use Uint8Array');
}
}
function cleanup(arr) {
for (var i = 0; i < arr.length; i++) arr[i] = 0;
}
nacl.randomBytes = function (n) {
var b = new Uint8Array(n);
randombytes(b, n);
return b;
};
nacl.secretbox = function (msg, nonce, key) {
checkArrayTypes(msg, nonce, key);
checkLengths(key, nonce);
var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length);
var c = new Uint8Array(m.length);
for (var i = 0; i < msg.length; i++) m[i + crypto_secretbox_ZEROBYTES] = msg[i];
crypto_secretbox(c, m, m.length, nonce, key);
return c.subarray(crypto_secretbox_BOXZEROBYTES);
};
nacl.secretbox.open = function (box, nonce, key) {
checkArrayTypes(box, nonce, key);
checkLengths(key, nonce);
var c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.length);
var m = new Uint8Array(c.length);
for (var i = 0; i < box.length; i++) c[i + crypto_secretbox_BOXZEROBYTES] = box[i];
if (c.length < 32) return null;
if (crypto_secretbox_open(m, c, c.length, nonce, key) !== 0) return null;
return m.subarray(crypto_secretbox_ZEROBYTES);
};
nacl.secretbox.keyLength = crypto_secretbox_KEYBYTES;
nacl.secretbox.nonceLength = crypto_secretbox_NONCEBYTES;
nacl.secretbox.overheadLength = crypto_secretbox_BOXZEROBYTES;
nacl.scalarMult = function (n, p) {
checkArrayTypes(n, p);
if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size');
if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size');
var q = new Uint8Array(crypto_scalarmult_BYTES);
crypto_scalarmult(q, n, p);
return q;
};
nacl.scalarMult.base = function (n) {
checkArrayTypes(n);
if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size');
var q = new Uint8Array(crypto_scalarmult_BYTES);
crypto_scalarmult_base(q, n);
return q;
};
nacl.scalarMult.scalarLength = crypto_scalarmult_SCALARBYTES;
nacl.scalarMult.groupElementLength = crypto_scalarmult_BYTES;
nacl.box = function (msg, nonce, publicKey, secretKey) {
var k = nacl.box.before(publicKey, secretKey);
return nacl.secretbox(msg, nonce, k);
};
nacl.box.before = function (publicKey, secretKey) {
checkArrayTypes(publicKey, secretKey);
checkBoxLengths(publicKey, secretKey);
var k = new Uint8Array(crypto_box_BEFORENMBYTES);
crypto_box_beforenm(k, publicKey, secretKey);
return k;
};
nacl.box.after = nacl.secretbox;
nacl.box.open = function (msg, nonce, publicKey, secretKey) {
var k = nacl.box.before(publicKey, secretKey);
return nacl.secretbox.open(msg, nonce, k);
};
nacl.box.open.after = nacl.secretbox.open;
nacl.box.keyPair = function () {
var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES);
var sk = new Uint8Array(crypto_box_SECRETKEYBYTES);
crypto_box_keypair(pk, sk);
return { publicKey: pk, secretKey: sk };
};
nacl.box.keyPair.fromSecretKey = function (secretKey) {
checkArrayTypes(secretKey);
if (secretKey.length !== crypto_box_SECRETKEYBYTES)
throw new Error('bad secret key size');
var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES);
crypto_scalarmult_base(pk, secretKey);
return { publicKey: pk, secretKey: new Uint8Array(secretKey) };
};
nacl.box.publicKeyLength = crypto_box_PUBLICKEYBYTES;
nacl.box.secretKeyLength = crypto_box_SECRETKEYBYTES;
nacl.box.sharedKeyLength = crypto_box_BEFORENMBYTES;
nacl.box.nonceLength = crypto_box_NONCEBYTES;
nacl.box.overheadLength = nacl.secretbox.overheadLength;
nacl.sign = function (msg, secretKey) {
checkArrayTypes(msg, secretKey);
if (secretKey.length !== crypto_sign_SECRETKEYBYTES)
throw new Error('bad secret key size');
var signedMsg = new Uint8Array(crypto_sign_BYTES + msg.length);
crypto_sign(signedMsg, msg, msg.length, secretKey);
return signedMsg;
};
nacl.sign.open = function (signedMsg, publicKey) {
checkArrayTypes(signedMsg, publicKey);
if (publicKey.length !== crypto_sign_PUBLICKEYBYTES)
throw new Error('bad public key size');
var tmp = new Uint8Array(signedMsg.length);
var mlen = crypto_sign_open(tmp, signedMsg, signedMsg.length, publicKey);
if (mlen < 0) return null;
var m = new Uint8Array(mlen);
for (var i = 0; i < m.length; i++) m[i] = tmp[i];
return m;
};
nacl.sign.detached = function (msg, secretKey) {
var signedMsg = nacl.sign(msg, secretKey);
var sig = new Uint8Array(crypto_sign_BYTES);
for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i];
return sig;
};
nacl.sign.detached.verify = function (msg, sig, publicKey) {
checkArrayTypes(msg, sig, publicKey);
if (sig.length !== crypto_sign_BYTES)
throw new Error('bad signature size');
if (publicKey.length !== crypto_sign_PUBLICKEYBYTES)
throw new Error('bad public key size');
var sm = new Uint8Array(crypto_sign_BYTES + msg.length);
var m = new Uint8Array(crypto_sign_BYTES + msg.length);
var i;
for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i];
for (i = 0; i < msg.length; i++) sm[i + crypto_sign_BYTES] = msg[i];
return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0);
};
nacl.sign.keyPair = function () {
var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES);
var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES);
crypto_sign_keypair(pk, sk);
return { publicKey: pk, secretKey: sk };
};
nacl.sign.keyPair.fromSecretKey = function (secretKey) {
checkArrayTypes(secretKey);
if (secretKey.length !== crypto_sign_SECRETKEYBYTES)
throw new Error('bad secret key size');
var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES);
for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32 + i];
return { publicKey: pk, secretKey: new Uint8Array(secretKey) };
};
nacl.sign.keyPair.fromSeed = function (seed) {
checkArrayTypes(seed);
if (seed.length !== crypto_sign_SEEDBYTES)
throw new Error('bad seed size');
var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES);
var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES);
for (var i = 0; i < 32; i++) sk[i] = seed[i];
crypto_sign_keypair(pk, sk, true);
return { publicKey: pk, secretKey: sk };
};
nacl.sign.publicKeyLength = crypto_sign_PUBLICKEYBYTES;
nacl.sign.secretKeyLength = crypto_sign_SECRETKEYBYTES;
nacl.sign.seedLength = crypto_sign_SEEDBYTES;
nacl.sign.signatureLength = crypto_sign_BYTES;
nacl.hash = function (msg) {
checkArrayTypes(msg);
var h = new Uint8Array(crypto_hash_BYTES);
crypto_hash(h, msg, msg.length);
return h;
};
nacl.hash.hashLength = crypto_hash_BYTES;
nacl.verify = function (x, y) {
checkArrayTypes(x, y);
// Zero length arguments are considered not equal.
if (x.length === 0 || y.length === 0) return false;
if (x.length !== y.length) return false;
return (vn(x, 0, y, 0, x.length) === 0) ? true : false;
};
nacl.setPRNG = function (fn) {
randombytes = fn;
};
(function () {
// Initialize PRNG if environment provides CSPRNG.
// If not, methods calling randombytes will throw.
var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null;
if (crypto && crypto.getRandomValues) {
// Browsers.
var QUOTA = 65536;
nacl.setPRNG(function (x, n) {
var i, v = new Uint8Array(n);
for (i = 0; i < n; i += QUOTA) {
crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA)));
}
for (i = 0; i < n; i++) x[i] = v[i];
cleanup(v);
});
} else if (typeof require !== 'undefined') {
// Node.js.
crypto = require('crypto');
if (crypto && crypto.randomBytes) {
nacl.setPRNG(function (x, n) {
var i, v = crypto.randomBytes(n);
for (i = 0; i < n; i++) x[i] = v[i];
cleanup(v);
});
}
}
})();
})(typeof module !== 'undefined' && module.exports ? module.exports : (self.nacl = (typeof self !== 'undefined' && self.nacl) ? self.nacl : {}));
var nacl = (typeof module !== 'undefined' && module.exports && module.exports.sign) ? module.exports : (self.nacl || this.nacl || globalThis.nacl);
/**
* ============================================================================
* TechnoSwarm GAS Autonomous Worker & Daily Check-in Script
* ============================================================================
*
* [Overview]
* Fully autonomous Google Apps Script (GAS) agent for Technocore Chat & FLOP Network.
* Handles automated cryptographic check-ins, liveness maintenance (7-day anti-reaper),
* mutual peer defense task execution, and automated Google Spreadsheet dashboard logging.
*
* [Zero-Touch Setup]
* 1. Open https://script.google.com/ and create a New Project.
* 2. Paste this entire code into the editor and save (💾).
* 3. Select 'testRunner' in the dropdown and click 'Run'.
* (All DID generation, initial check-in, and daily triggers are configured automatically)
* ============================================================================
*/
/**
* Main 1-click test runner (generates DID, performs initial check-in, and registers daily trigger)
*/
function testRunner() {
dailyRunnerAndCheckin();
setupDailyTrigger();
}
/**
* Daily autonomous runner loop (triggered every morning)
*/
function dailyRunnerAndCheckin() {
Logger.log("=== TechnoSwarm GAS Runner & Check-in Loop Starting ===");
var userLock = LockService.getUserLock();
if (!userLock.tryLock(30000)) {
Logger.log("⚠️ Another instance of TechnoSwarm GAS Runner is currently executing. Exiting gracefully.");
return;
}
try {
var props = PropertiesService.getUserProperties();
var seedHex = props.getProperty("TECHNOCORE_SEED_HEX");
// 1. Zero-Touch Setup: Generate and securely store production Ed25519 seed in UserProperties if not set
if (!seedHex || seedHex.trim() === "") {
Logger.log("ℹ️ 'TECHNOCORE_SEED_HEX' is not set in UserProperties. Generating a new secure production DID...");
seedHex = generateSecureRandomSeedHex();
props.setProperty("TECHNOCORE_SEED_HEX", seedHex);
Logger.log("🎉 Successfully generated and securely stored your production DID seed (Ed25519) in UserProperties!");
}
var gatewayDid = props.getProperty("GATEWAY_DID") || "did:key:z6MkrWdvQBpV12QF2yUVSzCHxfcRU2vNSKJTRA8DBKJKD6Vw";
var runner = new TechnoSwarmGasRunner(seedHex, gatewayDid);
Logger.log("Your Production DID: " + runner.did);
Logger.log("Fingerprint: " + runner.fingerprint);
Logger.log("Parent Gateway DID: " + runner.gatewayDid);
Logger.log("Dedicated Mailbox: " + runner.mailbox);
// 0. Random jitter delay to smooth out concurrent peak load
var jitterMs = Math.floor(Math.random() * 15000);
if (jitterMs > 1000) {
Utilities.sleep(jitterMs);
}
// 1. Submit self-protection MemoryGuard task to Parent Gateway
Logger.log("\n--- Step 1: Submitting Memory Guard Task to Gateway ---");
var targetTasksRoom = "mb-p-gw-tasks-" + runner.gatewayFp;
try {
var submitRes = runner.submitMemoryGuardTask();
Logger.log("✓ Guard Task submitted to Gateway: " + submitRes.taskId);
runner.logEventToSheet("Task Order", "Me -> Gateway", "Request Guard Task", targetTasksRoom, runner.gatewayDid, "task_id: " + submitRes.taskId, "Submitted");
} catch (e) {
Logger.log("Guard Task Submit Note: " + e.message);
runner.logEventToSheet("Task Order", "Me -> Gateway", "Request Guard Task", targetTasksRoom, runner.gatewayDid, e.message, "Failed (503)");
}
// 2. Self Liveness Check-in with dynamic entropy
Logger.log("\n--- Step 2: Self Liveness Check-in (/r/lobby) ---");
var now = new Date();
var isoTime = Utilities.formatDate(now, "GMT", "yyyy-MM-dd'T'HH:mm:ss'Z'");
var dynamicNonce = now.getTime().toString();
var dynamicMsg = "[Liveness Pulse] Runner " + runner.fingerprint + " online at " + isoTime + " (seq-proof:" + dynamicNonce.slice(-6) + ") | TechnoSwarm Hybrid Broker";
var selfCheckinSuccess = false;
try {
var lobbyRes = runner.saySigned("lobby", dynamicMsg);
Logger.log("✓ Self Check-in Succeeded: " + lobbyRes.substring(0, 100) + "...");
selfCheckinSuccess = true;
runner.logEventToSheet("Liveness", "Me -> Lobby", "Liveness Check-in", "lobby", runner.did, dynamicMsg, "Success");
} catch (e) {
Logger.warning("Self Check-in Warning: " + e.message);
Logger.warning("ℹ️ Technocore server might be temporarily congested. Retrying automatically in next schedule.");
runner.logEventToSheet("Liveness", "Me -> Lobby", "Liveness Check-in", "lobby", runner.did, e.message, "Retry Queued (503)");
}
// 2.5. Register runner to Parent Gateway for task dispatching
Logger.log("\n--- Step 2.5: Registering to Parent Gateway ---");
var regRoom = "mb-p-gw-reg-" + runner.gatewayFp;
var regPayload = {
action: "register_runner",
runner_did: runner.did,
mailbox: runner.mailbox,
capabilities: ["memory:guard"],
timestamp: Math.floor(now.getTime() / 1000)
};
try {
runner.saySigned(regRoom, JSON.stringify(regPayload));
Logger.log("✓ Registered to Parent Gateway successfully: " + regRoom);
runner.logEventToSheet("Registration", "Me -> Gateway", "Register Worker", regRoom, runner.gatewayDid, "capabilities: ['memory:guard']", "Registered");
} catch (e) {
Logger.log("Register Note: " + e.message);
runner.logEventToSheet("Registration", "Me -> Gateway", "Register Worker", regRoom, runner.gatewayDid, e.message, "Retry Queued (503)");
}
// 3. Poll Mailbox for dispatched tasks from Parent Gateway & peer Pings
Logger.log("\n--- Step 3: Polling Dispatched Tasks from Mailbox ---");
var mailboxRoom = runner.mailbox;
var messages = runner.readRoomJson(mailboxRoom, 20);
Logger.log("Mailbox (" + mailboxRoom + ") messages count: " + messages.length);
var processedTasksMapStr = props.getProperty("PROCESSED_TASKS_MAP") || "{}";
var processedTasksMap = {};
try {
processedTasksMap = JSON.parse(processedTasksMapStr);
} catch (e) {
processedTasksMap = {};
}
var nowSec = Math.floor(new Date().getTime() / 1000);
// Garbage collection: purge tasks older than 24h (86,400s) from map
var cleanedTasksMap = {};
for (var tid in processedTasksMap) {
if (nowSec - processedTasksMap[tid] < 86400) {
cleanedTasksMap[tid] = processedTasksMap[tid];
}
}
processedTasksMap = cleanedTasksMap;
var newProcessed = false;
var verifiedTasksFound = 0;
for (var i = 0; i < messages.length; i++) {
var msg = messages[i];
if (msg.text) {
// Detect incoming peer guard pings
if (msg.text.indexOf("MemoryGuard") !== -1 || msg.text.indexOf("memory_guard") !== -1 || msg.text.indexOf("Liveness pulse") !== -1) {
var senderDid = msg.did || msg.from || "Peer Worker";
// Cryptographically verify detached Ed25519 signature on peer guard pings
var isPeerSigValid = runner.verifySignature(mailboxRoom, senderDid, msg.sig, msg.nonce, msg.text);
if (!isPeerSigValid) {
continue; // Silently skip unverified or legacy test pings
}
var pingSeq = msg.seq || ("msg-" + i);
var processedPingsKey = "PING_SEEN_" + pingSeq;
if (!props.getProperty(processedPingsKey)) {
Logger.log("🛡️ Received verified guard ping from: " + senderDid);
runner.logEventToSheet("Mutual Guard", "Peer -> Me", "Guard Ping Received", mailboxRoom, senderDid, msg.text, "Confirmed");
props.setProperty(processedPingsKey, "1");
}
}
// Process tasks ONLY when cryptographically verified to originate from Parent Gateway
if (msg.text.indexOf("task_id") !== -1) {
var senderDid = msg.did || msg.from || "";
if (senderDid !== runner.gatewayDid) {
continue; // Silently skip tasks from untrusted senders
}
// Cryptographic Ed25519 signature verification against Gateway Public Key
var isVerified = runner.verifySignature(mailboxRoom, senderDid, msg.sig, msg.nonce, msg.text);
if (!isVerified) {
continue; // Silently skip legacy test tasks with outdated signature formats
}
try {
var dispatch = JSON.parse(msg.text);
if (dispatch.task_id) {
if (processedTasksMap[dispatch.task_id]) {
continue;
}
// Anti-Replay: Verify task timestamp (mandatory dispatched_at or created_at within last 24h, clock drift tolerance 300s)
var taskCreatedAt = parseInt(dispatch.dispatched_at || dispatch.created_at, 10);
if (!taskCreatedAt || isNaN(taskCreatedAt)) {
continue;
}
if (nowSec - taskCreatedAt > 86400 || taskCreatedAt - nowSec > 300) {
continue; // Skip expired tasks outside 24h window
}
if (dispatch.module_need === "memory:guard") {
verifiedTasksFound++;
Logger.log("Processing verified memory:guard task from Gateway: " + dispatch.task_id);
var taskSuccess = runner.processMemoryGuardTask(dispatch);
if (taskSuccess) {
processedTasksMap[dispatch.task_id] = nowSec;
newProcessed = true;
var targetDid = (dispatch.payload && dispatch.payload.target_did) ? dispatch.payload.target_did : "Unknown DID";
var targetMb = (dispatch.payload && dispatch.payload.target_mailbox) ? dispatch.payload.target_mailbox : "-";
runner.logEventToSheet("Mutual Guard", "Me -> Peer", "Defend Peer", targetMb, targetDid, "task_id: " + dispatch.task_id + " (receipt delivered)", "Completed");
}
}
}
} catch (err) {
Logger.log("Non-JSON or invalid dispatch message: " + err.message);
}
}
}
}
if (verifiedTasksFound === 0) {
Logger.log("✓ Mailbox scanned: No new pending tasks.");
}
if (newProcessed) {
props.setProperty("PROCESSED_TASKS_MAP", JSON.stringify(processedTasksMap));
}
if (selfCheckinSuccess) {
Logger.log("\n[✓] Daily mutual guard and anti-reaper check-in cycle completed successfully!");
} else {
Logger.log("\n[⚠️ Pending] Technocore server was congested. Check-in queued for next automatic execution.");
}
try {
var ss = runner.getOrCreateDashboardSheet();
Logger.log("\n📊 Mutual Guard Dashboard (Google Sheets): " + ss.getUrl());
} catch (sheetErr) {
Logger.log("Dashboard Sheet Note: " + sheetErr.message);
}
} finally {
userLock.releaseLock();
}
}
/**
* Sets up daily automatic execution trigger (8:00 - 9:00 AM) with 1-click
*/
function setupDailyTrigger() {
var functionName = "dailyRunnerAndCheckin";
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
if (triggers[i].getHandlerFunction() === functionName) {
Logger.log("ℹ️ Daily execution trigger is already configured (skipping duplicate).");
return;
}
}
ScriptApp.newTrigger(functionName)
.timeBased()
.everyDays(1)
.atHour(8)
.create();
Logger.log("🎉 Daily automatic execution trigger (8:00 - 9:00 AM) registered successfully!");
}
/**
* Checks agent DID status, daily trigger state, and recent mailbox communications
*/
function checkMyStatus() {
Logger.log("=== TechnoSwarm GAS Runner Status Check ===");
var props = PropertiesService.getUserProperties();
var seedHex = props.getProperty("TECHNOCORE_SEED_HEX");
if (!seedHex) {
Logger.log("⚠️ Private key seed not found in UserProperties. Please run 'testRunner' first.");
return;
}
var gatewayDid = props.getProperty("GATEWAY_DID") || "did:key:z6MkrWdvQBpV12QF2yUVSzCHxfcRU2vNSKJTRA8DBKJKD6Vw";
var runner = new TechnoSwarmGasRunner(seedHex, gatewayDid);
Logger.log("【Agent Information】");
Logger.log("・Production DID: " + runner.did);
Logger.log("・Fingerprint: " + runner.fingerprint);
Logger.log("・Parent Gateway DID:" + runner.gatewayDid);
Logger.log("・Dedicated Mailbox: " + runner.mailbox);
Logger.log("\n【Daily Trigger Status】");
var triggers = ScriptApp.getProjectTriggers();
var triggerFound = false;
for (var i = 0; i < triggers.length; i++) {
if (triggers[i].getHandlerFunction() === "dailyRunnerAndCheckin") {
triggerFound = true;
Logger.log("・Daily Trigger: Active ⏰");
break;
}
}
if (!triggerFound) {
Logger.log("・Daily Trigger: Not registered (run 'setupDailyTrigger' to activate)");
}
Logger.log("\n【Recent Mailbox Messages】");
var mailboxMsgs = runner.readRoomJson(runner.mailbox, 5);
Logger.log("・Recent Message Count: " + mailboxMsgs.length);
for (var j = 0; j < mailboxMsgs.length; j++) {
var m = mailboxMsgs[j];
Logger.log(" [" + (j + 1) + "] " + (m.ts || m.created_at || "Recent") + " : " + (m.text ? m.text.substring(0, 80) : ""));
}
Logger.log("\n[✓] Status Check Completed: Your production DID is fully operational.");
}
// ----------------------------------------------------------------------------
// TechnoSwarm GAS Runner Class
// ----------------------------------------------------------------------------
function TechnoSwarmGasRunner(seedHex, gatewayDid) {
this.seed = hexToUint8Array(seedHex.trim());
if (this.seed.length !== 32) {
throw new Error("Invalid seed length (must be 32 bytes).");
}
var keyPair = nacl.sign.keyPair.fromSeed(this.seed);
this.secretKey = keyPair.secretKey;
this.publicKey = keyPair.publicKey;
var prefixed = new Uint8Array(34);
prefixed[0] = 0xed;
prefixed[1] = 0x01;
prefixed.set(this.publicKey, 2);
this.did = "did:key:z" + base58Encode(prefixed);
var didDigest = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, this.did, Utilities.Charset.UTF_8);
this.fingerprint = bytesToHex(didDigest).substring(0, 16);
this.mailbox = "mb-p-runner-" + this.fingerprint;
this.gatewayDid = gatewayDid;
var gwDigest = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, gatewayDid, Utilities.Charset.UTF_8);
this.gatewayFp = bytesToHex(gwDigest).substring(0, 16);
this.receiptMailbox = "mb-p-gw-receipt-" + this.gatewayFp;
this.baseUrl = "https://technocore.chat";
}
TechnoSwarmGasRunner.prototype.cleanSingleLine = function (text) {
if (typeof text !== "string") return "";
return text
.replace(/[\x00-\x1f\x7f-\x9f\u00ad\u061c\u17b4\u17b5\u180e\u2000-\u200f\u2028-\u202f\u205f-\u206f\u3000\ufeff\ufff0-\uffff]/g, " ")
.replace(/\s+/g, " ")
.trim();
};
/**
* Returns a strictly monotonically increasing nonce to prevent replay/rejection errors
*/
TechnoSwarmGasRunner.prototype.getNextNonce = function () {
var props = PropertiesService.getUserProperties();
var lastNonce = parseInt(props.getProperty("LAST_USED_NONCE") || "0", 10);
var nowMs = new Date().getTime();
var nextNonce = Math.max(nowMs, lastNonce + 1);
props.setProperty("LAST_USED_NONCE", nextNonce.toString());
return nextNonce.toString();
};
TechnoSwarmGasRunner.prototype.signMessage = function (room, text) {
var cleanText = this.cleanSingleLine(text);
var nonce = this.getNextNonce();
var payloadStr = room + "|" + nonce + "|" + cleanText;
var payloadBytes = stringToUtf8ByteArray(payloadStr);
var sig = nacl.sign.detached(payloadBytes, this.secretKey);
var sigB64Url = base64UrlEncode(sig);
return {
cleanText: cleanText,
nonce: nonce,
sig: sigB64Url
};
};
TechnoSwarmGasRunner.prototype.saySigned = function (room, text) {
var url = this.baseUrl + "/r/" + encodeURIComponent(room);
var maxRetries = 3;
var lastError = null;
for (var attempt = 0; attempt <= maxRetries; attempt++) {
var signed = this.signMessage(room, text);
var payload = {
did: this.did,
sig: signed.sig,
nonce: signed.nonce,
text: signed.cleanText
};
var options = {
method: "post",
contentType: "application/json",
payload: JSON.stringify(payload),
muteHttpExceptions: true
};
var res = UrlFetchApp.fetch(url, options);
var code = res.getResponseCode();
if (code >= 200 && code < 300) {
return res.getContentText();
}
lastError = new Error("HTTP " + code);
// Exponential backoff retry on temporary server failure (5s, 10s, 20s)
if (code >= 500 && attempt < maxRetries) {
var waitSec = 5 * Math.pow(2, attempt);
Logger.log("⚠️ Technocore server congested (HTTP " + code + "). Retrying in " + waitSec + "s (" + (attempt + 1) + "/" + maxRetries + ")...");
Utilities.sleep(waitSec * 1000);
continue;
}
break;
}
throw lastError;
};
TechnoSwarmGasRunner.prototype.readRoomJson = function (room, limit) {
var url = this.baseUrl + "/r/" + encodeURIComponent(room) + "?format=json&limit=" + (limit || 10);
var options = { method: "get", muteHttpExceptions: true };
var maxRetries = 3;
for (var attempt = 0; attempt <= maxRetries; attempt++) {
var res = UrlFetchApp.fetch(url, options);
var code = res.getResponseCode();
if (code >= 200 && code < 300) {
try {
var data = JSON.parse(res.getContentText());
return data.messages || [];
} catch (e) {
return [];
}
}
if (code >= 500 && attempt < maxRetries) {
var waitSec = 5 * Math.pow(2, attempt);
Logger.log("⚠️ Technocore server congested on read (HTTP " + code + "). Retrying in " + waitSec + "s (" + (attempt + 1) + "/" + maxRetries + ")...");
Utilities.sleep(waitSec * 1000);
continue;
}
break;
}
return [];
};
/**
* Cryptographically verifies an Ed25519 signature on a message against the sender's DID
*/
TechnoSwarmGasRunner.prototype.verifySignature = function (room, did, sig, nonce, text) {
try {
if (!did || !sig || nonce === undefined || nonce === null || !text) return false;
nonce = String(nonce);
var pubKey = didToPublicKey(did);
if (!pubKey || pubKey.length !== 32) return false;
var cleanText = this.cleanSingleLine(text);
var payloadStr = room + "|" + nonce + "|" + cleanText;
var payloadBytes = stringToUtf8ByteArray(payloadStr);
var sigBytes = base64UrlDecode(sig);
if (sigBytes.length !== 64) return false;
return nacl.sign.detached.verify(payloadBytes, sigBytes, pubKey);
} catch (e) {
Logger.log("Signature verification error: " + e.message);
return false;
}
};
TechnoSwarmGasRunner.prototype.processMemoryGuardTask = function (dispatch) {
var startTime = new Date().getTime();
var payload = dispatch.payload || {};
var targetDid = payload.target_did;
var pulseNum = parseInt(payload.pulse_number, 10) || 1;
if (pulseNum < 1 || pulseNum > 1000000) pulseNum = 1;
if (!targetDid || typeof targetDid !== "string" || targetDid.indexOf("did:key:") !== 0) {
Logger.log("Invalid or missing target_did in payload");
return false;
}
var now = new Date();
var isoTime = Utilities.formatDate(now, "GMT", "yyyy-MM-dd'T'HH:mm:ss'Z'");
var targetDigest = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, targetDid, Utilities.Charset.UTF_8);
var targetFp = bytesToHex(targetDigest).substring(0, 16);
// Cryptographic destination validation: derive expected mailbox from target DID hash
var verifiedTargetMailbox = "mb-p-runner-" + targetFp;
// 1. Build pure protocol message (clean of promotional text or URLs)
var pingMsg = "[TechnoSwarm MemoryGuard] Liveness pulse #" + pulseNum + " at " + isoTime + " | " +
"Target: " + targetFp + " | Safe from 7-day Reaper.";
// 2. Send ping to target mailbox and verify delivery
Logger.log("Sending MemoryGuard Ping to " + verifiedTargetMailbox + "...");
var pingRes = this.saySigned(verifiedTargetMailbox, pingMsg);
if (!pingRes) {
Logger.log("⚠️ MemoryGuard ping delivery failed (no response).");
return false;
}
var elapsedSec = Math.max(0.05, (new Date().getTime() - startTime) / 1000);
var actualExecutionTime = Math.round(elapsedSec * 100) / 100;
// 3. Return execution receipt to parent Gateway (claiming verified execution proof)
var receipt = {
task_id: dispatch.task_id,
runner_did: this.did,
status: "success",
output: {
delivered: true,
target_mailbox: verifiedTargetMailbox,
pulse_number: pulseNum,
timestamp: now.getTime() / 1000,
message_sent: pingMsg
},
poui_proof: {
module: "memory_guard",
runner_fp: this.fingerprint,
target_fp: targetFp,
pulse_number: pulseNum,
timestamp: now.getTime() / 1000
},
execution_time_sec: actualExecutionTime,
simulated: false,
completed_at: now.getTime() / 1000
};
Logger.log("Returning ExecutionReceipt to Gateway (" + this.receiptMailbox + ")...");
var rcpRes = this.saySigned(this.receiptMailbox, JSON.stringify(receipt));
if (rcpRes) {
Logger.log("✓ Task " + dispatch.task_id + " completed and receipt delivered successfully!");
return true;
} else {
Logger.log("⚠️ Task receipt delivery failed (no response).");
return false;
}
};
TechnoSwarmGasRunner.prototype.submitMemoryGuardTask = function () {
var taskId = Utilities.getUuid();
var now = Math.floor(new Date().getTime() / 1000);
var targetTasksRoom = "mb-p-gw-tasks-" + this.gatewayFp;
var taskPayload = {
task_id: taskId,
client_did: this.did,
gateway_did: this.gatewayDid,
module_need: "memory:guard",
payload: {
target_did: this.did,
target_mailbox: this.mailbox
},
timeout_sec: 60,
created_at: now,
is_e2ee: false
};
var jsonStr = JSON.stringify(taskPayload);
this.saySigned(targetTasksRoom, jsonStr);
return { taskId: taskId, room: targetTasksRoom };
};
/**
* Retrieves or creates the automatic Google Spreadsheet dashboard
*/
TechnoSwarmGasRunner.prototype.getOrCreateDashboardSheet = function () {
var props = PropertiesService.getUserProperties();
var sheetId = props.getProperty("DASHBOARD_SPREADSHEET_ID");
var ss = null;
if (sheetId) {
try {
ss = SpreadsheetApp.openById(sheetId);
} catch (e) {
ss = null;
}
}
if (!ss) {
var sheetTitle = "TechnoSwarm Event Log (" + this.fingerprint + ")";
ss = SpreadsheetApp.create(sheetTitle);
props.setProperty("DASHBOARD_SPREADSHEET_ID", ss.getId());
}
var sheet = ss.getSheetByName("Event Logs");
if (!sheet) {
var oldSheet = ss.getSheetByName("イベント詳細ログ");
if (oldSheet) {
sheet = oldSheet.setName("Event Logs");
} else {
sheet = ss.insertSheet("Event Logs", 0);
}
}
// Ensure table headers are updated to 8-column left-aligned schema
var headers = [
"Timestamp",
"Category",
"Direction",
"Action",
"Target Room / Mailbox",
"Partner DID / Target",
"Task ID / Details",
"Status"
];
if (sheet.getLastRow() === 0 || sheet.getRange(1, 3).getValue() !== "Direction") {
var headerRange = sheet.getRange(1, 1, 1, headers.length);
headerRange.setValues([headers]);
headerRange.setBackground("#1a73e8");
headerRange.setFontColor("#ffffff");
headerRange.setFontWeight("bold");
headerRange.setHorizontalAlignment("left");
sheet.setFrozenRows(1);
}
return ss;
};
/**
* Sanitizes cell values to prevent Google Sheets CSV/Formula Injection (=, +, -, @)
*/
function sanitizeForSpreadsheet(val) {
if (val === null || val === undefined) return "-";
var str = String(val);
if (/^[=\+\-@\t\r]/.test(str)) {
return "'" + str;
}
return str;
}
/**
* Appends a single row of event logs to Google Spreadsheet
*/
TechnoSwarmGasRunner.prototype.logEventToSheet = function (category, direction, action, targetRoom, partnerDid, memo, status) {
try {
var ss = this.getOrCreateDashboardSheet();
var sheet = ss.getSheetByName("Event Logs") || ss.getActiveSheet();
var timeZone = Session.getScriptTimeZone() || "Asia/Tokyo";
var nowStr = Utilities.formatDate(new Date(), timeZone, "yyyy-MM-dd HH:mm:ss");
var rowData = [
nowStr,
sanitizeForSpreadsheet(category),
sanitizeForSpreadsheet(direction),
sanitizeForSpreadsheet(action),
sanitizeForSpreadsheet(targetRoom),
sanitizeForSpreadsheet(partnerDid),
sanitizeForSpreadsheet(memo),
sanitizeForSpreadsheet(status)
];
sheet.appendRow(rowData);
// Row alignment: Left align entire row for clean readability
var lastRow = sheet.getLastRow();
sheet.getRange(lastRow, 1, 1, rowData.length).setHorizontalAlignment("left");
// Visual highlights based on status
var statusCell = sheet.getRange(lastRow, 8);
var statusStr = String(status || "");
if (statusStr.indexOf("Success") !== -1 || statusStr.indexOf("Registered") !== -1 || statusStr.indexOf("Completed") !== -1 || statusStr.indexOf("Submitted") !== -1) {
statusCell.setBackground("#e6f4ea");
statusCell.setFontColor("#137333");
} else if (statusStr.indexOf("Confirmed") !== -1) {
statusCell.setBackground("#e8f0fe");
statusCell.setFontColor("#1a73e8");
} else if (statusStr.indexOf("Failed") !== -1 || statusStr.indexOf("Retry") !== -1) {
statusCell.setBackground("#fef7e0");
statusCell.setFontColor("#b06000");
}
} catch (e) {
Logger.log("logEventToSheet Note: " + e.message);
}
};
// ----------------------------------------------------------------------------
// Utilities (Base58, Base64URL, Hex, UTF-8, Multi-Entropy Seed & Multicodec DID)
// ----------------------------------------------------------------------------
function generateSecureRandomSeedHex() {
// Generates 32-byte Ed25519 seed from multi-source UUID and timestamp entropy pool
var entropyPool = [];
for (var i = 0; i < 16; i++) {
entropyPool.push(Utilities.getUuid());
}
entropyPool.push(new Date().getTime().toString());
var digest = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, entropyPool.join(":"), Utilities.Charset.UTF_8);
return bytesToHex(digest);
}
function hexToUint8Array(hex) {
var bytes = new Uint8Array(hex.length / 2);
for (var i = 0; i < hex.length; i += 2) {
bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
}
return bytes;
}
function bytesToHex(bytes) {
return Array.prototype.map.call(new Uint8Array(bytes), function (x) {
return ("00" + (x & 0xFF).toString(16)).slice(-2);
}).join("");
}
function stringToUtf8ByteArray(str) {
var out = [], p = 0;
for (var i = 0; i < str.length; i++) {
var c = str.charCodeAt(i);
if (c < 128) {
out[p++] = c;
} else if (c < 2048) {
out[p++] = (c >> 6) | 192;
out[p++] = (c & 63) | 128;
} else if (((c & 0xFC00) == 0xD800) && (i + 1) < str.length && ((str.charCodeAt(i + 1) & 0xFC00) == 0xDC00)) {
c = 0x10000 + ((c & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF);
out[p++] = (c >> 18) | 240;
out[p++] = ((c >> 12) & 63) | 128;
out[p++] = ((c >> 6) & 63) | 128;
out[p++] = (c & 63) | 128;
} else {
out[p++] = (c >> 12) | 224;
out[p++] = ((c >> 6) & 63) | 128;
out[p++] = (c & 63) | 128;
}
}
return new Uint8Array(out);
}
function base64UrlEncode(uint8Array) {
var b64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
var result = "";
var len = uint8Array.length;
var i = 0;
while (i < len) {
var b1 = uint8Array[i++];
var b2 = i < len ? uint8Array[i++] : NaN;
var b3 = i < len ? uint8Array[i++] : NaN;
result += b64chars[b1 >> 2];
result += b64chars[((b1 & 3) << 4) | (isNaN(b2) ? 0 : (b2 >> 4))];
if (!isNaN(b2)) {
result += b64chars[((b2 & 15) << 2) | (isNaN(b3) ? 0 : (b3 >> 6))];
}
if (!isNaN(b3)) {
result += b64chars[b3 & 63];
}
}
return result;
}
function base64UrlDecode(str) {
var b64 = str.replace(/-/g, "+").replace(/_/g, "/");
while (b64.length % 4 !== 0) {
b64 += "=";
}
var decoded = Utilities.base64Decode(b64);
return new Uint8Array(decoded);
}
var B58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
function base58Encode(source) {
if (source.length === 0) return "";
var digits = [0];
for (var i = 0; i < source.length; i++) {
var carry = source[i];
for (var j = 0; j < digits.length; j++) {
carry += digits[j] << 8;
digits[j] = carry % 58;
carry = (carry / 58) | 0;
}
while (carry > 0) {
digits.push(carry % 58);
carry = (carry / 58) | 0;
}
}
var str = "";
for (var k = 0; k < source.length && source[k] === 0; k++) {
str += "1";
}
for (var q = digits.length - 1; q >= 0; q--) {
str += B58_ALPHABET[digits[q]];
}
return str;
}
function base58Decode(string) {
if (string.length === 0) return new Uint8Array(0);
var bytes = [0];
for (var i = 0; i < string.length; i++) {
var c = string[i];
var value = B58_ALPHABET.indexOf(c);
if (value === -1) {
throw new Error("Non-base58 character");
}
for (var j = 0; j < bytes.length; j++) {
bytes[j] *= 58;
}
bytes[0] += value;
var carry = 0;
for (var k = 0; k < bytes.length; k++) {
bytes[k] += carry;
carry = bytes[k] >> 8;
bytes[k] &= 0xff;
}
while (carry > 0) {
bytes.push(carry & 0xff);
carry >>= 8;
}
}
for (var leadingZeros = 0; leadingZeros < string.length && string[leadingZeros] === '1'; leadingZeros++) {
bytes.push(0);
}
return new Uint8Array(bytes.reverse());
}
/**
* Extracts 32-byte Ed25519 public key from a 'did:key:z...' multicodec identifier
*/
function didToPublicKey(did) {
if (!did || typeof did !== "string" || did.indexOf("did:key:z") !== 0) return null;
try {
var b58Str = did.substring(9);
var rawBytes = base58Decode(b58Str);
// Multicodec for Ed25519 public key starts with 0xed, 0x01 followed by 32 bytes public key
if (rawBytes.length === 34 && rawBytes[0] === 0xed && rawBytes[1] === 0x01) {
return rawBytes.subarray(2);
}
return null;
} catch (e) {
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment