Thanks to visit codestin.com
Credit goes to github.com

Skip to content

sid200727/AI_Multi-Sig_Wallet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 

Repository files navigation

⬡ AI Multi-Sig Wallet

License Claude Hyperledger Status

Three AI agents with distinct personalities co-own tokens.
They debate every transaction. They argue with each other. They sign — or refuse.

▶ Live Demo · PR #1597 · About boolpolicy


What is this?

This project is a live interactive demo of boolpolicy a new identity type I implemented in Hyperledger fabric-token-sdk that allows token ownership to be governed by a boolean expression over a set of identities.

Instead of "all signers must sign" (the old AND-only multi-sig), boolpolicy supports any boolean combination:

$0 OR $1              → either Alice or Bob can authorize
$0 AND $1             → both Alice and Bob must sign
($0 AND $1) OR $2     → both Alice+Bob together, or Charlie alone
$0 AND $1 AND $2      → all three must agree

Here, each signer $N is replaced by a Claude AI agent with a unique personality. They read the transaction, debate it in real-time, and sign or refuse based on their character.

The Agents

Agent Index Personality Strategy
Alice 🔵 $0 Risk-averse · Cautious Scrutinizes amounts, asks for compliance, skeptical of vague reasons
Bob 🟢 $1 Pragmatic · Business-focused Signs if the reason is legitimate, pushes back on over-caution
Charlie 🟡 $2 Aggressive · Growth-first Approves fast, impatient with Alice, refuses only clear fraud

Each agent is a separate Claude API call with a carefully crafted system prompt. They receive what previous agents said and react to each other — making the debate feel genuinely dynamic.

🔑 Getting Your API Key (Free — No Credit Card)

This app uses the Google Gemini API which has a completely free tier — no credit card required.

Step-by-step:

  1. Go to aistudio.google.com/app/apikey
  2. Sign in with your Google account
  3. Click Create API Key
  4. Copy the key — it looks like AIzaSy...
  5. Paste it into the modal when you open the app

That's it. The free tier gives you 15 requests per minute and 1 million tokens per day — more than enough for hundreds of debates.

Privacy note: Your API key is stored only in your browser's session memory. It's never sent to any server other than Google's Gemini API directly. It's cleared automatically when you close the tab.

Option 1 — GitHub Pages (recommended)

Just visit: https://github.com/sid200727/AI_Multi-Sig_Wallet

You'll be prompted to enter your AI Studio(Google) API key in the page.

Option 2 — Run Locally

git clone https://github.com/sid200727/ai-multisig-wallet
cd ai-multisig-wallet

# Open index.html in your browser
# No build step. No npm install. Pure HTML + JS.
open index.html

Then add your AI Studio API key to index.html:

// Line ~290 in index.html
const ANTHROPIC_KEY = 'sk-ant-...your-key-here...';

Get a free API key at console.aistudio.google.com.

⚙️ The boolpolicy Engine

The core logic comes directly from PR #1597 in Hyperledger fabric-token-sdk.

What I built in the PR

fabric-token-sdk/
├── token/core/common/boolpolicy/
│   ├── parser.go          ← Recursive descent parser
│   ├── parser_test.go     ← 30 unit tests
│   ├── identity.go        ← PolicyIdentity (ASN.1 serialized)
│   ├── sig.go             ← PolicyVerifier + sparse signature envelope
│   ├── deserializer.go    ← TypedIdentityDeserializer
│   └── verify_test.go     ← 14 unit tests for Verify
├── token/driver/wallet.go ← PolicyIdentityType = 6
└── token/core/fabtoken/v1/driver/deserializer.go  ← registration
    token/core/zkatdlog/nogh/v1/driver/deserializer.go

The Grammar

The policy parser implements this grammar (AND binds tighter than OR):

expr     = or_expr
or_expr  = and_expr ( 'OR' and_expr )*
and_expr = primary  ( 'AND' primary )*
primary  = '$' digits | '(' expr ')'

This means $0 OR $1 AND $2 is parsed as $0 OR ($1 AND $2) — correct precedence without any special-casing, it falls out naturally from the grammar layering.

Policy Evaluation in this Demo

function evalPolicy(policy, sigs) {
  // sigs = [true/false, true/false, true/false]
  // Replace $N references with actual signature booleans
  let expr = policy
    .replace(/\$0/g, sigs[0])
    .replace(/\$1/g, sigs[1])
    .replace(/\$2/g, sigs[2]);
  // Evaluate: "true OR (false AND true)" → true
  return Function('"use strict"; return (' + expr + ')')();
}

🧠 Code Walkthrough

1. Agent Personalities (system prompts)

Each agent is defined with:

  • A name and index (maps to $0, $1, $2 in policy expressions)
  • A system prompt that defines their personality and decision style
  • A mandatory instruction: end every response with SIGN or REFUSE
const agents = {
  alice: {
    index: 0,
    system: `You are Alice, a cautious risk-averse financial agent...
             You MUST end your response with: SIGN or REFUSE.`
  },
  bob: { index: 1, system: `You are Bob, a pragmatic business-focused agent...` },
  charlie: { index: 2, system: `You are Charlie, an aggressive growth-focused agent...` }
};

2. Sequential Debate (agents react to each other)

Agents are called sequentially, not in parallel. Each agent receives what previous agents said:

async function callAgent(agentKey, tx, prevMsgs) {
  let context = '';
  if (prevMsgs.length > 0) {
    context = '\n\nOther agents have already commented:\n'
      + prevMsgs.map(m => `${m.name}: ${m.text}`).join('\n')
      + '\n\nBriefly react to what they said, then give your own verdict.';
  }
  // Call Claude API with personality + transaction + context
}

This creates genuine multi-turn dynamics — Bob might push back on Alice's refusal, and Charlie might agree with Bob.

3. Only relevant agents are called

If the policy is $0 OR $1, Charlie is never called. The app extracts which agent indices appear in the policy expression:

const order = ['alice','bob','charlie']
  .filter(a => activePolicy.includes(`$${agents[a].index}`));

4. Signature parsing

The agent's final line must be SIGN or REFUSE. The app splits the response, reads the last word, and strips it from the displayed text:

const lines = reply.split('\n').map(l => l.trim()).filter(Boolean);
const lastWord = lines[lines.length - 1].toUpperCase();
const signed = lastWord === 'SIGN';
const displayText = lines
  .filter(l => l.toUpperCase() !== 'SIGN' && l.toUpperCase() !== 'REFUSE')
  .join(' ');

🧪 Try These Scenarios

Policy Transaction Expected outcome
$0 OR $1 100 TKN, "office supplies" One of Alice/Bob approves → passes
$0 AND $1 900 TKN, "mystery purchase" Alice likely refuses → fails
$2 999 TKN, anything Charlie almost always signs
($0 AND $1) OR $2 500 TKN, "risky bet" Alice+Bob split → depends on Charlie
$0 AND $1 AND $2 1 TKN, "test payment" All three must agree

🔗 Related

👤 Author

Siddhi Khandelwal — independent open-source contributor to Hyperledger Labs

License

Apache 2.0 — same as Hyperledger fabric-token-sdk.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages