Update database paths and fix foreign key references across coordinator API
- Change SQLite database path from `/home/oib/windsurf/aitbc/data/` to `/opt/data/` - Fix foreign key references to use correct table names (users, wallets, gpu_registry) - Replace governance router with new governance and community routers - Add multi-modal RL router to main application - Simplify DEPLOYMENT_READINESS_REPORT.md to focus on production deployment status - Update governance router with decentralized DAO voting
This commit is contained in:
566
contracts/AIPowerRental.sol
Normal file
566
contracts/AIPowerRental.sol
Normal file
@@ -0,0 +1,566 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
|
||||
import "@openzeppelin/contracts/security/Pausable.sol";
|
||||
import "./ZKReceiptVerifier.sol";
|
||||
import "./Groth16Verifier.sol";
|
||||
|
||||
/**
|
||||
* @title AI Power Rental Contract
|
||||
* @dev Smart contract for AI compute power rental agreements with performance verification
|
||||
* @notice Manages rental agreements between AI compute providers and consumers
|
||||
*/
|
||||
contract AIPowerRental is Ownable, ReentrancyGuard, Pausable {
|
||||
|
||||
// State variables
|
||||
IERC20 public aitbcToken;
|
||||
ZKReceiptVerifier public zkVerifier;
|
||||
Groth16Verifier public groth16Verifier;
|
||||
|
||||
uint256 public agreementCounter;
|
||||
uint256 public platformFeePercentage = 250; // 2.5% in basis points
|
||||
uint256 public minRentalDuration = 3600; // 1 hour minimum
|
||||
uint256 public maxRentalDuration = 86400 * 30; // 30 days maximum
|
||||
|
||||
// Structs
|
||||
struct RentalAgreement {
|
||||
uint256 agreementId;
|
||||
address provider;
|
||||
address consumer;
|
||||
uint256 duration;
|
||||
uint256 price;
|
||||
uint256 startTime;
|
||||
uint256 endTime;
|
||||
uint256 platformFee;
|
||||
RentalStatus status;
|
||||
PerformanceMetrics performance;
|
||||
string gpuModel;
|
||||
uint256 computeUnits;
|
||||
bytes32 performanceProof;
|
||||
}
|
||||
|
||||
struct PerformanceMetrics {
|
||||
uint256 responseTime;
|
||||
uint256 accuracy;
|
||||
uint256 availability;
|
||||
uint256 computePower;
|
||||
bool withinSLA;
|
||||
uint256 lastUpdateTime;
|
||||
}
|
||||
|
||||
struct DisputeInfo {
|
||||
bool exists;
|
||||
address initiator;
|
||||
string reason;
|
||||
uint256 disputeTime;
|
||||
bool resolved;
|
||||
uint256 resolutionAmount;
|
||||
}
|
||||
|
||||
// Enums
|
||||
enum RentalStatus {
|
||||
Created,
|
||||
Active,
|
||||
Completed,
|
||||
Disputed,
|
||||
Cancelled,
|
||||
Expired
|
||||
}
|
||||
|
||||
// Mappings
|
||||
mapping(uint256 => RentalAgreement) public rentalAgreements;
|
||||
mapping(uint256 => DisputeInfo) public disputes;
|
||||
mapping(address => uint256[]) public providerAgreements;
|
||||
mapping(address => uint256[]) public consumerAgreements;
|
||||
mapping(address => bool) public authorizedProviders;
|
||||
mapping(address => bool) public authorizedConsumers;
|
||||
|
||||
// Events
|
||||
event AgreementCreated(
|
||||
uint256 indexed agreementId,
|
||||
address indexed provider,
|
||||
address indexed consumer,
|
||||
uint256 duration,
|
||||
uint256 price,
|
||||
string gpuModel,
|
||||
uint256 computeUnits
|
||||
);
|
||||
|
||||
event AgreementStarted(
|
||||
uint256 indexed agreementId,
|
||||
uint256 startTime,
|
||||
uint256 endTime
|
||||
);
|
||||
|
||||
event AgreementCompleted(
|
||||
uint256 indexed agreementId,
|
||||
uint256 completionTime,
|
||||
bool withinSLA
|
||||
);
|
||||
|
||||
event PaymentProcessed(
|
||||
uint256 indexed agreementId,
|
||||
address indexed provider,
|
||||
uint256 amount,
|
||||
uint256 platformFee
|
||||
);
|
||||
|
||||
event PerformanceSubmitted(
|
||||
uint256 indexed agreementId,
|
||||
uint256 responseTime,
|
||||
uint256 accuracy,
|
||||
uint256 availability,
|
||||
bool withinSLA
|
||||
);
|
||||
|
||||
event DisputeFiled(
|
||||
uint256 indexed agreementId,
|
||||
address indexed initiator,
|
||||
string reason
|
||||
);
|
||||
|
||||
event DisputeResolved(
|
||||
uint256 indexed agreementId,
|
||||
uint256 resolutionAmount,
|
||||
bool resolvedInFavorOfProvider
|
||||
);
|
||||
|
||||
event ProviderAuthorized(address indexed provider);
|
||||
event ProviderRevoked(address indexed provider);
|
||||
event ConsumerAuthorized(address indexed consumer);
|
||||
event ConsumerRevoked(address indexed consumer);
|
||||
|
||||
// Modifiers
|
||||
modifier onlyAuthorizedProvider() {
|
||||
require(authorizedProviders[msg.sender], "Not authorized provider");
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyAuthorizedConsumer() {
|
||||
require(authorizedConsumers[msg.sender], "Not authorized consumer");
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyParticipant(uint256 _agreementId) {
|
||||
require(
|
||||
rentalAgreements[_agreementId].provider == msg.sender ||
|
||||
rentalAgreements[_agreementId].consumer == msg.sender,
|
||||
"Not agreement participant"
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier agreementExists(uint256 _agreementId) {
|
||||
require(_agreementId < agreementCounter, "Agreement does not exist");
|
||||
_;
|
||||
}
|
||||
|
||||
modifier validStatus(uint256 _agreementId, RentalStatus _requiredStatus) {
|
||||
require(rentalAgreements[_agreementId].status == _requiredStatus, "Invalid agreement status");
|
||||
_;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
constructor(
|
||||
address _aitbcToken,
|
||||
address _zkVerifier,
|
||||
address _groth16Verifier
|
||||
) {
|
||||
aitbcToken = IERC20(_aitbcToken);
|
||||
zkVerifier = ZKReceiptVerifier(_zkVerifier);
|
||||
groth16Verifier = Groth16Verifier(_groth16Verifier);
|
||||
agreementCounter = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Creates a new rental agreement
|
||||
* @param _provider Address of the compute provider
|
||||
* @param _consumer Address of the compute consumer
|
||||
* @param _duration Duration in seconds
|
||||
* @param _price Total price in AITBC tokens
|
||||
* @param _gpuModel GPU model being rented
|
||||
* @param _computeUnits Amount of compute units
|
||||
*/
|
||||
function createRental(
|
||||
address _provider,
|
||||
address _consumer,
|
||||
uint256 _duration,
|
||||
uint256 _price,
|
||||
string memory _gpuModel,
|
||||
uint256 _computeUnits
|
||||
) external onlyAuthorizedConsumer nonReentrant whenNotPaused returns (uint256) {
|
||||
require(_duration >= minRentalDuration, "Duration too short");
|
||||
require(_duration <= maxRentalDuration, "Duration too long");
|
||||
require(_price > 0, "Price must be positive");
|
||||
require(authorizedProviders[_provider], "Provider not authorized");
|
||||
|
||||
uint256 agreementId = agreementCounter++;
|
||||
uint256 platformFee = (_price * platformFeePercentage) / 10000;
|
||||
|
||||
rentalAgreements[agreementId] = RentalAgreement({
|
||||
agreementId: agreementId,
|
||||
provider: _provider,
|
||||
consumer: _consumer,
|
||||
duration: _duration,
|
||||
price: _price,
|
||||
startTime: 0,
|
||||
endTime: 0,
|
||||
platformFee: platformFee,
|
||||
status: RentalStatus.Created,
|
||||
performance: PerformanceMetrics({
|
||||
responseTime: 0,
|
||||
accuracy: 0,
|
||||
availability: 0,
|
||||
computePower: 0,
|
||||
withinSLA: false,
|
||||
lastUpdateTime: 0
|
||||
}),
|
||||
gpuModel: _gpuModel,
|
||||
computeUnits: _computeUnits,
|
||||
performanceProof: bytes32(0)
|
||||
});
|
||||
|
||||
providerAgreements[_provider].push(agreementId);
|
||||
consumerAgreements[_consumer].push(agreementId);
|
||||
|
||||
emit AgreementCreated(
|
||||
agreementId,
|
||||
_provider,
|
||||
_consumer,
|
||||
_duration,
|
||||
_price,
|
||||
_gpuModel,
|
||||
_computeUnits
|
||||
);
|
||||
|
||||
return agreementId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Starts a rental agreement and locks payment
|
||||
* @param _agreementId ID of the agreement to start
|
||||
*/
|
||||
function startRental(uint256 _agreementId)
|
||||
external
|
||||
agreementExists(_agreementId)
|
||||
validStatus(_agreementId, RentalStatus.Created)
|
||||
nonReentrant
|
||||
{
|
||||
RentalAgreement storage agreement = rentalAgreements[_agreementId];
|
||||
|
||||
require(msg.sender == agreement.consumer, "Only consumer can start");
|
||||
|
||||
uint256 totalAmount = agreement.price + agreement.platformFee;
|
||||
|
||||
// Transfer tokens from consumer to contract
|
||||
require(
|
||||
aitbcToken.transferFrom(msg.sender, address(this), totalAmount),
|
||||
"Payment transfer failed"
|
||||
);
|
||||
|
||||
agreement.startTime = block.timestamp;
|
||||
agreement.endTime = block.timestamp + agreement.duration;
|
||||
agreement.status = RentalStatus.Active;
|
||||
|
||||
emit AgreementStarted(_agreementId, agreement.startTime, agreement.endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Completes a rental agreement and processes payment
|
||||
* @param _agreementId ID of the agreement to complete
|
||||
*/
|
||||
function completeRental(uint256 _agreementId)
|
||||
external
|
||||
agreementExists(_agreementId)
|
||||
validStatus(_agreementId, RentalStatus.Active)
|
||||
onlyParticipant(_agreementId)
|
||||
nonReentrant
|
||||
{
|
||||
RentalAgreement storage agreement = rentalAgreements[_agreementId];
|
||||
|
||||
require(block.timestamp >= agreement.endTime, "Rental period not ended");
|
||||
|
||||
agreement.status = RentalStatus.Completed;
|
||||
|
||||
// Process payment to provider
|
||||
uint256 providerAmount = agreement.price;
|
||||
uint256 platformFeeAmount = agreement.platformFee;
|
||||
|
||||
if (providerAmount > 0) {
|
||||
require(
|
||||
aitbcToken.transfer(agreement.provider, providerAmount),
|
||||
"Provider payment failed"
|
||||
);
|
||||
}
|
||||
|
||||
if (platformFeeAmount > 0) {
|
||||
require(
|
||||
aitbcToken.transfer(owner(), platformFeeAmount),
|
||||
"Platform fee transfer failed"
|
||||
);
|
||||
}
|
||||
|
||||
emit PaymentProcessed(_agreementId, agreement.provider, providerAmount, platformFeeAmount);
|
||||
emit AgreementCompleted(_agreementId, block.timestamp, agreement.performance.withinSLA);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Files a dispute for a rental agreement
|
||||
* @param _agreementId ID of the agreement
|
||||
* @param _reason Reason for the dispute
|
||||
*/
|
||||
function disputeRental(uint256 _agreementId, string memory _reason)
|
||||
external
|
||||
agreementExists(_agreementId)
|
||||
onlyParticipant(_agreementId)
|
||||
nonReentrant
|
||||
{
|
||||
RentalAgreement storage agreement = rentalAgreements[_agreementId];
|
||||
|
||||
require(
|
||||
agreement.status == RentalStatus.Active ||
|
||||
agreement.status == RentalStatus.Completed,
|
||||
"Cannot dispute this agreement"
|
||||
);
|
||||
|
||||
require(!disputes[_agreementId].exists, "Dispute already exists");
|
||||
|
||||
disputes[_agreementId] = DisputeInfo({
|
||||
exists: true,
|
||||
initiator: msg.sender,
|
||||
reason: _reason,
|
||||
disputeTime: block.timestamp,
|
||||
resolved: false,
|
||||
resolutionAmount: 0
|
||||
});
|
||||
|
||||
agreement.status = RentalStatus.Disputed;
|
||||
|
||||
emit DisputeFiled(_agreementId, msg.sender, _reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Submits performance metrics for a rental agreement
|
||||
* @param _agreementId ID of the agreement
|
||||
* @param _responseTime Response time in milliseconds
|
||||
* @param _accuracy Accuracy percentage (0-100)
|
||||
* @param _availability Availability percentage (0-100)
|
||||
* @param _computePower Compute power utilized
|
||||
* @param _zkProof Zero-knowledge proof for performance verification
|
||||
*/
|
||||
function submitPerformance(
|
||||
uint256 _agreementId,
|
||||
uint256 _responseTime,
|
||||
uint256 _accuracy,
|
||||
uint256 _availability,
|
||||
uint256 _computePower,
|
||||
bytes memory _zkProof
|
||||
) external agreementExists(_agreementId) onlyAuthorizedProvider {
|
||||
RentalAgreement storage agreement = rentalAgreements[_agreementId];
|
||||
|
||||
require(agreement.status == RentalStatus.Active, "Agreement not active");
|
||||
|
||||
// Verify ZK proof
|
||||
bool proofValid = zkVerifier.verifyPerformanceProof(
|
||||
_agreementId,
|
||||
_responseTime,
|
||||
_accuracy,
|
||||
_availability,
|
||||
_computePower,
|
||||
_zkProof
|
||||
);
|
||||
|
||||
require(proofValid, "Invalid performance proof");
|
||||
|
||||
agreement.performance = PerformanceMetrics({
|
||||
responseTime: _responseTime,
|
||||
accuracy: _accuracy,
|
||||
availability: _availability,
|
||||
computePower: _computePower,
|
||||
withinSLA: _calculateSLA(_responseTime, _accuracy, _availability),
|
||||
lastUpdateTime: block.timestamp
|
||||
});
|
||||
|
||||
agreement.performanceProof = keccak256(_zkProof);
|
||||
|
||||
emit PerformanceSubmitted(
|
||||
_agreementId,
|
||||
_responseTime,
|
||||
_accuracy,
|
||||
_availability,
|
||||
agreement.performance.withinSLA
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Authorizes a provider to offer compute services
|
||||
* @param _provider Address of the provider
|
||||
*/
|
||||
function authorizeProvider(address _provider) external onlyOwner {
|
||||
authorizedProviders[_provider] = true;
|
||||
emit ProviderAuthorized(_provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Revokes provider authorization
|
||||
* @param _provider Address of the provider
|
||||
*/
|
||||
function revokeProvider(address _provider) external onlyOwner {
|
||||
authorizedProviders[_provider] = false;
|
||||
emit ProviderRevoked(_provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Authorizes a consumer to rent compute services
|
||||
* @param _consumer Address of the consumer
|
||||
*/
|
||||
function authorizeConsumer(address _consumer) external onlyOwner {
|
||||
authorizedConsumers[_consumer] = true;
|
||||
emit ConsumerAuthorized(_consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Revokes consumer authorization
|
||||
* @param _consumer Address of the consumer
|
||||
*/
|
||||
function revokeConsumer(address _consumer) external onlyOwner {
|
||||
authorizedConsumers[_consumer] = false;
|
||||
emit ConsumerRevoked(_consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Resolves a dispute
|
||||
* @param _agreementId ID of the disputed agreement
|
||||
* @param _resolutionAmount Amount to award to the winner
|
||||
* @param _resolveInFavorOfProvider True if resolving in favor of provider
|
||||
*/
|
||||
function resolveDispute(
|
||||
uint256 _agreementId,
|
||||
uint256 _resolutionAmount,
|
||||
bool _resolveInFavorOfProvider
|
||||
) external onlyOwner agreementExists(_agreementId) {
|
||||
require(disputes[_agreementId].exists, "No dispute exists");
|
||||
require(!disputes[_agreementId].resolved, "Dispute already resolved");
|
||||
|
||||
RentalAgreement storage agreement = rentalAgreements[_agreementId];
|
||||
disputes[_agreementId].resolved = true;
|
||||
disputes[_agreementId].resolutionAmount = _resolutionAmount;
|
||||
|
||||
address winner = _resolveInFavorOfProvider ? agreement.provider : agreement.consumer;
|
||||
|
||||
if (_resolutionAmount > 0) {
|
||||
require(
|
||||
aitbcToken.transfer(winner, _resolutionAmount),
|
||||
"Resolution payment failed"
|
||||
);
|
||||
}
|
||||
|
||||
emit DisputeResolved(_agreementId, _resolutionAmount, _resolveInFavorOfProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Cancels a rental agreement (only before it starts)
|
||||
* @param _agreementId ID of the agreement to cancel
|
||||
*/
|
||||
function cancelRental(uint256 _agreementId)
|
||||
external
|
||||
agreementExists(_agreementId)
|
||||
validStatus(_agreementId, RentalStatus.Created)
|
||||
onlyParticipant(_agreementId)
|
||||
nonReentrant
|
||||
{
|
||||
RentalAgreement storage agreement = rentalAgreements[_agreementId];
|
||||
agreement.status = RentalStatus.Cancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Emergency pause function
|
||||
*/
|
||||
function pause() external onlyOwner {
|
||||
_pause();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Unpause function
|
||||
*/
|
||||
function unpause() external onlyOwner {
|
||||
_unpause();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Updates platform fee percentage
|
||||
* @param _newFee New fee percentage in basis points
|
||||
*/
|
||||
function updatePlatformFee(uint256 _newFee) external onlyOwner {
|
||||
require(_newFee <= 1000, "Fee too high"); // Max 10%
|
||||
platformFeePercentage = _newFee;
|
||||
}
|
||||
|
||||
// View functions
|
||||
|
||||
/**
|
||||
* @dev Gets rental agreement details
|
||||
* @param _agreementId ID of the agreement
|
||||
*/
|
||||
function getRentalAgreement(uint256 _agreementId)
|
||||
external
|
||||
view
|
||||
agreementExists(_agreementId)
|
||||
returns (RentalAgreement memory)
|
||||
{
|
||||
return rentalAgreements[_agreementId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets dispute information
|
||||
* @param _agreementId ID of the agreement
|
||||
*/
|
||||
function getDisputeInfo(uint256 _agreementId)
|
||||
external
|
||||
view
|
||||
agreementExists(_agreementId)
|
||||
returns (DisputeInfo memory)
|
||||
{
|
||||
return disputes[_agreementId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets all agreements for a provider
|
||||
* @param _provider Address of the provider
|
||||
*/
|
||||
function getProviderAgreements(address _provider)
|
||||
external
|
||||
view
|
||||
returns (uint256[] memory)
|
||||
{
|
||||
return providerAgreements[_provider];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets all agreements for a consumer
|
||||
* @param _consumer Address of the consumer
|
||||
*/
|
||||
function getConsumerAgreements(address _consumer)
|
||||
external
|
||||
view
|
||||
returns (uint256[] memory)
|
||||
{
|
||||
return consumerAgreements[_consumer];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Calculates if performance meets SLA requirements
|
||||
*/
|
||||
function _calculateSLA(
|
||||
uint256 _responseTime,
|
||||
uint256 _accuracy,
|
||||
uint256 _availability
|
||||
) internal pure returns (bool) {
|
||||
return _responseTime <= 5000 && // <= 5 seconds
|
||||
_accuracy >= 95 && // >= 95% accuracy
|
||||
_availability >= 99; // >= 99% availability
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user