185 lines
5.7 KiB
Go
185 lines
5.7 KiB
Go
![]() |
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"math/big"
|
||
|
"net/http"
|
||
|
"os"
|
||
|
|
||
|
"4vif5i.gitea.cloud/numenor-labs/discourse/backend/blockchain"
|
||
|
"4vif5i.gitea.cloud/numenor-labs/discourse/backend/feedback"
|
||
|
"4vif5i.gitea.cloud/numenor-labs/discourse/backend/identity"
|
||
|
"4vif5i.gitea.cloud/numenor-labs/discourse/backend/ipfs"
|
||
|
"4vif5i.gitea.cloud/numenor-labs/discourse/backend/moderation"
|
||
|
"4vif5i.gitea.cloud/numenor-labs/discourse/backend/perspective"
|
||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||
|
"github.com/ethereum/go-ethereum/common"
|
||
|
"github.com/ethereum/go-ethereum/crypto"
|
||
|
"github.com/ethereum/go-ethereum/ethclient"
|
||
|
"github.com/gin-gonic/gin"
|
||
|
"github.com/go-redis/redis/v8"
|
||
|
"gorm.io/driver/postgres"
|
||
|
"gorm.io/gorm"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
rpcURL = os.Getenv("RPC_URL")
|
||
|
contractAddress = os.Getenv("CONTRACT_ADDRESS")
|
||
|
privateKey = os.Getenv("PRIVATE_KEY")
|
||
|
redisAddr = getEnv("REDIS_ADDR", "localhost:6379")
|
||
|
redisPassword = getEnv("REDIS_PASSWORD", "")
|
||
|
redisDB = 0
|
||
|
dbDSN = getEnv("DATABASE_URL", "postgres://postgres:postgres@localhost:5432/voxpop?sslmode=disable")
|
||
|
)
|
||
|
|
||
|
// getEnv gets an environment variable or returns a default value
|
||
|
func getEnv(key, defaultValue string) string {
|
||
|
value := os.Getenv(key)
|
||
|
if value == "" {
|
||
|
return defaultValue
|
||
|
}
|
||
|
return value
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
// Connect to Sepolia
|
||
|
client, err := ethclient.Dial(rpcURL)
|
||
|
if err != nil {
|
||
|
log.Fatalf("Failed to connect to Ethereum client: %v", err)
|
||
|
}
|
||
|
|
||
|
// Connect to Redis
|
||
|
redisClient := redis.NewClient(&redis.Options{
|
||
|
Addr: redisAddr,
|
||
|
Password: redisPassword,
|
||
|
DB: redisDB,
|
||
|
})
|
||
|
|
||
|
// Connect to PostgreSQL
|
||
|
db, err := gorm.Open(postgres.Open(dbDSN), &gorm.Config{})
|
||
|
if err != nil {
|
||
|
log.Fatalf("Failed to connect to database: %v", err)
|
||
|
}
|
||
|
log.Println("Connected to PostgreSQL database")
|
||
|
|
||
|
// Set up HTTP server
|
||
|
router := gin.Default()
|
||
|
|
||
|
// Initialize the verification handler
|
||
|
verificationHandler := identity.NewVerificationHandler()
|
||
|
|
||
|
// Register the verification routes
|
||
|
verificationHandler.RegisterRoutes(router)
|
||
|
|
||
|
// Initialize the IPFS service (or use mock for development)
|
||
|
var ipfsService perspective.IPFSServiceInterface
|
||
|
pinataProd := os.Getenv("PINATA_PRODUCTION")
|
||
|
if pinataProd == "true" {
|
||
|
ipfsServiceReal, err := ipfs.NewIPFSService()
|
||
|
if err != nil {
|
||
|
log.Printf("Warning: Failed to initialize Pinata IPFS service: %v", err)
|
||
|
log.Println("Falling back to mock IPFS service")
|
||
|
ipfsService = ipfs.NewMockIPFSService()
|
||
|
} else {
|
||
|
ipfsService = ipfsServiceReal
|
||
|
log.Println("Initialized Pinata IPFS service")
|
||
|
}
|
||
|
} else {
|
||
|
ipfsService = ipfs.NewMockIPFSService()
|
||
|
log.Println("Using mock IPFS service")
|
||
|
}
|
||
|
|
||
|
// Initialize the perspective service and handler
|
||
|
perspectiveService := perspective.NewPerspectiveService(redisClient, db, ipfsService)
|
||
|
perspectiveHandler := perspective.NewPerspectiveHandler(perspectiveService)
|
||
|
|
||
|
// Register the perspective routes
|
||
|
perspectiveHandler.RegisterRoutes(router)
|
||
|
|
||
|
// Initialize the moderation service and handler
|
||
|
moderationService := moderation.NewModerationService(db)
|
||
|
moderationHandler := moderation.NewModerationHandler(moderationService)
|
||
|
|
||
|
// Register the moderation routes
|
||
|
moderationHandler.RegisterRoutes(router)
|
||
|
|
||
|
// Initialize the blockchain service and handler
|
||
|
blockchainService, err := blockchain.NewBlockchainService()
|
||
|
if err != nil {
|
||
|
log.Fatalf("Failed to initialize blockchain service: %v", err)
|
||
|
}
|
||
|
defer blockchainService.Close()
|
||
|
|
||
|
blockchainHandler := blockchain.NewHandler(blockchainService)
|
||
|
|
||
|
// Register the blockchain routes
|
||
|
blockchainHandler.RegisterRoutes(router)
|
||
|
|
||
|
// Existing feedback submission endpoint
|
||
|
router.OPTIONS(
|
||
|
"/submit-feedback", func(c *gin.Context) {
|
||
|
c.Header("Access-Control-Allow-Origin", "*")
|
||
|
c.Header("Access-Control-Allow-Methods", "POST, OPTIONS")
|
||
|
c.Header("Access-Control-Allow-Headers", "Content-Type")
|
||
|
c.Status(http.StatusOK)
|
||
|
},
|
||
|
)
|
||
|
router.POST(
|
||
|
"/submit-feedback", func(c *gin.Context) {
|
||
|
c.Header("Access-Control-Allow-Origin", "*")
|
||
|
c.Header("Access-Control-Allow-Methods", "POST, OPTIONS")
|
||
|
c.Header("Access-Control-Allow-Headers", "Content-Type")
|
||
|
var request struct {
|
||
|
Proof string `json:"proof"`
|
||
|
Feedback string `json:"feedback"`
|
||
|
}
|
||
|
if err := c.BindJSON(&request); err != nil {
|
||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Mocked ZKP verification
|
||
|
if request.Proof != "valid_proof" {
|
||
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid proof"})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
privateKeyECDSA, err := crypto.HexToECDSA(privateKey)
|
||
|
if err != nil {
|
||
|
fmt.Println("Failed to parse private key:", err)
|
||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to parse private key"})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Create the transactor (chain ID 11155111 is for Sepolia testnet, adjust as needed)
|
||
|
auth, err := bind.NewKeyedTransactorWithChainID(privateKeyECDSA, big.NewInt(11155111))
|
||
|
if err != nil {
|
||
|
log.Fatalf("Failed to create transactor: %v", err)
|
||
|
}
|
||
|
|
||
|
// Instantiate the contract
|
||
|
contract, err := feedback.NewFeedback(common.HexToAddress(contractAddress), client)
|
||
|
if err != nil {
|
||
|
fmt.Println("Failed to instantiate contract:", err)
|
||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to instantiate contract"})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Submit feedback to blockchain
|
||
|
tx, err := contract.SubmitFeedback(auth, request.Feedback)
|
||
|
if err != nil {
|
||
|
fmt.Println("Failed to submit feedback:", err)
|
||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to submit feedback"})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
fmt.Println("Submitted feedback:", tx.Hash().Hex())
|
||
|
c.JSON(http.StatusOK, gin.H{"transaction": tx.Hash().Hex()})
|
||
|
},
|
||
|
)
|
||
|
|
||
|
log.Println("Server running on :3000")
|
||
|
router.Run(":3000")
|
||
|
}
|