Skip to content

Commit 61aa011

Browse files
committed
init
1 parent f3003f1 commit 61aa011

File tree

12 files changed

+387
-0
lines changed

12 files changed

+387
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: Build and Release
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
permissions:
10+
contents: write
11+
12+
jobs:
13+
build-and-release:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v3
17+
18+
- name: Set up Python
19+
uses: actions/setup-python@v4
20+
with:
21+
python-version: '3.11'
22+
23+
- name: Set up Docker Buildx
24+
uses: docker/setup-buildx-action@v2
25+
26+
- name: Build Docker image
27+
uses: docker/build-push-action@v4
28+
with:
29+
context: .
30+
load: true
31+
tags: |
32+
my-proof:${{ github.run_number }}
33+
my-proof:latest
34+
cache-from: type=gha
35+
cache-to: type=gha,mode=max
36+
37+
- name: Export image to file
38+
run: |
39+
docker save my-proof:latest | gzip > my-proof-${{ github.run_number }}.tar.gz
40+
- name: Generate release body
41+
run: |
42+
echo "Image SHA256: $(sha256sum my-proof-${{ github.run_number }}.tar.gz | cut -d' ' -f1)" >> release_body.txt
43+
- name: Upload image
44+
uses: actions/upload-artifact@v3
45+
with:
46+
name: my-proof-image
47+
path: my-proof-${{ github.run_number }}.tar.gz
48+
49+
- name: Create Release and Upload Assets
50+
uses: softprops/action-gh-release@v1
51+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
52+
env:
53+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
54+
with:
55+
tag_name: v${{ github.run_number }}
56+
name: Release v${{ github.run_number }}
57+
body_path: release_body.txt
58+
draft: false
59+
prerelease: false
60+
files: |
61+
./my-proof-${{ github.run_number }}.tar.gz
62+
- name: Log build result
63+
if: always()
64+
run: |
65+
if [ ${{ job.status }} == "success" ]; then
66+
echo "Build and release completed successfully"
67+
else
68+
echo "Build and release failed"
69+
fi

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
.DS_Store
3+
/venv

Dockerfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FROM python:3.12-slim
2+
3+
4+
WORKDIR /app
5+
6+
COPY . /app
7+
8+
# Install any needed packages specified in requirements.txt
9+
RUN pip install --no-cache-dir -r requirements.txt
10+
11+
CMD ["python", "-m", "my_proof"]

