Skip to main content

ai_agent_bitcoin_escrow/
lib.rs

1//! # AI Agent Bitcoin Escrow Library
2//!
3//! A Rust library that enables AI agents to create, manage, and execute Bitcoin
4//! escrow contracts using multisig. The library supports condition-based fund
5//! releases triggered by AI agent decisions or external oracles, with full
6//! audit logging for all actions.
7//!
8//! ## Features
9//!
10//! - **Multisig Support**: 2-of-3 (or n-of-m) multisig escrow contracts
11//! - **Condition-Based Release**: AI decisions, oracle triggers, timelocks
12//! - **Audit Logging**: Immutable, chained audit log for all operations
13//! - **Oracle Integration**: HTTP-based oracle support for real-world data
14//! - **AI Agent Autonomy**: Designed for autonomous AI agent economic activities
15//!
16//! ## Quick Start
17//!
18//! ```rust,no_run
19//! use ai_agent_bitcoin_escrow::{
20//!     escrow::{EscrowBuilder, EscrowManager},
21//!     multisig::create_participant,
22//!     conditions::ConditionBuilder,
23//!     audit::AuditLogger,
24//!     types::{EscrowConfig, EscrowRole},
25//! };
26//! use bitcoin::Network;
27//!
28//! // Create an escrow manager with audit logging
29//! let audit = AuditLogger::new("/tmp/audit.log").unwrap();
30//! let mut manager = EscrowManager::new(audit);
31//!
32//! // Create participants
33//! let (buyer, _buyer_key) = create_participant(
34//!     EscrowRole::Buyer, 
35//!     "buyer-1".to_string(), 
36//!     Network::Testnet
37//! ).unwrap();
38//! let (seller, _seller_key) = create_participant(
39//!     EscrowRole::Seller, 
40//!     "seller-1".to_string(), 
41//!     Network::Testnet
42//! ).unwrap();
43//! let (arbiter, _arbiter_key) = create_participant(
44//!     EscrowRole::Arbiter, 
45//!     "arbiter-1".to_string(), 
46//!     Network::Testnet
47//! ).unwrap();
48//!
49//! // Build an escrow contract
50//! let contract = EscrowBuilder::new()
51//!     .network(Network::Testnet)
52//!     .threshold(2)
53//!     .participant(buyer)
54//!     .participant(seller)
55//!     .participant(arbiter)
56//!     .description("AI agent bounty payment")
57//!     .build()
58//!     .unwrap();
59//!
60//! println!("Escrow contract created: {}", contract.id);
61//! ```
62//!
63//! ## Architecture
64//!
65//! The library is organized into several modules:
66//!
67//! - [`escrow`] - Main escrow contract management
68//! - [`multisig`] - Multisignature wallet operations
69//! - [`conditions`] - Release condition evaluation
70//! - [`audit`] - Immutable audit logging
71//! - [`oracle`] - External oracle integration
72//! - [`types`] - Common types and structures
73//! - [`error`] - Error handling
74//!
75//! ## AI Agent Integration
76//!
77//! This library is designed to be used by AI agents for autonomous economic
78//! activities. Key features for AI agent autonomy:
79//!
80//! - **Self-Custody**: AI agents control their own keys
81//! - **Verifiable Actions**: All operations are logged in an immutable audit log
82//! - **Conditional Releases**: Funds can be released based on AI decisions
83//! - **Oracle Integration**: Real-world data can trigger releases
84//!
85//! ## Security Considerations
86//!
87//! - All private keys should be securely stored
88//! - The audit log provides a verifiable record of all actions
89//! - Multisig ensures no single party can unilaterally control funds
90//! - Timelocks provide a safety mechanism for dispute resolution
91//!
92//! ## License
93//!
94//! Dual-licensed under MIT or Apache-2.0.
95
96pub mod audit;
97pub mod conditions;
98pub mod error;
99pub mod escrow;
100pub mod multisig;
101pub mod oracle;
102pub mod types;
103
104// Re-export commonly used types at the crate root
105pub use error::{EscrowError, Result};
106pub use escrow::{EscrowBuilder, EscrowContract, EscrowManager};
107pub use types::{
108    AgentId, ConditionResult, EscrowConfig, EscrowId, EscrowParticipant,
109    EscrowRole, EscrowStatus, OracleId, ReleaseCondition,
110};
111
112/// Library version.
113pub const VERSION: &str = env!("CARGO_PKG_VERSION");
114
115/// Library name.
116pub const NAME: &str = env!("CARGO_PKG_NAME");
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121    use audit::AuditLogger;
122    use bitcoin::Network;
123    use escrow::EscrowBuilder;
124    use multisig::create_participant;
125    use types::EscrowRole;
126
127    #[test]
128    fn test_library_version() {
129        assert!(!VERSION.is_empty());
130        assert_eq!(NAME, "ai-agent-bitcoin-escrow");
131    }
132
133    #[test]
134    fn test_full_escrow_workflow() {
135        // Create participants
136        let (buyer, _) = create_participant(EscrowRole::Buyer, "buyer-1".to_string(), Network::Testnet).unwrap();
137        let (seller, _) = create_participant(EscrowRole::Seller, "seller-1".to_string(), Network::Testnet).unwrap();
138        let (arbiter, _) = create_participant(EscrowRole::Arbiter, "arbiter-1".to_string(), Network::Testnet).unwrap();
139
140        // Build escrow
141        let contract = EscrowBuilder::new()
142            .network(Network::Testnet)
143            .threshold(2)
144            .participant(buyer)
145            .participant(seller)
146            .participant(arbiter)
147            .description("Test bounty payment")
148            .build()
149            .unwrap();
150
151        // Verify contract
152        assert_eq!(contract.status, EscrowStatus::Created);
153        assert_eq!(contract.participants.len(), 3);
154        assert_eq!(contract.config.threshold, 2);
155
156        // Initialize multisig
157        let mut contract = contract;
158        contract.initialize_multisig().unwrap();
159        assert!(contract.multisig.is_some());
160
161        // Get escrow address
162        let address = contract.escrow_address().unwrap();
163        assert!(!address.to_string().is_empty());
164    }
165
166    #[tokio::test]
167    async fn test_escrow_manager_workflow() {
168        let audit = AuditLogger::in_memory();
169        let mut manager = EscrowManager::new(audit);
170
171        // Create contract
172        let contract = manager
173            .create_contract(
174                EscrowConfig::default(),
175                Some("Test escrow".to_string()),
176                "test-agent".to_string(),
177            )
178            .unwrap();
179
180        let contract_id = contract.id.clone();
181
182        // Add participants
183        let (buyer, _) = create_participant(EscrowRole::Buyer, "buyer-1".to_string(), Network::Testnet).unwrap();
184        let (seller, _) = create_participant(EscrowRole::Seller, "seller-1".to_string(), Network::Testnet).unwrap();
185        let (arbiter, _) = create_participant(EscrowRole::Arbiter, "arbiter-1".to_string(), Network::Testnet).unwrap();
186
187        manager
188            .add_participant(&contract_id, buyer, "test-agent".to_string())
189            .unwrap();
190        manager
191            .add_participant(&contract_id, seller, "test-agent".to_string())
192            .unwrap();
193        manager
194            .add_participant(&contract_id, arbiter, "test-agent".to_string())
195            .unwrap();
196
197        // Initialize multisig
198        let address = manager.initialize_multisig(&contract_id).unwrap();
199        assert!(!address.to_string().is_empty());
200
201        // Verify audit log
202        let entries = manager.audit().get_entries(&contract_id);
203        assert!(entries.len() >= 4); // Created + 3 participants
204    }
205}