LICENSE

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
The MIT License (MIT)
2+
Copyright © 2024 Corsali, Inc. dba Vana
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5+
6+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7+
8+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# VanaTensor Satya Proof of Contribution
2+
3+
This repository creating a [proof of contribution](https://docs.vana.org/vana/core-concepts/key-elements/proof-of-contribution) tasks using Python. It is executed on Vana's Satya Network, a group of highly confidential and secure compute nodes that can validate data without revealing its contents to the node operator.
4+
5+
## Overview
6+
7+
This poc provides a basic structure for building proof tasks that:
8+
9+
1. Read input files from the `/input` directory.
10+
2. Process the data securely, running any necessary validations to prove the data authentic, unique, high quality, etc.
11+
3. Write proof results to the `/output/results.json` file in the following format:
12+
13+
```json
14+
{
15+
"dlp_id": 1,
16+
"valid": true,
17+
"score": 0.7614457831325301,
18+
"time_minimums": 1.0,
19+
"time_correlation": 1.0,
20+
"time_distribution": 1.0,
21+
"repeat_anwsers": 1.0,
22+
"both_sides": 0,
23+
"model_distribution": 0.0,
24+
"poison_data": 0.0,
25+
"uniqueness": 0.0
26+
}
27+
```
28+
29+
The project is designed to work with Intel TDX (Trust Domain Extensions), providing hardware-level isolation and security guarantees for confidential computing workloads.
30+
31+
## Project Structure
32+
33+
- `my_proof/`: Contains the main proof logic
34+
- `proof.py`: Implements the proof generation logic
35+
- `__main__.py`: Entry point for the proof execution
36+
- `models/`: Data models for the proof system
37+
- `demo/`: Contains sample input and output for testing
38+
- `Dockerfile`: Defines the container image for the proof task
39+
- `requirements.txt`: Python package dependencies
40+
41+
## Customizing the Proof Logic
42+
43+
The main proof logic is implemented in `my_proof/proof.py`. To customize it, update the `Proof.generate()` function to change how input files are processed.
44+
45+
The proof can be configured using environment variables:
46+
47+
- `USER_EMAIL`: The email address of the data contributor, to verify data ownership
48+
49+
## Local Development
50+
51+
To setup venv and install dependencies:
52+
53+
```bash
54+
python3 -m venv venv
55+
source venv/bin/activate
56+
pip install -r requirements.txt
57+
export PYTHONPATH=.
58+
```
59+
60+
To run the proof locally for testing, you can use Docker:
61+
62+
```bash
63+
docker build -t my-proof .
64+
```
65+
66+
```bash
67+
docker run --rm --volume $(pwd)/input:/input --volume $(pwd)/output:/output -e AWS_ACCESS_KEY_ID=<your-access-key-id> -e AWS_SECRET_ACCESS_KEY=<your-secret-access-key> my-proof
68+
```
69+
70+
## Running with Intel TDX
71+
72+
Intel TDX (Trust Domain Extensions) provides hardware-based memory encryption and integrity protection for virtual machines. To run this container in a TDX-enabled environment, follow your infrastructure provider's specific instructions for deploying confidential containers.
73+
74+
Common volume mounts and environment variables:
75+
76+
```bash
77+
docker run --rm --volume /path/to/input:/input --volume /path/to/output:/output -e AWS_ACCESS_KEY_ID=<your-access-key-id> -e AWS_SECRET_ACCESS_KEY=<your-secret-access-key> my-proof
78+
```
79+
80+
Remember to populate the `/input` directory with the files you want to process.
81+
82+
## Security Features
83+
84+
This proof leverages several security features:
85+
86+
1. **Hardware-based Isolation**: The proof runs inside a TDX-protected environment, isolating it from the rest of the system
87+
2. **Input/Output Isolation**: Input and output directories are mounted separately, ensuring clear data flow boundaries
88+
3. **Minimal Container**: Uses a minimal Python base image to reduce attack surface
89+
90+
## Contributing
91+
92+
If you have suggestions for improving this poc, please open an issue or submit a pull request.
93+
94+
## License
95+
96+
[MIT License](LICENSE)

my_proof/Swipes.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[
2+
{
3+
"imgUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS-iIwAvtGqGJj7uq6Ub17LIDPR3j82UiLOdA&s",
4+
"imgText": "Horse",
5+
"userResponse": 1
6+
},
7+
{
8+
"imgUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTLcD2uF7NRv4r285_j3RADo9gjFCXsVaJ74g&s",
9+
"imgText": "Car",
10+
"userResponse": 1
11+
},
12+
{
13+
"imgUrl": "https://i.natgeofe.com/n/4cebbf38-5df4-4ed0-864a-4ebeb64d33a4/NationalGeographic_1468962_16x9.jpg",
14+
"imgText": "Cat",
15+
"userResponse": 1
16+
},
17+
{
18+
"imgUrl": "https://i.natgeofe.com/n/4cebbf38-5df4-4ed0-864a-4ebeb64d33a4/NationalGeographic_1468962_16x9.jpg",
19+
"imgText": "Dog",
20+
"userResponse": 1
21+
},
22+
{
23+
"imgUrl": "https://i.natgeofe.com/n/4cebbf38-5df4-4ed0-864a-4ebeb64d33a4/NationalGeographic_1468962_16x9.jpg",
24+
"imgText": "Cat",
25+
"userResponse": 0
26+
}
27+
]

my_proof/__init__.py

Whitespace-only changes.

my_proof/__main__.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import json
2+
import logging
3+
import os
4+
import sys
5+
import traceback
6+
import zipfile
7+
from typing import Dict, Any
8+
9+
from my_proof.proof import Proof
10+
11+
INPUT_DIR, OUTPUT_DIR = '/input', '/output'
12+
13+
logging.basicConfig(level=logging.INFO, format='%(message)s')
14+
15+
16+
def load_config() -> Dict[str, Any]:
17+
"""Load proof configuration from environment variables."""
18+
config = {
19+
'dlp_id': 1,#to be changed
20+
'input_dir': INPUT_DIR,
21+
}
22+
logging.info(f"Using config: {json.dumps(config, indent=2)}")
23+
return config
24+
25+
26+
def run() -> None:
27+
"""Generate proofs for all input files."""
28+
config = load_config()
29+
input_files_exist = os.path.isdir(INPUT_DIR) and bool(os.listdir(INPUT_DIR))
30+
31+
if not input_files_exist:
32+
raise FileNotFoundError(f"No input files found in {INPUT_DIR}")
33+
34+
proof = Proof(config)
35+
proof_response = proof.generate()
36+
37+
output_path = os.path.join(OUTPUT_DIR, "results.json")
38+
with open(output_path, 'w') as f:
39+
json.dump(proof_response.dict(), f, indent=2)
40+
logging.info(f"Proof generation complete: {proof_response}")
41+
42+
if __name__ == "__main__":
43+
try:
44+
run()
45+
except Exception as e:
46+
logging.error(f"Error during proof generation: {e}")
47+
traceback.print_exc()
48+
sys.exit(1)

my_proof/checks.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import json
2+
from typing import List, Dict, Any
3+
from openai import OpenAI
4+
5+
class SwipeValidation:
6+
def __init__(self):
7+
self.client = OpenAI(api_key="")#needs to be in env
8+
9+
def _verify_image_content(self, image_url: str, expected_object: str) -> bool:
10+
try:
11+
# Create the prompt for GPT-4 Vision
12+
prompt = f"Is there a {expected_object.lower()} in this image? Please answer with just 'yes' or 'no'."
13+
14+
response = self.client.chat.completions.create(
15+
model="gpt-4o",
16+
messages=[
17+
{
18+
"role": "user",
19+
"content": [
20+
{"type": "text", "text": prompt},
21+
{"type": "image_url", "image_url": {"url": image_url}}
22+
]
23+
}
24+
],
25+
max_tokens=10
26+
)
27+
28+
# Get the response and normalize it
29+
ai_response = response.choices[0].message.content.lower().strip()
30+
return 'yes' in ai_response
31+
32+
except Exception as e:
33+
print(f"Error processing image {image_url}: {str(e)}")
34+
return False
35+
36+
def validate(self, data: List[Dict[str, Any]]) -> float:
37+
if not data:
38+
return 0.0
39+
40+
correct_validations = 0
41+
total_validations = len(data)
42+
43+
for item in data:
44+
# Get the image URL and expected object from the data
45+
image_url = item['imgUrl']
46+
expected_object = item['imgText']
47+
user_response = bool(item['userResponse'])
48+
49+
# Verify with GPT-4 Vision
50+
ai_sees_object = self._verify_image_content(image_url, expected_object)
51+
52+
# Compare AI's response with user's response
53+
if ai_sees_object == user_response:
54+
correct_validations += 1
55+
56+
# Calculate and return the accuracy score (0.0 to 1.0)
57+
return correct_validations / total_validations
58+
59+
60+
if __name__ == "__main__":
61+
62+
with open("Swipes.json", "r") as f:
63+
data = json.load(f)
64+
65+
validator = SwipeValidation()
66+
results = validator.validate(data)
67+
print(f"Validation accuracy: {results:.2%}")
68+

my_proof/models/proof_response.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from typing import Dict, Optional, Any
2+
3+
from pydantic import BaseModel
4+
5+
6+
class ProofResponse(BaseModel):
7+
dlp_id: int
8+
valid: bool = False
9+
score: float = 0.0
10+
uniqueness: float = 0.0
11+
quality: float = 0.0
12+
ownership: float = 1.0
13+
authenticity: float = 1.0
14+
attributes: Dict[str, Any] = {}

0 commit comments

Comments
 (0)