├── .gitignore ├── README.md ├── .github └── ISSUE_TEMPLATE │ ├── custom.md │ ├── feature_request.md │ └── bug_report.md ├── tests ├── unit │ ├── pi_unit_test_test.go │ └── pi_unit_test.go └── integration │ ├── pi_integration_test_test.go │ └── pi_integration_test.go ├── main.go ├── utils ├── pi_utils_test.go └── pi_utils.go ├── sharding ├── utils │ ├── sharding_utils.go │ └── sharding_utils_test.go └── mechanism │ ├── pi_sharding.go │ └── pi_sharding_test.go ├── consensus ├── utils │ ├── consensus_utils.go │ └── consensus_utils_test.go └── algorithm │ ├── pi_consensus.go │ └── pi_consensus_test.go ├── blockchain ├── pi_network │ ├── utils │ │ ├── pi_utils.go │ │ └── pi_utils_test.go │ ├── node │ │ ├── pi_node.go │ │ └── pi_node_test.go │ └── protocol │ │ ├── pi_protocol_test.go │ │ └── pi_protocol.go ├── cosmos │ ├── protocol │ │ ├── cosmos_protocol_test.go │ │ └── cosmos_protocol.go │ ├── utils │ │ ├── cosmos_utils.go │ │ └── cosmos_utils_test.go │ └── node │ │ ├── cosmos_node.go │ │ └── cosmos_node_test.go └── polkadot │ ├── utils │ ├── polkadot_utils.go │ └── polkadot_utils_test.go │ ├── node │ ├── polkadot_node.go │ └── polkadot_node_test.go │ └── protocol │ ├── polkadot_protocol_tests.go │ └── polkadot_protocol.go ├── interoperability ├── utils │ ├── interoperability_utils.go │ └── interoperability_utils_test.go └── protocol │ ├── pi_interoperability.go │ └── pi_interoperability_test.go ├── crypto ├── encryption │ ├── pi_encryption.go │ └── pi_encryption_test.go ├── decryption │ ├── pi_decryption.go │ └── pi_decryption_test.go └── utils │ ├── crypto_utils.go │ └── crypto_utils_test.go ├── network ├── utils │ ├── network_utils.go │ └── network_utils_test.go ├── protocol │ ├── pi_protocol.go │ └── pi_protocol_test.go └── node │ ├── pi_node.go │ └── pi_node_test.go └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | # Object file 2 | *.o 3 | 4 | # Ada Library Information 5 | *.ali 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nexapi 2 | A decentralized, sharded, and interoperable network protocol for the Pi Network, connecting it to other blockchain networks and enabling a vast, interconnected ecosystem. 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /tests/unit/pi_unit_test_test.go: -------------------------------------------------------------------------------- 1 | package unit 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestApproximatePI(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | numPoints int 13 | expectedPI float64 14 | }{ 15 | {"Small", 100, 3.14}, 16 | {"Medium", 1000, 3.141}, 17 | {"Large", 10000, 3.1415}, 18 | } 19 | 20 | for _, tt := range tests { 21 | t.Run(tt.name, func(t *testing.T) { 22 | actualPI := approximatePI(tt.numPoints) 23 | assert.InDelta(t, tt.expectedPI, actualPI, 0.01) 24 | }) 25 | } 26 | } 27 | 28 | func BenchmarkApproximatePI(b *testing.B) { 29 | for i := 0; i < b.N; i++ { 30 | approximatePI(10000) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/integration/pi_integration_test_test.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestCalculatePI(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | numPoints int 13 | expectedPI float64 14 | }{ 15 | {"Small", 100, 3.14}, 16 | {"Medium", 1000, 3.141}, 17 | {"Large", 10000, 3.1415}, 18 | } 19 | 20 | for _, tt := range tests { 21 | t.Run(tt.name, func(t *testing.T) { 22 | pi, err := CalculatePI(context.Background(), tt.numPoints) 23 | assert.NoError(t, err) 24 | 25 | assert.InDelta(t, tt.expectedPI, pi, 0.01) 26 | }) 27 | } 28 | } 29 | 30 | func BenchmarkCalculatePI(b *testing.B) { 31 | for i := 0; i < b.N; i++ { 32 | _, err := CalculatePI(context.Background(), 10000) 33 | if err!= nil { 34 | b.Errorf("Expected CalculatePI to succeed, but got error: %s", err) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /tests/unit/pi_unit_test.go: -------------------------------------------------------------------------------- 1 | package unit 2 | 3 | import ( 4 | "math" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestPIConstants(t *testing.T) { 11 | assert.Equal(t, math.Pi, piConstant, "piConstant should be equal to math.Pi") 12 | } 13 | 14 | func TestPIApproximation(t *testing.T) { 15 | tests := []struct { 16 | name string 17 | numPoints int 18 | expectedPI float64 19 | }{ 20 | {"Small", 100, 3.14}, 21 | {"Medium", 1000, 3.141}, 22 | {"Large", 10000, 3.1415}, 23 | } 24 | 25 | for _, tt := range tests { 26 | t.Run(tt.name, func(t *testing.T) { 27 | actualPI := approximatePI(tt.numPoints) 28 | assert.InDelta(t, tt.expectedPI, actualPI, 0.01) 29 | }) 30 | } 31 | } 32 | 33 | func BenchmarkPIApproximation(b *testing.B) { 34 | for i := 0; i < b.N; i++ { 35 | approximatePI(10000) 36 | } 37 | } 38 | 39 | func approximatePI(numPoints int) float64 { 40 | var sum float64 41 | for i := 0; i < numPoints; i++ { 42 | x := float64(i) / float64(numPoints-1) 43 | y := 4 * (1 - x*x) 44 | sum += y 45 | } 46 | return sum / float64(numPoints) 47 | } 48 | 49 | const piConstant = 3.14159265359 50 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | "math" 8 | "time" 9 | 10 | "github.com/spf13/viper" 11 | "golang.org/x/exp/rand" 12 | 13 | "pi/utils" 14 | ) 15 | 16 | var ( 17 | configFile = flag.String("config", "config.yaml", "Path to the configuration file") 18 | numPoints = flag.Int("num-points", 10000, "Number of points to use for PI calculation") 19 | numWorkers = flag.Int("num-workers", 4, "Number of workers to use for parallel PI calculation") 20 | ) 21 | 22 | func main() { 23 | flag.Parse() 24 | 25 | // Load configuration from file 26 | viper.SetConfigFile(*configFile) 27 | err := viper.ReadInConfig() 28 | if err!= nil { 29 | log.Fatal(err) 30 | } 31 | 32 | // Initialize random number generator 33 | rand.Seed(time.Now().UnixNano()) 34 | 35 | // Calculate PI using the Monte Carlo method 36 | startTime := time.Now() 37 | pi := utils.CalculatePIParallel(*numPoints, *numWorkers) 38 | elapsedTime := time.Since(startTime) 39 | 40 | fmt.Printf("PI: %.6f\n", pi) 41 | fmt.Printf("Error: %.6f\n", math.Abs(pi-math.Pi)) 42 | fmt.Printf("Time: %v\n", elapsedTime) 43 | 44 | // Print configuration 45 | fmt.Println("Configuration:") 46 | fmt.Println(" Num points:", *numPoints) 47 | fmt.Println(" Num workers:", *numWorkers) 48 | fmt.Println(" Config file:", *configFile) 49 | } 50 | -------------------------------------------------------------------------------- /utils/pi_utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestRandomPoint(t *testing.T) { 10 | x, y := RandomPoint() 11 | assert.True(t, x >= -1 && x <= 1) 12 | assert.True(t, y >= -1 && y <= 1) 13 | } 14 | 15 | func TestIsPointInCircle(t *testing.T) { 16 | tests := []struct { 17 | x, y float64 18 | want bool 19 | }{ 20 | {0, 0, true}, 21 | {1, 0, true}, 22 | {0, 1, true}, 23 | {-1, 0, true}, 24 | {0, -1, true}, 25 | {2, 0, false}, 26 | {0, 2, false}, 27 | } 28 | 29 | for _, tt := range tests { 30 | got := IsPointInCircle(tt.x, tt.y) 31 | assert.Equal(t, tt.want, got) 32 | } 33 | } 34 | 35 | func TestCalculatePI(t *testing.T) { 36 | tests := []struct { 37 | numPoints int 38 | want float64 39 | }{ 40 | {100, 3.14}, 41 | {1000, 3.141}, 42 | {10000, 3.1415}, 43 | } 44 | 45 | for _, tt := range tests { 46 | got := CalculatePI(tt.numPoints) 47 | assert.InDelta(t, tt.want, got, 0.01) 48 | } 49 | } 50 | 51 | func TestCalculatePIParallel(t *testing.T) { 52 | tests := []struct { 53 | numPoints int 54 | numWorkers int 55 | want float64 56 | }{ 57 | {100, 2, 3.14}, 58 | {1000, 4, 3.141}, 59 | {10000, 8, 3.1415}, 60 | } 61 | 62 | for _, tt := range tests { 63 | got := CalculatePIParallel(tt.numPoints, tt.numWorkers) 64 | assert.InDelta(t, tt.want, got, 0.01) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /utils/pi_utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "math" 5 | "math/rand" 6 | "time" 7 | ) 8 | 9 | // PI represents the mathematical constant PI 10 | const PI = 3.14159265359 11 | 12 | // RandomPoint generates a random point within the unit circle 13 | func RandomPoint() (x, y float64) { 14 | rand.Seed(time.Now().UnixNano()) 15 | x = rand.Float64() * 2 - 1 16 | y = rand.Float64() * 2 - 1 17 | return 18 | } 19 | 20 | // IsPointInCircle checks if a point is within the unit circle 21 | func IsPointInCircle(x, y float64) bool { 22 | return x*x+y*y <= 1 23 | } 24 | 25 | // CalculatePI calculates an approximation of PI using the Monte Carlo method 26 | func CalculatePI(numPoints int) float64 { 27 | pointsInCircle := 0 28 | for i := 0; i < numPoints; i++ { 29 | x, y := RandomPoint() 30 | if IsPointInCircle(x, y) { 31 | pointsInCircle++ 32 | } 33 | } 34 | return 4 * float64(pointsInCircle) / float64(numPoints) 35 | } 36 | 37 | // CalculatePIParallel calculates an approximation of PI using the Monte Carlo method in parallel 38 | func CalculatePIParallel(numPoints int, numWorkers int) float64 { 39 | ch := make(chan int, numWorkers) 40 | for i := 0; i < numWorkers; i++ { 41 | go func() { 42 | pointsInCircle := 0 43 | for j := 0; j < numPoints/numWorkers; j++ { 44 | x, y := RandomPoint() 45 | if IsPointInCircle(x, y) { 46 | pointsInCircle++ 47 | } 48 | } 49 | ch <- pointsInCircle 50 | }() 51 | } 52 | 53 | pointsInCircle := 0 54 | for i := 0; i < numWorkers; i++ { 55 | pointsInCircle += <-ch 56 | } 57 | 58 | return 4 * float64(pointsInCircle) / float64(numPoints) 59 | } 60 | -------------------------------------------------------------------------------- /sharding/utils/sharding_utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto/sha256" 5 | "encoding/hex" 6 | "math/big" 7 | "strings" 8 | 9 | "github.com/ethereum/go-ethereum/common" 10 | ) 11 | 12 | const ( 13 | ShardIDSize = 32 14 | ) 15 | 16 | func GenerateShardID(data []byte) ([]byte, error) { 17 | hash := sha256.Sum256(data) 18 | return hash[:ShardIDSize], nil 19 | } 20 | 21 | func ShardIDToString(shardID []byte) string { 22 | return hex.EncodeToString(shardID) 23 | } 24 | 25 | func StringToShardID(shardIDStr string) ([]byte, error) { 26 | shardID, err := hex.DecodeString(shardIDStr) 27 | if err!= nil { 28 | return nil, err 29 | } 30 | if len(shardID)!= ShardIDSize { 31 | return nil, fmt.Errorf("invalid shard ID size") 32 | } 33 | return shardID, nil 34 | } 35 | 36 | func CalculateShardIndex(shardID []byte, shardCount int) (int, error) { 37 | if shardCount <= 0 { 38 | return 0, fmt.Errorf("shard count must be positive") 39 | } 40 | shardIndex := new(big.Int) 41 | shardIndex.SetBytes(shardID) 42 | shardIndex.Mod(shardIndex, big.NewInt(int64(shardCount))) 43 | return int(shardIndex.Int64()), nil 44 | } 45 | 46 | func SplitDataIntoShards(data []byte, shardSize int) [][]byte { 47 | shards := make([][]byte, 0) 48 | for len(data) > shardSize { 49 | shard := data[:shardSize] 50 | data = data[shardSize:] 51 | shards = append(shards, shard) 52 | } 53 | if len(data) > 0 { 54 | shards = append(shards, data) 55 | } 56 | return shards 57 | } 58 | 59 | func MergeShards(shards [][]byte) []byte { 60 | data := make([]byte, 0) 61 | for _, shard := range shards { 62 | data = append(data, shard...) 63 | } 64 | return data 65 | } 66 | -------------------------------------------------------------------------------- /consensus/utils/consensus_utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "crypto/rand" 6 | "crypto/sha256" 7 | "encoding/hex" 8 | "fmt" 9 | "math/big" 10 | ) 11 | 12 | // GeneratePrivateKey generates a new ECDSA private key 13 | func GeneratePrivateKey() (*ecdsa.PrivateKey, error) { 14 | return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 15 | } 16 | 17 | // GeneratePublicKey generates a new ECDSA public key from a private key 18 | func GeneratePublicKey(privateKey *ecdsa.PrivateKey) (*ecdsa.PublicKey, error) { 19 | return &privateKey.PublicKey, nil 20 | } 21 | 22 | // GenerateAddress generates a new address from a public key 23 | func GenerateAddress(publicKey *ecdsa.PublicKey) (string, error) { 24 | hash := sha256.Sum256(elliptic.Marshal(publicKey.X, publicKey.Y)) 25 | return fmt.Sprintf("0x%x", hash), nil 26 | } 27 | 28 | // Sign signs a message with a private key 29 | func Sign(privateKey *ecdsa.PrivateKey, message []byte) (string, error) { 30 | r, s, err := ecdsa.Sign(rand.Reader, privateKey, message) 31 | if err!= nil { 32 | return "", err 33 | } 34 | return fmt.Sprintf("%x%x", r, s), nil 35 | } 36 | 37 | // Verify verifies a signature with a public key 38 | func Verify(publicKey *ecdsa.PublicKey, message []byte, signature string) (bool, error) { 39 | r, s, err := hex.DecodeString(signature) 40 | if err!= nil { 41 | return false, err 42 | } 43 | return ecdsa.Verify(&publicKey, message, r, s), nil 44 | } 45 | 46 | // CalculateBlockHash calculates the hash of a block 47 | func CalculateBlockHash(block *types.Block) (string, error) { 48 | hash := sha256.Sum256([]byte(block.PreviousHash + block.Transactions[0].ID + fmt.Sprintf("%d", block.Timestamp))) 49 | return fmt.Sprintf("0x%x", hash), nil 50 | } 51 | -------------------------------------------------------------------------------- /blockchain/pi_network/utils/pi_utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "crypto/rand" 6 | "crypto/sha256" 7 | "encoding/hex" 8 | "fmt" 9 | "math/big" 10 | ) 11 | 12 | // GeneratePrivateKey generates a new ECDSA private key 13 | func GeneratePrivateKey() (*ecdsa.PrivateKey, error) { 14 | return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 15 | } 16 | 17 | // GeneratePublicKey generates a new ECDSA public key from a private key 18 | func GeneratePublicKey(privateKey *ecdsa.PrivateKey) (*ecdsa.PublicKey, error) { 19 | return &privateKey.PublicKey, nil 20 | } 21 | 22 | // GenerateAddress generates a new address from a public key 23 | func GenerateAddress(publicKey *ecdsa.PublicKey) (string, error) { 24 | pubBytes := elliptic.Marshal(publicKey, publicKey.X, publicKey.Y) 25 | hash := sha256.Sum256(pubBytes) 26 | address := hex.EncodeToString(hash[:]) 27 | return address, nil 28 | } 29 | 30 | // GenerateHash generates a new hash from a byte slice 31 | func GenerateHash(data []byte) (string, error) { 32 | hash := sha256.Sum256(data) 33 | return hex.EncodeToString(hash[:]), nil 34 | } 35 | 36 | // Sign signs a byte slice with a private key 37 | func Sign(privateKey *ecdsa.PrivateKey, data []byte) ([]byte, error) { 38 | r, s, err := ecdsa.Sign(rand.Reader, privateKey, data) 39 | if err != nil { 40 | return nil, err 41 | } 42 | signature := append(r.Bytes(), s.Bytes()...) 43 | return signature, nil 44 | } 45 | 46 | // Verify verifies a signature with a public key 47 | func Verify(publicKey *ecdsa.PublicKey, data []byte, signature []byte) (bool, error) { 48 | r := big.NewInt(0).SetBytes(signature[:len(signature)/2]) 49 | s := big.NewInt(0).SetBytes(signature[len(signature)/2:]) 50 | if ecdsa.Verify(publicKey, data, r, s) { 51 | return true, nil 52 | } 53 | return false, fmt.Errorf("invalid signature") 54 | } 55 | -------------------------------------------------------------------------------- /blockchain/cosmos/protocol/cosmos_protocol_test.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/ethereum/go-ethereum/accounts" 8 | "github.com/ethereum/go-ethereum/common" 9 | "github.com/ethereum/go-ethereum/core/types" 10 | ) 11 | 12 | func TestCosmosProtocol(t *testing.T) { 13 | // ... 14 | 15 | // Test getting balance 16 | address := common.HexToAddress("0x742d35Cc6634C0532925a3b844Bc454e4438f44e") 17 | balance, err := protocol.GetBalance(address) 18 | if err!= nil { 19 | t.Fatal(err) 20 | } 21 | fmt.Printf("Balance: %s\n", balance) 22 | 23 | // Test getting transaction count 24 | nonce, err := protocol.GetTransactionCount(address) 25 | if err!= nil { 26 | t.Fatal(err) 27 | } 28 | fmt.Printf("Transaction count: %d\n", nonce) 29 | 30 | // Test getting block by number 31 | block, err := protocol.GetBlockByNumber(12345) 32 | if err!= nil { 33 | t.Fatal(err) 34 | } 35 | fmt.Printf("Block: %v\n", block) 36 | 37 | // Test getting block by hash 38 | hash := common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef") 39 | block, err = protocol.GetBlockByHash(hash) 40 | if err!= nil { 41 | t.Fatal(err) 42 | } 43 | fmt.Printf("Block: %v\n", block) 44 | 45 | // Test getting transaction by hash 46 | txHash := common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef") 47 | tx, _, err := protocol.GetTransactionByHash(txHash) 48 | if err!= nil { 49 | t.Fatal(err) 50 | } 51 | fmt.Printf("Transaction: %v\n", tx) 52 | 53 | // Test getting transaction receipt 54 | receipt, err := protocol.GetTransactionReceipt(txHash) 55 | if err!= nil { 56 | t.Fatal(err) 57 | } 58 | fmt.Printf("Receipt: %v\n", receipt) 59 | } 60 | -------------------------------------------------------------------------------- /tests/integration/pi_integration_test.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "math" 7 | "testing" 8 | "time" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | const ( 15 | piCalculationTimeout = 10 * time.Second 16 | ) 17 | 18 | func TestPIIntegration(t *testing.T) { 19 | tests := []struct { 20 | name string 21 | numPoints int 22 | expectedPI float64 23 | }{ 24 | {"Small", 100, 3.14}, 25 | {"Medium", 1000, 3.141}, 26 | {"Large", 10000, 3.1415}, 27 | } 28 | 29 | for _, tt := range tests { 30 | t.Run(tt.name, func(t *testing.T) { 31 | ctx, cancel := context.WithTimeout(context.Background(), piCalculationTimeout) 32 | defer cancel() 33 | 34 | actualPI, err := CalculatePI(ctx, tt.numPoints) 35 | require.NoError(t, err) 36 | 37 | assert.InDelta(t, tt.expectedPI, actualPI, 0.01) 38 | }) 39 | } 40 | } 41 | 42 | func BenchmarkPIIntegration(b *testing.B) { 43 | for i := 0; i < b.N; i++ { 44 | ctx, cancel := context.WithTimeout(context.Background(), piCalculationTimeout) 45 | defer cancel() 46 | 47 | _, err := CalculatePI(ctx, 10000) 48 | if err!= nil { 49 | b.Errorf("Expected CalculatePI to succeed, but got error: %s", err) 50 | } 51 | } 52 | } 53 | 54 | func CalculatePI(ctx context.Context, numPoints int) (float64, error) { 55 | ch := make(chan float64, numPoints) 56 | errCh := make(chan error, 1) 57 | 58 | go func() { 59 | defer close(ch) 60 | defer close(errCh) 61 | 62 | for i := 0; i < numPoints; i++ { 63 | x := float64(i) / float64(numPoints-1) 64 | y := 4 * (1 - x*x) 65 | ch <- y 66 | } 67 | }() 68 | 69 | go func() { 70 | defer close(errCh) 71 | 72 | var sum float64 73 | for y := range ch { 74 | sum += y 75 | } 76 | 77 | pi := sum / float64(numPoints) 78 | errCh <- nil 79 | }() 80 | 81 | select { 82 | case <-ctx.Done(): 83 | return 0, ctx.Err() 84 | case err := <-errCh: 85 | return 0, err 86 | case pi := <-ch: 87 | return pi, nil 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /sharding/mechanism/pi_sharding.go: -------------------------------------------------------------------------------- 1 | package mechanism 2 | 3 | import ( 4 | "math" 5 | "math/big" 6 | 7 | "github.com/consensys/gurvy" 8 | ) 9 | 10 | const ( 11 | DefaultShardCount = 1024 12 | DefaultShardSize = 100 13 | ) 14 | 15 | func ShardPi(ctx context.Context, pi *big.Float, shardCount int, shardSize int) ([]*big.Float, error) { 16 | if shardCount <= 0 { 17 | shardCount = DefaultShardCount 18 | } 19 | if shardSize <= 0 { 20 | shardSize = DefaultShardSize 21 | } 22 | if shardCount%shardSize != 0 { 23 | return nil, fmt.Errorf("shardCount must be a multiple of shardSize") 24 | } 25 | shardCount = shardCount / shardSize 26 | shards := make([]*big.Float, shardCount) 27 | for i := 0; i < shardCount; i++ { 28 | shards[i] = new(big.Float) 29 | } 30 | cur := new(big.Float) 31 | cur.SetPrec(64) 32 | cur.SetString("0") 33 | for i := 0; i < shardCount; i++ { 34 | cur.Add(cur, pi) 35 | cur.Quo(cur, big.NewFloat(float64(shardCount))) 36 | shards[i].Add(shards[i], cur) 37 | cur.Mul(cur, big.NewFloat(float64(shardSize))) 38 | } 39 | return shards, nil 40 | } 41 | 42 | func UnshardPi(ctx context.Context, shards []*big.Float) (*big.Float, error) { 43 | if len(shards) <= 0 { 44 | return nil, fmt.Errorf("shards cannot be empty") 45 | } 46 | total := new(big.Float) 47 | for _, shard := range shards { 48 | total.Add(total, shard) 49 | } 50 | return total, nil 51 | } 52 | 53 | func VerifyPiShard(ctx context.Context, shard *big.Float, shardIndex int, shardSize int) error { 54 | if shardIndex < 0 || shardIndex >= len(shards) { 55 | return fmt.Errorf("shardIndex out of range") 56 | } 57 | if shardSize <= 0 { 58 | return fmt.Errorf("shardSize must be positive") 59 | } 60 | if shard.Cmp(new(big.Float).SetInt64(0)) == 0 { 61 | return fmt.Errorf("shard cannot be zero") 62 | } 63 | cur := new(big.Float) 64 | cur.SetPrec(64) 65 | cur.SetInt64(int64(shardIndex) * int64(shardSize)) 66 | cur.Quo(cur, big.NewFloat(float64(len(shards)))) 67 | cur.Mul(cur, big.NewFloat(math.Pi)) 68 | if cur.Cmp(shard) != 0 { 69 | return fmt.Errorf("shard verification failed") 70 | } 71 | return nil 72 | } 73 | -------------------------------------------------------------------------------- /sharding/mechanism/pi_sharding_test.go: -------------------------------------------------------------------------------- 1 | package mechanism 2 | 3 | import ( 4 | "math/big" 5 | "testing" 6 | ) 7 | 8 | func TestShardPi(t *testing.T) { 9 | pi := big.NewFloat(math.Pi) 10 | shards, err := ShardPi(context.Background(), pi, 1024, 100) 11 | if err!= nil { 12 | t.Errorf("Expected ShardPi to succeed, but got error: %s", err) 13 | } 14 | if len(shards) != 10 { 15 | t.Errorf("Expected 10 shards, but got %d", len(shards)) 16 | } 17 | } 18 | 19 | func TestUnshardPi(t *testing.T) { 20 | pi := big.NewFloat(math.Pi) 21 | shards, err := ShardPi(context.Background(), pi, 1024, 100) 22 | if err!= nil { 23 | t.Errorf("Expected ShardPi to succeed, but got error: %s", err) 24 | } 25 | unshardedPi, err := UnshardPi(context.Background(), shards) 26 | if err!= nil { 27 | t.Errorf("Expected UnshardPi to succeed, but got error: %s", err) 28 | } 29 | if unshardedPi.Cmp(pi)!= 0 { 30 | t.Errorf("Expected unsharded Pi to match original Pi") 31 | } 32 | } 33 | 34 | func TestVerifyPiShard(t *testing.T) { 35 | pi := big.NewFloat(math.Pi) 36 | shards, err := ShardPi(context.Background(), pi, 1024, 100) 37 | if err!= nil { 38 | t.Errorf("Expected ShardPi to succeed, but got error: %s", err) 39 | } 40 | for i, shard := range shards { 41 | err := VerifyPiShard(context.Background(), shard, i, 100) 42 | if err!= nil { 43 | t.Errorf("Expected VerifyPiShard to succeed, but got error: %s", err) 44 | } 45 | } 46 | } 47 | 48 | func BenchmarkShardPi(b *testing.B) { 49 | pi := big.NewFloat(math.Pi) 50 | for i := 0; i < b.N; i++ { 51 | _, err := ShardPi(context.Background(), pi, 1024, 100) 52 | if err!= nil { 53 | b.Errorf("Expected ShardPi to succeed, but got error: %s", err) 54 | } 55 | } 56 | } 57 | 58 | func BenchmarkUnshardPi(b *testing.B) { 59 | pi := big.NewFloat(math.Pi) 60 | shards, err := ShardPi(context.Background(), pi, 1024, 100) 61 | if err!= nil { 62 | b.Errorf("Expected ShardPi to succeed, but got error: %s", err) 63 | } 64 | for i := 0; i < b.N; i++ { 65 | _, err := UnshardPi(context.Background(), shards) 66 | if err!= nil { 67 | b.Errorf("Expected UnshardPi to succeed, but got error: %s", err) 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /interoperability/utils/interoperability_utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha256" 6 | "encoding/base64" 7 | "encoding/json" 8 | "errors" 9 | "fmt" 10 | "math/rand" 11 | "net/http" 12 | "net/url" 13 | "strings" 14 | "time" 15 | ) 16 | 17 | // GenerateRandomString generates a random string of a given length 18 | func GenerateRandomString(length int) string { 19 | b := make([]byte, length) 20 | rand.Read(b) 21 | return fmt.Sprintf("%x", b) 22 | } 23 | 24 | // ComputeHMAC computes the HMAC of a given message using a secret key 25 | func ComputeHMAC(message []byte, secretKey []byte) ([]byte, error) { 26 | h := hmac.New(sha256.New, secretKey) 27 | _, err := h.Write(message) 28 | if err!= nil { 29 | return nil, err 30 | } 31 | return h.Sum(nil), nil 32 | } 33 | 34 | // Base64Encode encodes a byte slice to a base64-encoded string 35 | func Base64Encode(data []byte) string { 36 | return base64.StdEncoding.EncodeToString(data) 37 | } 38 | 39 | // Base64Decode decodes a base64-encoded string to a byte slice 40 | func Base64Decode(encoded string) ([]byte, error) { 41 | return base64.StdEncoding.DecodeString(encoded) 42 | } 43 | 44 | // JSONMarshal marshals a struct to a JSON byte slice 45 | func JSONMarshal(v interface{}) ([]byte, error) { 46 | return json.Marshal(v) 47 | } 48 | 49 | // JSONUnmarshal unmarshals a JSON byte slice to a struct 50 | func JSONUnmarshal(data []byte, v interface{}) error { 51 | return json.Unmarshal(data, v) 52 | } 53 | 54 | // HTTPGet sends an HTTP GET request to a given URL 55 | func HTTPGet(url string) ([]byte, error) { 56 | resp, err := http.Get(url) 57 | if err!= nil { 58 | return nil, err 59 | } 60 | defer resp.Body.Close() 61 | return ioutil.ReadAll(resp.Body) 62 | } 63 | 64 | // URLParse parses a URL string into a URL struct 65 | func URLParse(url string) (*url.URL, error) { 66 | return url.Parse(url) 67 | } 68 | 69 | // URLQueryEscape escapes a URL query string 70 | func URLQueryEscape(query string) string { 71 | return url.QueryEscape(query) 72 | } 73 | 74 | // ErrorString returns a string representation of an error 75 | func ErrorString(err error) string { 76 | if err == nil { 77 | return "" 78 | } 79 | return err.Error() 80 | } 81 | 82 | // IsError returns true if the error is not nil 83 | func IsError(err error) bool { 84 | return err!= nil 85 | } 86 | -------------------------------------------------------------------------------- /blockchain/pi_network/utils/pi_utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGeneratePrivateKey(t *testing.T) { 8 | privateKey, err := GeneratePrivateKey() 9 | if err != nil { 10 | t.Errorf("Expected private key to be generated, but got error: %s", err) 11 | } 12 | 13 | if privateKey == nil { 14 | t.Errorf("Expected private key to be generated, but got nil") 15 | } 16 | } 17 | 18 | func TestGeneratePublicKey(t *testing.T) { 19 | privateKey, err := GeneratePrivateKey() 20 | if err != nil { 21 | t.Fatal(err) 22 | } 23 | 24 | publicKey, err := GeneratePublicKey(privateKey) 25 | if err != nil { 26 | t.Errorf("Expected public key to be generated, but got error: %s", err) 27 | } 28 | 29 | if publicKey == nil { 30 | t.Errorf("Expected public key to be generated, but got nil") 31 | } 32 | } 33 | 34 | func TestGenerateAddress(t *testing.T) { 35 | privateKey, err := GeneratePrivateKey() 36 | if err != nil { 37 | t.Fatal(err) 38 | } 39 | 40 | publicKey, err := GeneratePublicKey(privateKey) 41 | if err != nil { 42 | t.Fatal(err) 43 | } 44 | 45 | address, err := GenerateAddress(publicKey) 46 | if err != nil { 47 | t.Errorf("Expected address to be generated, but got error: %s", err) 48 | } 49 | 50 | if address == "" { 51 | t.Errorf("Expected address to be generated, but got empty string") 52 | } 53 | } 54 | 55 | func TestGenerateHash(t *testing.T) { 56 | data := []byte("hello world") 57 | hash, err := GenerateHash(data) 58 | if err != nil { 59 | t.Errorf("Expected hash to be generated, but got error: %s", err) 60 | } 61 | 62 | if hash == "" { 63 | t.Errorf("Expected hash to be generated, but got empty string") 64 | } 65 | } 66 | 67 | func TestSignAndVerify(t *testing.T) { 68 | privateKey, err := GeneratePrivateKey() 69 | if err != nil { 70 | t.Fatal(err) 71 | } 72 | 73 | publicKey, err := GeneratePublicKey(privateKey) 74 | if err != nil { 75 | t.Fatal(err) 76 | } 77 | 78 | data := []byte("hello world") 79 | signature, err := Sign(privateKey, data) 80 | if err != nil { 81 | t.Errorf("Expected signature to be generated, but got error: %s", err) 82 | } 83 | 84 | valid, err := Verify(publicKey, data, signature) 85 | if err != nil { 86 | t.Errorf("Expected signature to be verified, but got error: %s", err) 87 | } 88 | 89 | if !valid { 90 | t.Errorf("Expected signature to be valid, but got invalid") 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /crypto/encryption/pi_encryption.go: -------------------------------------------------------------------------------- 1 | package encryption 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/rand" 7 | "encoding/base64" 8 | "errors" 9 | "io" 10 | ) 11 | 12 | // PiEncryption is a struct that holds the encryption key and other parameters 13 | type PiEncryption struct { 14 | key []byte 15 | } 16 | 17 | // NewPiEncryption creates a new instance of PiEncryption 18 | func NewPiEncryption(key []byte) (*PiEncryption, error) { 19 | if len(key) != 32 { 20 | return nil, errors.New("key must be 32 bytes long") 21 | } 22 | return &PiEncryption{key: key}, nil 23 | } 24 | 25 | // Encrypt encrypts a plaintext message using AES-256-CBC 26 | func (pe *PiEncryption) Encrypt(plaintext []byte) ([]byte, error) { 27 | block, err := aes.NewCipher(pe.key) 28 | if err != nil { 29 | return nil, err 30 | } 31 | ciphertext := make([]byte, aes.BlockSize+len(plaintext)) 32 | iv := ciphertext[:aes.BlockSize] 33 | if _, err := io.ReadFull(rand.Reader, iv); err != nil { 34 | return nil, err 35 | } 36 | cfb := cipher.NewCFBEncrypter(block, iv) 37 | cfb.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) 38 | return ciphertext, nil 39 | } 40 | 41 | // Decrypt decrypts a ciphertext message using AES-256-CBC 42 | func (pe *PiEncryption) Decrypt(ciphertext []byte) ([]byte, error) { 43 | block, err := aes.NewCipher(pe.key) 44 | if err != nil { 45 | return nil, err 46 | } 47 | if len(ciphertext) < aes.BlockSize { 48 | return nil, errors.New("ciphertext too short") 49 | } 50 | iv := ciphertext[:aes.BlockSize] 51 | ciphertext = ciphertext[aes.BlockSize:] 52 | cfb := cipher.NewCFBDecrypter(block, iv) 53 | cfb.XORKeyStream(ciphertext, ciphertext) 54 | return ciphertext, nil 55 | } 56 | 57 | // EncryptBase64 encrypts a plaintext message and returns the result as a base64-encoded string 58 | func (pe *PiEncryption) EncryptBase64(plaintext []byte) (string, error) { 59 | ciphertext, err := pe.Encrypt(plaintext) 60 | if err != nil { 61 | return "", err 62 | } 63 | return base64.StdEncoding.EncodeToString(ciphertext), nil 64 | } 65 | 66 | // DecryptBase64 decrypts a base64-encoded ciphertext message and returns the result as a plaintext byte slice 67 | func (pe *PiEncryption) DecryptBase64(ciphertext string) ([]byte, error) { 68 | ciphertextBytes, err := base64.StdEncoding.DecodeString(ciphertext) 69 | if err != nil { 70 | return nil, err 71 | } 72 | return pe.Decrypt(ciphertextBytes) 73 | } 74 | -------------------------------------------------------------------------------- /crypto/decryption/pi_decryption.go: -------------------------------------------------------------------------------- 1 | package decryption 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/rand" 7 | "encoding/base64" 8 | "errors" 9 | "io" 10 | ) 11 | 12 | // PiDecryption is a struct that holds the decryption key and other parameters 13 | type PiDecryption struct { 14 | key []byte 15 | } 16 | 17 | // NewPiDecryption creates a new instance of PiDecryption 18 | func NewPiDecryption(key []byte) (*PiDecryption, error) { 19 | if len(key) != 32 { 20 | return nil, errors.New("key must be 32 bytes long") 21 | } 22 | return &PiDecryption{key: key}, nil 23 | } 24 | 25 | // Decrypt decrypts a ciphertext message using AES-256-CBC 26 | func (pd *PiDecryption) Decrypt(ciphertext []byte) ([]byte, error) { 27 | block, err := aes.NewCipher(pd.key) 28 | if err != nil { 29 | return nil, err 30 | } 31 | if len(ciphertext) < aes.BlockSize { 32 | return nil, errors.New("ciphertext too short") 33 | } 34 | iv := ciphertext[:aes.BlockSize] 35 | ciphertext = ciphertext[aes.BlockSize:] 36 | cfb := cipher.NewCFBDecrypter(block, iv) 37 | cfb.XORKeyStream(ciphertext, ciphertext) 38 | return ciphertext, nil 39 | } 40 | 41 | // DecryptBase64 decrypts a base64-encoded ciphertext message and returns the result as a plaintext byte slice 42 | func (pd *PiDecryption) DecryptBase64(ciphertext string) ([]byte, error) { 43 | ciphertextBytes, err := base64.StdEncoding.DecodeString(ciphertext) 44 | if err != nil { 45 | return nil, err 46 | } 47 | return pd.Decrypt(ciphertextBytes) 48 | } 49 | 50 | // DecryptWithMAC decrypts a ciphertext message using AES-256-CBC and verifies the MAC (Message Authentication Code) 51 | func (pd *PiDecryption) DecryptWithMAC(ciphertext []byte, mac []byte) ([]byte, error) { 52 | block, err := aes.NewCipher(pd.key) 53 | if err != nil { 54 | return nil, err 55 | } 56 | if len(ciphertext) < aes.BlockSize { 57 | return nil, errors.New("ciphertext too short") 58 | } 59 | iv := ciphertext[:aes.BlockSize] 60 | ciphertext = ciphertext[aes.BlockSize:] 61 | cfb := cipher.NewCFBDecrypter(block, iv) 62 | cfb.XORKeyStream(ciphertext, ciphertext) 63 | expectedMAC := pd.calculateMAC(ciphertext) 64 | if !hmac.Equal(expectedMAC, mac) { 65 | return nil, errors.New("MAC verification failed") 66 | } 67 | return ciphertext, nil 68 | } 69 | 70 | func (pd *PiDecryption) calculateMAC(data []byte) []byte { 71 | mac := hmac.New(sha256.New, pd.key) 72 | mac.Write(data) 73 | return mac.Sum(nil) 74 | } 75 | -------------------------------------------------------------------------------- /network/utils/network_utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "crypto/tls" 6 | "fmt" 7 | "net" 8 | "time" 9 | 10 | "github.com/libp2p/go-libp2p-core/network" 11 | "github.com/libp2p/go-libp2p-core/peer" 12 | "github.com/multiformats/go-multibase" 13 | ) 14 | 15 | const ( 16 | DefaultDialTimeout = 10 * time.Second 17 | DefaultConnectTimeout = 30 * time.Second 18 | ) 19 | 20 | func DialContext(ctx context.Context, addr string) (net.Conn, error) { 21 | dialer := &net.Dialer{ 22 | Timeout: DefaultDialTimeout, 23 | } 24 | return dialer.DialContext(ctx, "tcp", addr) 25 | } 26 | 27 | func ConnectContext(ctx context.Context, addr string) (net.Conn, error) { 28 | conn, err := DialContext(ctx, addr) 29 | if err!= nil { 30 | return nil, err 31 | } 32 | err = conn.SetDeadline(time.Now().Add(DefaultConnectTimeout)) 33 | if err!= nil { 34 | return nil, err 35 | } 36 | return conn, nil 37 | } 38 | 39 | func NewTLSConfig(certFile, keyFile string) (*tls.Config, error) { 40 | cert, err := tls.LoadX509KeyPair(certFile, keyFile) 41 | if err!= nil { 42 | return nil, err 43 | } 44 | return &tls.Config{ 45 | Certificates: []tls.Certificate{cert}, 46 | }, nil 47 | } 48 | 49 | func NewLibp2pHost(ctx context.Context, privateKey *ecdsa.PrivateKey, listenAddr string) (*network.Host, error) { 50 | id, err := peer.IDFromPrivateKey(privateKey) 51 | if err!= nil { 52 | return nil, err 53 | } 54 | host, err := network.NewHost(ctx, id, listenAddr) 55 | if err!= nil { 56 | return nil, err 57 | } 58 | return host, nil 59 | } 60 | 61 | func GetFreePort() (int, error) { 62 | addr, err := net.ResolveTCPAddr("tcp", "localhost:0") 63 | if err!= nil { 64 | return 0, err 65 | } 66 | l, err := net.ListenTCP("tcp", addr) 67 | if err!= nil { 68 | return 0, err 69 | } 70 | defer l.Close() 71 | return l.Addr().(*net.TCPAddr).Port, nil 72 | } 73 | 74 | func GetExternalIP() (net.IP, error) { 75 | ifaces, err := net.Interfaces() 76 | if err!= nil { 77 | return nil, err 78 | } 79 | for _, iface := range ifaces { 80 | addrs, err := iface.Addrs() 81 | if err!= nil { 82 | return nil, err 83 | } 84 | for _, addr := range addrs { 85 | var ip net.IP 86 | switch v := addr.(type) { 87 | case *net.IPNet: 88 | ip = v.IP 89 | case *net.IPAddr: 90 | ip = v.IP 91 | } 92 | if ip!= nil &&!ip.IsLoopback() && ip.To4()!= nil { 93 | return ip, nil 94 | } 95 | } 96 | } 97 | return nil, errors.New("no external IP found") 98 | } 99 | -------------------------------------------------------------------------------- /network/utils/network_utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "net" 7 | "testing" 8 | "time" 9 | 10 | "github.com/libp2p/go-libp2p-core/network" 11 | "github.com/libp2p/go-libp2p-core/peer" 12 | ) 13 | 14 | func TestDialContext(t *testing.T) { 15 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 16 | defer cancel() 17 | conn, err := DialContext(ctx, "example.com:80") 18 | if err!= nil { 19 | t.Errorf("Expected DialContext to succeed, but got error: %s", err) 20 | } 21 | defer conn.Close() 22 | } 23 | 24 | func TestConnectContext(t *testing.T) { 25 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 26 | defer cancel() 27 | conn, err := ConnectContext(ctx, "example.com:80") 28 | if err!= nil { 29 | t.Errorf("Expected ConnectContext to succeed, but got error: %s", err) 30 | } 31 | defer conn.Close() 32 | } 33 | 34 | func TestNewTLSConfig(t *testing.T) { 35 | certFile := "testdata/cert.pem" 36 | keyFile := "testdata/key.pem" 37 | tlsConfig, err := NewTLSConfig(certFile, keyFile) 38 | if err!= nil { 39 | t.Errorf("Expected NewTLSConfig to succeed, but got error: %s", err) 40 | } 41 | if tlsConfig.Certificates[0].Leaf.Subject.CommonName!= "example.com" { 42 | t.Errorf("Expected certificate subject to be example.com, but got %s", tlsConfig.Certificates[0].Leaf.Subject.CommonName) 43 | } 44 | } 45 | 46 | func TestNewLibp2pHost(t *testing.T) { 47 | privateKey, _, err := GenerateKeyPair() 48 | if err!= nil { 49 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 50 | } 51 | listenAddr := "/ip4/0.0.0.0/tcp/0" 52 | host, err := NewLibp2pHost(context.Background(), privateKey, listenAddr) 53 | if err!= nil { 54 | t.Errorf("Expected NewLibp2pHost to succeed, but got error: %s", err) 55 | } 56 | defer host.Close() 57 | if host.ID().String()!= peer.IDFromPrivateKey(privateKey).String() { 58 | t.Errorf("Expected host ID to match private key ID") 59 | } 60 | } 61 | 62 | func TestGetFreePort(t *testing.T) { 63 | port, err := GetFreePort() 64 | if err!= nil { 65 | t.Errorf("Expected GetFreePort to succeed, but got error: %s", err) 66 | } 67 | if port <= 0 || port >= 65536 { 68 | t.Errorf("Expected port to be in range 1-65535, but got %d", port) 69 | } 70 | } 71 | 72 | func TestGetExternalIP(t *testing.T) { 73 | ip, err := GetExternalIP() 74 | if err!= nil { 75 | t.Errorf("Expected GetExternalIP to succeed, but got error: %s", err) 76 | } 77 | if ip== nil { 78 | t.Errorf("Expected external IP to be non-nil") 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /interoperability/protocol/pi_interoperability.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | 8 | "github.com/golang/protobuf/proto" 9 | "github.com/gorilla/websocket" 10 | ) 11 | 12 | // PIInteroperability represents the PI Interoperability protocol 13 | type PIInteroperability struct { 14 | conn *websocket.Conn 15 | } 16 | 17 | // NewPIInteroperability creates a new PI Interoperability instance 18 | func NewPIInteroperability(conn *websocket.Conn) *PIInteroperability { 19 | return &PIInteroperability{conn: conn} 20 | } 21 | 22 | // SendMessage sends a message to the PI Interoperability endpoint 23 | func (pi *PIInteroperability) SendMessage(message *PIMessage) error { 24 | data, err := json.Marshal(message) 25 | if err != nil { 26 | return err 27 | } 28 | return pi.conn.WriteMessage(websocket.TextMessage, data) 29 | } 30 | 31 | // ReceiveMessage receives a message from the PI Interoperability endpoint 32 | func (pi *PIInteroperability) ReceiveMessage() (*PIMessage, error) { 33 | _, data, err := pi.conn.ReadMessage() 34 | if err != nil { 35 | return nil, err 36 | } 37 | var message PIMessage 38 | err = json.Unmarshal(data, &message) 39 | return &message, err 40 | } 41 | 42 | // Close closes the PI Interoperability connection 43 | func (pi *PIInteroperability) Close() error { 44 | return pi.conn.Close() 45 | } 46 | 47 | // PIMessage represents a PI Interoperability message 48 | type PIMessage struct { 49 | Type string `json:"type"` 50 | Payload json.RawMessage `json:"payload"` 51 | } 52 | 53 | // UnmarshalPayload unmarshals the payload of a PI Interoperability message 54 | func (m *PIMessage) UnmarshalPayload(v interface{}) error { 55 | return json.Unmarshal(m.Payload, v) 56 | } 57 | 58 | // MarshalPayload marshals the payload of a PI Interoperability message 59 | func (m *PIMessage) MarshalPayload(v interface{}) error { 60 | data, err := json.Marshal(v) 61 | if err != nil { 62 | return err 63 | } 64 | m.Payload = data 65 | return nil 66 | } 67 | 68 | // PIProtoMessage represents a PI Interoperability protocol buffer message 69 | type PIProtoMessage struct { 70 | Type string `protobuf:"bytes,1,opt,name=type"` 71 | Payload []byte `protobuf:"bytes,2,opt,name=payload"` 72 | } 73 | 74 | // Marshal marshals a PI Interoperability protocol buffer message 75 | func (m *PIProtoMessage) Marshal() ([]byte, error) { 76 | return proto.Marshal(m) 77 | } 78 | 79 | // Unmarshal unmarshals a PI Interoperability protocol buffer message 80 | func (m *PIProtoMessage) Unmarshal(data []byte) error { 81 | return proto.Unmarshal(data, m) 82 | } 83 | -------------------------------------------------------------------------------- /crypto/encryption/pi_encryption_test.go: -------------------------------------------------------------------------------- 1 | package encryption 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestNewPiEncryption(t *testing.T) { 8 | key := make([]byte, 32) 9 | _, err := rand.Read(key) 10 | if err != nil { 11 | t.Fatal(err) 12 | } 13 | pe, err := NewPiEncryption(key) 14 | if err != nil { 15 | t.Errorf("Expected NewPiEncryption to succeed, but got error: %s", err) 16 | } 17 | if pe == nil { 18 | t.Errorf("Expected pe to be non-nil, but got nil") 19 | } 20 | } 21 | 22 | func TestEncryptDecrypt(t *testing.T) { 23 | key := make([]byte, 32) 24 | _, err := rand.Read(key) 25 | if err != nil { 26 | t.Fatal(err) 27 | } 28 | pe, err := NewPiEncryption(key) 29 | if err != nil { 30 | t.Fatal(err) 31 | } 32 | plaintext := []byte("hello world") 33 | ciphertext, err := pe.Encrypt(plaintext) 34 | if err != nil { 35 | t.Errorf("Expected Encrypt to succeed, but got error: %s", err) 36 | } 37 | decrypted, err := pe.Decrypt(ciphertext) 38 | if err != nil { 39 | t.Errorf("Expected Decrypt to succeed, but got error: %s", err) 40 | } 41 | if string(decrypted) != string(plaintext) { 42 | t.Errorf("Expected decrypted text to match original plaintext, but got %s", decrypted) 43 | } 44 | } 45 | 46 | func TestEncryptBase64DecryptBase64(t *testing.T) { 47 | key := make([]byte, 32) 48 | _, err := rand.Read(key) 49 | if err != nil { 50 | t.Fatal(err) 51 | } 52 | pe, err := NewPiEncryption(key) 53 | if err != nil { 54 | t.Fatal(err) 55 | } 56 | plaintext := []byte("hello world") 57 | encrypted, err := pe.EncryptBase64(plaintext) 58 | if err != nil { 59 | t.Errorf("Expected EncryptBase64 to succeed, but got error: %s", err) 60 | } 61 | decrypted, err := pe.DecryptBase64(encrypted) 62 | if err != nil { 63 | t.Errorf("Expected DecryptBase64 to succeed, but got error: %s", err) 64 | } 65 | if string(decrypted) != string(plaintext) { 66 | t.Errorf("Expected decrypted text to match original plaintext, but got %s", decrypted) 67 | } 68 | } 69 | 70 | func TestInvalidKeyLength(t *testing.T) { 71 | key := make([]byte, 16) 72 | _, err := NewPiEncryption(key) 73 | if err == nil { 74 | t.Errorf("Expected NewPiEncryption to fail with invalid key length, but got nil error") 75 | } 76 | } 77 | 78 | func TestInvalidCiphertext(t *testing.T) { 79 | key := make([]byte, 32) 80 | _, err := rand.Read(key) 81 | if err != nil { 82 | t.Fatal(err) 83 | } 84 | pe, err := NewPiEncryption(key) 85 | if err != nil { 86 | t.Fatal(err) 87 | } 88 | ciphertext := []byte("invalid ciphertext") 89 | _, err = pe.Decrypt(ciphertext) 90 | if err == nil { 91 | t.Errorf("Expected Decrypt to fail with invalid ciphertext, but got nil error") 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /blockchain/cosmos/utils/cosmos_utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "crypto/rand" 6 | "encoding/hex" 7 | "fmt" 8 | "math/big" 9 | "strings" 10 | 11 | "github.com/ethereum/go-ethereum/accounts" 12 | "github.com/ethereum/go-ethereum/common" 13 | "github.com/ethereum/go-ethereum/crypto" 14 | ) 15 | 16 | // GeneratePrivateKey generates a new private key 17 | func GeneratePrivateKey() (*ecdsa.PrivateKey, error) { 18 | return crypto.GenerateKey() 19 | } 20 | 21 | // GetAccountFromPrivateKey gets an account from a private key 22 | func GetAccountFromPrivateKey(privateKey *ecdsa.PrivateKey) (accounts.Account, error) { 23 | return accounts.Account{ 24 | Address: crypto.PubkeyToAddress(privateKey.PublicKey), 25 | }, nil 26 | } 27 | 28 | // GetPublicKeyFromPrivateKey gets a public key from a private key 29 | func GetPublicKeyFromPrivateKey(privateKey *ecdsa.PrivateKey) (*ecdsa.PublicKey, error) { 30 | return &privateKey.PublicKey, nil 31 | } 32 | 33 | // GetAddressFromPublicKey gets an address from a public key 34 | func GetAddressFromPublicKey(publicKey *ecdsa.PublicKey) (common.Address, error) { 35 | return crypto.PubkeyToAddress(*publicKey), nil 36 | } 37 | 38 | // HexToPrivateKey converts a hex string to a private key 39 | func HexToPrivateKey(hexString string) (*ecdsa.PrivateKey, error) { 40 | privateKey, err := crypto.HexToECDSA(hexString) 41 | if err != nil { 42 | return nil, err 43 | } 44 | return privateKey, nil 45 | } 46 | 47 | // HexToAddress converts a hex string to an address 48 | func HexToAddress(hexString string) (common.Address, error) { 49 | address := common.HexToAddress(hexString) 50 | return address, nil 51 | } 52 | 53 | // AddressToString converts an address to a string 54 | func AddressToString(address common.Address) string { 55 | return address.Hex() 56 | } 57 | 58 | // PrivateKeyToString converts a private key to a string 59 | func PrivateKeyToString(privateKey *ecdsa.PrivateKey) string { 60 | return hex.EncodeToString(crypto.FromECDSA(privateKey)) 61 | } 62 | 63 | // PublicKeyToString converts a public key to a string 64 | func PublicKeyToString(publicKey *ecdsa.PublicKey) string { 65 | return hex.EncodeToString(crypto.FromECDSA(publicKey)) 66 | } 67 | 68 | // RandomHex generates a random hex string 69 | func RandomHex(length int) (string, error) { 70 | b := make([]byte, length) 71 | _, err := rand.Read(b) 72 | if err != nil { 73 | return "", err 74 | } 75 | return hex.EncodeToString(b), nil 76 | } 77 | 78 | // SplitAddress splits an address into its components 79 | func SplitAddress(address common.Address) (string, string, error) { 80 | parts := strings.Split(address.Hex(), "0x") 81 | if len(parts) != 2 { 82 | return "", "", fmt.Errorf("invalid address format") 83 | } 84 | return parts[0], parts[1], nil 85 | } 86 | -------------------------------------------------------------------------------- /blockchain/cosmos/node/cosmos_node.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "context" 5 | "crypto/ecdsa" 6 | "encoding/hex" 7 | "fmt" 8 | "math/big" 9 | "sync" 10 | "time" 11 | 12 | "github.com/cosmos/cosmos-sdk/types" 13 | "github.com/ethereum/go-ethereum/accounts" 14 | "github.com/ethereum/go-ethereum/common" 15 | "github.com/ethereum/go-ethereum/core/types" 16 | "github.com/ethereum/go-ethereum/crypto" 17 | "github.com/ethereum/go-ethereum/ethclient" 18 | "github.com/spf13/viper" 19 | ) 20 | 21 | // CosmosNode represents a Cosmos node 22 | type CosmosNode struct { 23 | client *ethclient.Client 24 | account accounts.Account 25 | privateKey *ecdsa.PrivateKey 26 | nodeURL string 27 | } 28 | 29 | // NewCosmosNode creates a new Cosmos node 30 | func NewCosmosNode(nodeURL string, privateKeyHex string) (*CosmosNode, error) { 31 | privateKey, err := crypto.HexToECDSA(privateKeyHex) 32 | if err!= nil { 33 | return nil, err 34 | } 35 | 36 | account := accounts.Account{ 37 | Address: crypto.PubkeyToAddress(privateKey.PublicKey), 38 | } 39 | 40 | client, err := ethclient.Dial(nodeURL) 41 | if err!= nil { 42 | return nil, err 43 | } 44 | 45 | return &CosmosNode{ 46 | client: client, 47 | account: account, 48 | privateKey: privateKey, 49 | nodeURL: nodeURL, 50 | }, nil 51 | } 52 | 53 | // Start starts the Cosmos node 54 | func (n *CosmosNode) Start(ctx context.Context) error { 55 | go n.listenForBlocks(ctx) 56 | return nil 57 | } 58 | 59 | // listenForBlocks listens for new blocks on the Cosmos node 60 | func (n *CosmosNode) listenForBlocks(ctx context.Context) { 61 | headers := make(chan *types.Header) 62 | sub, err := n.client.SubscribeNewHead(ctx, headers) 63 | if err!= nil { 64 | log.Fatal(err) 65 | } 66 | 67 | for { 68 | select { 69 | case header := <-headers: 70 | fmt.Printf("Received new block: %s\n", header.Hash().Hex()) 71 | n.processBlock(header) 72 | case <-ctx.Done(): 73 | sub.Unsubscribe() 74 | return 75 | } 76 | } 77 | } 78 | 79 | // processBlock processes a new block on the Cosmos node 80 | func (n *CosmosNode) processBlock(header *types.Header) { 81 | // Process block logic here 82 | } 83 | 84 | // SendTransaction sends a transaction on the Cosmos node 85 | func (n *CosmosNode) SendTransaction(tx *types.Transaction) error { 86 | return n.client.SendTransaction(context.Background(), tx) 87 | } 88 | 89 | // GetBalance gets the balance of an account on the Cosmos node 90 | func (n *CosmosNode) GetBalance(address common.Address) (*big.Int, error) { 91 | return n.client.BalanceAt(context.Background(), address, nil) 92 | } 93 | 94 | // GetTransactionCount gets the transaction count of an account on the Cosmos node 95 | func (n *CosmosNode) GetTransactionCount(address common.Address) (uint64, error) { 96 | return n.client.PendingNonceAt(context.Background(), address) 97 | } 98 | -------------------------------------------------------------------------------- /blockchain/polkadot/utils/polkadot_utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "encoding/hex" 6 | "encoding/json" 7 | "fmt" 8 | "math/big" 9 | "strings" 10 | "time" 11 | 12 | "github.com/centrifuge/go-substrate-rpc-client/v4/types" 13 | "github.com/ethereum/go-ethereum/accounts" 14 | "github.com/ethereum/go-ethereum/common" 15 | "github.com/ethereum/go-ethereum/core/types" 16 | "github.com/ethereum/go-ethereum/crypto" 17 | ) 18 | 19 | // HexToBytes converts a hex string to a byte slice 20 | func HexToBytes(hexString string) ([]byte, error) { 21 | return hex.DecodeString(strings.TrimPrefix(hexString, "0x")) 22 | } 23 | 24 | // BytesToHex converts a byte slice to a hex string 25 | func BytesToHex(bytes []byte) string { 26 | return "0x" + hex.EncodeToString(bytes) 27 | } 28 | 29 | // U256ToBigInt converts a U256 to a big.Int 30 | func U256ToBigInt(u256 types.U256) *big.Int { 31 | return big.NewInt(0).SetBytes(u256[:]) 32 | } 33 | 34 | // BigIntToU256 converts a big.Int to a U256 35 | func BigIntToU256(bigInt *big.Int) types.U256 { 36 | return types.U256(bigInt.Bytes()) 37 | } 38 | 39 | // SignMessage signs a message with a private key 40 | func SignMessage(privateKey *ecdsa.PrivateKey, message []byte) ([]byte, error) { 41 | return crypto.Sign(privateKey, message) 42 | } 43 | 44 | // VerifySignature verifies a signature with a public key 45 | func VerifySignature(publicKey *ecdsa.PublicKey, message []byte, signature []byte) bool { 46 | return crypto.VerifySignature(publicKey, message, signature) 47 | } 48 | 49 | // GenerateKey generates a new ECDSA key pair 50 | func GenerateKey() (*ecdsa.PrivateKey, *ecdsa.PublicKey, error) { 51 | return crypto.GenerateKey() 52 | } 53 | 54 | // GetAccountAddressFromPrivateKey gets the account address from a private key 55 | func GetAccountAddressFromPrivateKey(privateKey *ecdsa.PrivateKey) common.Address { 56 | return crypto.PubkeyToAddress(privateKey.PublicKey) 57 | } 58 | 59 | // GetAccountAddressFromPublicKey gets the account address from a public key 60 | func GetAccountAddressFromPublicKey(publicKey *ecdsa.PublicKey) common.Address { 61 | return crypto.PubkeyToAddress(*publicKey) 62 | } 63 | 64 | // EncodeExtrinsic encodes an extrinsic to JSON 65 | func EncodeExtrinsic(ext *types.Extrinsic) ([]byte, error) { 66 | return json.Marshal(ext) 67 | } 68 | 69 | // DecodeExtrinsic decodes an extrinsic from JSON 70 | func DecodeExtrinsic(data []byte) (*types.Extrinsic, error) { 71 | var ext types.Extrinsic 72 | err := json.Unmarshal(data, &ext) 73 | return &ext, err 74 | } 75 | 76 | // EncodeBlock encodes a block to JSON 77 | func EncodeBlock(block *types.Block) ([]byte, error) { 78 | return json.Marshal(block) 79 | } 80 | 81 | // DecodeBlock decodes a block from JSON 82 | func DecodeBlock(data []byte) (*types.Block, error) { 83 | var block types.Block 84 | err := json.Unmarshal(data, &block) 85 | return &block, err 86 | } 87 | -------------------------------------------------------------------------------- /blockchain/cosmos/node/cosmos_node_test.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/ethereum/go-ethereum/accounts" 8 | "github.com/ethereum/go-ethereum/common" 9 | "github.com/ethereum/go-ethereum/core/types" 10 | ) 11 | 12 | func TestCosmosNode(t *testing.T) { 13 | // ... 14 | 15 | // Test getting transaction count 16 | nonce, err := node.GetTransactionCount(address) 17 | if err!= nil { 18 | t.Fatal(err) 19 | } 20 | fmt.Printf("Transaction count: %d\n", nonce) 21 | 22 | // Test listening for blocks 23 | time.Sleep(10 * time.Second) // wait for 10 seconds to receive new blocks 24 | // assert that new blocks were received 25 | // ... 26 | } 27 | 28 | func TestNewCosmosNode(t *testing.T) { 29 | nodeURL := "https://mainnet.infura.io/v3/YOUR_PROJECT_ID" 30 | privateKeyHex := "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" 31 | 32 | _, err := NewCosmosNode(nodeURL, privateKeyHex) 33 | if err!= nil { 34 | t.Fatal(err) 35 | } 36 | } 37 | 38 | func TestCosmosNode_SendTransaction(t *testing.T) { 39 | nodeURL := "https://mainnet.infura.io/v3/YOUR_PROJECT_ID" 40 | privateKeyHex := "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" 41 | 42 | node, err := NewCosmosNode(nodeURL, privateKeyHex) 43 | if err!= nil { 44 | t.Fatal(err) 45 | } 46 | 47 | tx := types.NewTransaction(common.HexToAddress("0x742d35Cc6634C0532925a3b844Bc454e4438f44e"), common.HexToAddress("0x55241586d50469745864804697458648046974586"), big.NewInt(1000000000000000000), 20000, big.NewInt(20000000000)) 48 | err = node.SendTransaction(tx) 49 | if err!= nil { 50 | t.Fatal(err) 51 | } 52 | } 53 | 54 | func TestCosmosNode_GetBalance(t *testing.T) { 55 | nodeURL := "https://mainnet.infura.io/v3/YOUR_PROJECT_ID" 56 | privateKeyHex := "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" 57 | 58 | node, err := NewCosmosNode(nodeURL, privateKeyHex) 59 | if err!= nil { 60 | t.Fatal(err) 61 | } 62 | 63 | address := common.HexToAddress("0x742d35Cc6634C0532925a3b844Bc454e4438f44e") 64 | balance, err := node.GetBalance(address) 65 | if err!= nil { 66 | t.Fatal(err) 67 | } 68 | fmt.Printf("Balance: %s\n", balance) 69 | } 70 | 71 | func TestCosmosNode_GetTransactionCount(t *testing.T) { 72 | nodeURL := "https://mainnet.infura.io/v3/YOUR_PROJECT_ID" 73 | privateKeyHex := "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" 74 | 75 | node, err := NewCosmosNode(nodeURL, privateKeyHex) 76 | if err!= nil { 77 | t.Fatal(err) 78 | } 79 | 80 | address := common.HexToAddress("0x742d35Cc6634C0532925a3b844Bc454e4438f44e") 81 | nonce, err := node.GetTransactionCount(address) 82 | if err!= nil { 83 | t.Fatal(err) 84 | } 85 | fmt.Printf("Transaction count: %d\n", nonce) 86 | } 87 | -------------------------------------------------------------------------------- /blockchain/polkadot/node/polkadot_node.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "fmt" 5 | "github.com/centrifuge/go-substrate-rpc-client/v4/types" 6 | "github.com/centrifuge/go-substrate-rpc-client/v4/types/interfaces" 7 | "github.com/centrifuge/go-substrate-rpc-client/v4/types/primitive" 8 | "github.com/centrifuge/go-substrate-rpc-client/v4/types/events" 9 | "github.com/centrifuge/go-substrate-rpc-client/v4/types/extrinsic" 10 | "github.com/centrifuge/go-substrate-rpc-client/v4/types/query" 11 | "github.com/centrifuge/go-substrate-rpc-client/v4/types/rpc" 12 | "github.com/centrifuge/go-substrate-rpc-client/v4/types/sr25519" 13 | "github.com/centrifuge/go-substrate-rpc-client/v4/websocket" 14 | ) 15 | 16 | // PolkadotNode represents a Polkadot node 17 | type PolkadotNode struct { 18 | *websocket.Client 19 | } 20 | 21 | // NewPolkadotNode creates a new Polkadot node 22 | func NewPolkadotNode(url string) (*PolkadotNode, error) { 23 | client, err := websocket.New(url, nil) 24 | if err != nil { 25 | return nil, err 26 | } 27 | return &PolkadotNode{client}, nil 28 | } 29 | 30 | // GetBlockHash gets the hash of a block by its height 31 | func (n *PolkadotNode) GetBlockHash(height uint64) (types.Hash, error) { 32 | return n.Client.Chain.GetBlockHash(height) 33 | } 34 | 35 | // GetBlock gets a block by its hash 36 | func (n *PolkadotNode) GetBlock(hash types.Hash) (types.Block, error) { 37 | return n.Client.Chain.GetBlock(hash) 38 | } 39 | 40 | // GetFinalizedHead gets the finalized head of the chain 41 | func (n *PolkadotNode) GetFinalizedHead() (types.Header, error) { 42 | return n.Client.Chain.GetFinalizedHead() 43 | } 44 | 45 | // GetBestNumber gets the best block number 46 | func (n *PolkadotNode) GetBestNumber() (uint64, error) { 47 | return n.Client.Chain.GetBestNumber() 48 | } 49 | 50 | // GetMetadata gets the metadata of the chain 51 | func (n *PolkadotNode) GetMetadata() (types.Metadata, error) { 52 | return n.Client.State.GetMetadata() 53 | } 54 | 55 | // GetStorage gets the value of a storage item 56 | func (n *PolkadotNode) GetStorage(item types.StorageKey) (types.StorageData, error) { 57 | return n.Client.State.GetStorage(item) 58 | } 59 | 60 | // GetEventRecords gets the event records for a block 61 | func (n *PolkadotNode) GetEventRecords(hash types.Hash, event types.Event) ([]events.EventRecord, error) { 62 | return n.Client.Events.GetEventRecords(hash, event) 63 | } 64 | 65 | // ExtrinsicSign signs an extrinsic 66 | func (n *PolkadotNode) ExtrinsicSign(ext extrinsic.Extrinsic, signer sr25519.Pair) (extrinsic.Extrinsic, error) { 67 | return ext.Sign(signer) 68 | } 69 | 70 | // SubmitExtrinsic submits an extrinsic 71 | func (n *PolkadotNode) SubmitExtrinsic(ext extrinsic.Extrinsic) (types.Hash, error) { 72 | return n.Client.Extrinsic.Submit(ext) 73 | } 74 | 75 | // QuerySubscribe subscribes to a query 76 | func (n *PolkadotNode) QuerySubscribe(query query.Subscription) (query.Subscriber, error) { 77 | return n.Client.Subscribe(query) 78 | } 79 | -------------------------------------------------------------------------------- /consensus/utils/consensus_utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGeneratePrivateKey(t *testing.T) { 8 | privateKey, err := GeneratePrivateKey() 9 | if err!= nil { 10 | t.Errorf("Expected GeneratePrivateKey to succeed, but got error: %s", err) 11 | } 12 | if privateKey == nil { 13 | t.Errorf("Expected privateKey to be non-nil, but got nil") 14 | } 15 | } 16 | 17 | func TestGeneratePublicKey(t *testing.T) { 18 | privateKey, err := GeneratePrivateKey() 19 | if err!= nil { 20 | t.Fatal(err) 21 | } 22 | publicKey, err := GeneratePublicKey(privateKey) 23 | if err!= nil { 24 | t.Errorf("Expected GeneratePublicKey to succeed, but got error: %s", err) 25 | } 26 | if publicKey == nil { 27 | t.Errorf("Expected publicKey to be non-nil, but got nil") 28 | } 29 | } 30 | 31 | func TestGenerateAddress(t *testing.T) { 32 | privateKey, err := GeneratePrivateKey() 33 | if err!= nil { 34 | t.Fatal(err) 35 | } 36 | publicKey, err := GeneratePublicKey(privateKey) 37 | if err!= nil { 38 | t.Fatal(err) 39 | } 40 | address, err := GenerateAddress(publicKey) 41 | if err!= nil { 42 | t.Errorf("Expected GenerateAddress to succeed, but got error: %s", err) 43 | } 44 | if address == "" { 45 | t.Errorf("Expected address to be non-empty, but got empty string") 46 | } 47 | } 48 | 49 | func TestSign(t *testing.T) { 50 | privateKey, err := GeneratePrivateKey() 51 | if err!= nil { 52 | t.Fatal(err) 53 | } 54 | message := []byte("hello world") 55 | signature, err := Sign(privateKey, message) 56 | if err!= nil { 57 | t.Errorf("Expected Sign to succeed, but got error: %s", err) 58 | } 59 | if signature == "" { 60 | t.Errorf("Expected signature to be non-empty, but got empty string") 61 | } 62 | } 63 | 64 | func TestVerify(t *testing.T) { 65 | privateKey, err := GeneratePrivateKey() 66 | if err!= nil { 67 | t.Fatal(err) 68 | } 69 | publicKey, err := GeneratePublicKey(privateKey) 70 | if err!= nil { 71 | t.Fatal(err) 72 | } 73 | message := []byte("hello world") 74 | signature, err := Sign(privateKey, message) 75 | if err!= nil { 76 | t.Fatal(err) 77 | } 78 | valid, err := Verify(publicKey, message, signature) 79 | if err!= nil { 80 | t.Errorf("Expected Verify to succeed, but got error: %s", err) 81 | } 82 | if!valid { 83 | t.Errorf("Expected signature to be valid, but got invalid") 84 | } 85 | } 86 | 87 | func TestCalculateBlockHash(t *testing.T) { 88 | block := &types.Block{ 89 | PreviousHash: "previous-block-hash", 90 | Transactions: []*types.Transaction{ 91 | { 92 | ID: "transaction-id", 93 | }, 94 | }, 95 | Timestamp: time.Now().Unix(), 96 | } 97 | hash, err := CalculateBlockHash(block) 98 | if err!= nil { 99 | t.Errorf("Expected CalculateBlockHash to succeed, but got error: %s", err) 100 | } 101 | if hash == "" { 102 | t.Errorf("Expected hash to be non-empty, but got empty string") 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /network/protocol/pi_protocol.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "crypto/rand" 6 | "encoding/json" 7 | "errors" 8 | "fmt" 9 | "io" 10 | "net" 11 | 12 | "github.com/libp2p/go-libp2p-core/network" 13 | "github.com/libp2p/go-libp2p-core/peer" 14 | "github.com/multiformats/go-multibase" 15 | ) 16 | 17 | const ( 18 | ProtocolID = "/pi/1.0.0" 19 | ) 20 | 21 | type PiProtocol struct { 22 | peer.ID 23 | privateKey *ecdsa.PrivateKey 24 | } 25 | 26 | func NewPiProtocol(privateKey *ecdsa.PrivateKey) (*PiProtocol, error) { 27 | id, err := peer.IDFromPrivateKey(privateKey) 28 | if err!= nil { 29 | return nil, err 30 | } 31 | return &PiProtocol{ID: id, privateKey: privateKey}, nil 32 | } 33 | 34 | func (p *PiProtocol) HandleStream(s network.Stream) { 35 | // Handle incoming stream 36 | fmt.Println("Received stream from", s.Conn().RemotePeer()) 37 | // Read message from stream 38 | msg, err := readMessage(s) 39 | if err!= nil { 40 | fmt.Println("Error reading message:", err) 41 | return 42 | } 43 | // Process message 44 | p.processMessage(msg) 45 | } 46 | 47 | func (p *PiProtocol) processMessage(msg []byte) { 48 | // Unmarshal message 49 | var message struct { 50 | Type string `json:"type"` 51 | Data []byte `json:"data"` 52 | } 53 | err := json.Unmarshal(msg, &message) 54 | if err!= nil { 55 | fmt.Println("Error unmarshaling message:", err) 56 | return 57 | } 58 | // Handle message based on type 59 | switch message.Type { 60 | case "hello": 61 | fmt.Println("Received hello message from", p.ID) 62 | case "data": 63 | fmt.Println("Received data message from", p.ID) 64 | // Process data message 65 | p.processDataMessage(message.Data) 66 | default: 67 | fmt.Println("Unknown message type:", message.Type) 68 | } 69 | } 70 | 71 | func (p *PiProtocol) processDataMessage(data []byte) { 72 | // Process data message 73 | fmt.Println("Processing data message...") 74 | //... 75 | } 76 | 77 | func readMessage(s network.Stream) ([]byte, error) { 78 | // Read message length 79 | var length uint32 80 | err := binary.Read(s, binary.BigEndian, &length) 81 | if err!= nil { 82 | return nil, err 83 | } 84 | // Read message data 85 | msg := make([]byte, length) 86 | _, err = io.ReadFull(s, msg) 87 | if err!= nil { 88 | return nil, err 89 | } 90 | return msg, nil 91 | } 92 | 93 | func (p *PiProtocol) SendMessage(ctx context.Context, peerID peer.ID, msg []byte) error { 94 | // Create a new stream to the peer 95 | s, err := p.Host().NewStream(ctx, peerID, ProtocolID) 96 | if err!= nil { 97 | return err 98 | } 99 | // Write message to stream 100 | err = writeMessage(s, msg) 101 | if err!= nil { 102 | return err 103 | } 104 | return nil 105 | } 106 | 107 | func writeMessage(s network.Stream, msg []byte) error { 108 | // Write message length 109 | err := binary.Write(s, binary.BigEndian, uint32(len(msg))) 110 | if err!= nil { 111 | return err 112 | } 113 | // Write message data 114 | _, err = s.Write(msg) 115 | if err!= nil { 116 | return err 117 | } 118 | return nil 119 | } 120 | -------------------------------------------------------------------------------- /blockchain/polkadot/protocol/polkadot_protocol_tests.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "context" 5 | "crypto/ecdsa" 6 | "encoding/json" 7 | "fmt" 8 | "math/big" 9 | "strings" 10 | "testing" 11 | "time" 12 | 13 | "github.com/centrifuge/go-substrate-rpc-client/v4/types" 14 | "github.com/ethereum/go-ethereum/accounts" 15 | "github.com/ethereum/go-ethereum/common" 16 | "github.com/ethereum/go-ethereum/core/types" 17 | "github.com/ethereum/go-ethereum/crypto" 18 | ) 19 | 20 | func TestPolkadotProtocol(t *testing.T) { 21 | nodeURL := "ws://localhost:9944" 22 | protocol, err := NewPolkadotProtocol(nodeURL) 23 | if err!= nil { 24 | t.Fatal(err) 25 | } 26 | defer protocol.client.Close() 27 | 28 | // Test GetBlockHash 29 | height := uint64(100) 30 | hash, err := protocol.GetBlockHash(height) 31 | if err!= nil { 32 | t.Fatal(err) 33 | } 34 | fmt.Printf("Block hash at height %d: %s\n", height, hash) 35 | 36 | // Test GetBlock 37 | block, err := protocol.GetBlock(hash) 38 | if err!= nil { 39 | t.Fatal(err) 40 | } 41 | fmt.Printf("Block at hash %s: %+v\n", hash, block) 42 | 43 | // Test GetFinalizedHead 44 | header, err := protocol.GetFinalizedHead() 45 | if err!= nil { 46 | t.Fatal(err) 47 | } 48 | fmt.Printf("Finalized head: %+v\n", header) 49 | 50 | // Test GetBestNumber 51 | number, err := protocol.GetBestNumber() 52 | if err!= nil { 53 | t.Fatal(err) 54 | } 55 | fmt.Printf("Best block number: %d\n", number) 56 | 57 | // Test GetMetadata 58 | metadata, err := protocol.GetMetadata() 59 | if err!= nil { 60 | t.Fatal(err) 61 | } 62 | fmt.Printf("Metadata: %+v\n", metadata) 63 | 64 | // Test GetStorage 65 | key := "0x1234567890abcdef" 66 | data, err := protocol.GetStorage(key) 67 | if err!= nil { 68 | t.Fatal(err) 69 | } 70 | fmt.Printf("Storage value at key %s: %s\n", key, data) 71 | 72 | // Test ExtrinsicSign 73 | ext := &types.Extrinsic{ 74 | Call: &types.Call{ 75 | Module: "balances", 76 | Func: "transfer", 77 | Args: []types.Arg{ 78 | types.NewArg("amount", types.NewU128(100)), 79 | types.NewArg("dest", types.NewAccountId("0x1234567890abcdef")), 80 | }, 81 | }, 82 | } 83 | signer, err := crypto.GenerateKey() 84 | if err!= nil { 85 | t.Fatal(err) 86 | } 87 | signedExt, err := protocol.ExtrinsicSign(ext, signer) 88 | if err!= nil { 89 | t.Fatal(err) 90 | } 91 | fmt.Printf("Signed extrinsic: %+v\n", signedExt) 92 | 93 | // Test SubmitExtrinsic 94 | hash, err = protocol.SubmitExtrinsic(signedExt) 95 | if err!= nil { 96 | t.Fatal(err) 97 | } 98 | fmt.Printf("Submitted extrinsic with hash %s\n", hash) 99 | 100 | // Test QuerySubscribe 101 | query := &types.Query{ 102 | Module: "system", 103 | Func: "events", 104 | Args: []types.Arg{ 105 | types.NewArg("phase", types.NewU8(1)), 106 | }, 107 | } 108 | subscriber, err := protocol.QuerySubscribe(query) 109 | if err!= nil { 110 | t.Fatal(err) 111 | } 112 | defer subscriber.Unsubscribe() 113 | 114 | for { 115 | select { 116 | case <-subscriber.Done(): 117 | return 118 | case event := <-subscriber.Chan(): 119 | fmt.Printf("Received event: %+v\n", event) 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /blockchain/cosmos/protocol/cosmos_protocol.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "context" 5 | "crypto/ecdsa" 6 | "encoding/hex" 7 | "fmt" 8 | "math/big" 9 | "sync" 10 | "time" 11 | 12 | "github.com/cosmos/cosmos-sdk/types" 13 | "github.com/ethereum/go-ethereum/accounts" 14 | "github.com/ethereum/go-ethereum/common" 15 | "github.com/ethereum/go-ethereum/core/types" 16 | "github.com/ethereum/go-ethereum/crypto" 17 | "github.com/ethereum/go-ethereum/ethclient" 18 | "github.com/spf13/viper" 19 | ) 20 | 21 | // CosmosProtocol represents the Cosmos protocol 22 | type CosmosProtocol struct { 23 | node *Node 24 | client *ethclient.Client 25 | account accounts.Account 26 | privateKey *ecdsa.PrivateKey 27 | } 28 | 29 | // NewCosmosProtocol creates a new Cosmos protocol 30 | func NewCosmosProtocol(nodeURL string, privateKeyHex string) (*CosmosProtocol, error) { 31 | privateKey, err := crypto.HexToECDSA(privateKeyHex) 32 | if err!= nil { 33 | return nil, err 34 | } 35 | 36 | account := accounts.Account{ 37 | Address: crypto.PubkeyToAddress(privateKey.PublicKey), 38 | } 39 | 40 | client, err := ethclient.Dial(nodeURL) 41 | if err!= nil { 42 | return nil, err 43 | } 44 | 45 | node, err := NewNode(nodeURL, privateKeyHex) 46 | if err!= nil { 47 | return nil, err 48 | } 49 | 50 | return &CosmosProtocol{ 51 | node: node, 52 | client: client, 53 | account: account, 54 | privateKey: privateKey, 55 | }, nil 56 | } 57 | 58 | // Start starts the Cosmos protocol 59 | func (p *CosmosProtocol) Start(ctx context.Context) error { 60 | go p.node.listenForBlocks(ctx) 61 | return nil 62 | } 63 | 64 | // SendTransaction sends a transaction on the Cosmos protocol 65 | func (p *CosmosProtocol) SendTransaction(tx *types.Transaction) error { 66 | return p.client.SendTransaction(context.Background(), tx) 67 | } 68 | 69 | // GetBalance gets the balance of an account on the Cosmos protocol 70 | func (p *CosmosProtocol) GetBalance(address common.Address) (*big.Int, error) { 71 | return p.client.BalanceAt(context.Background(), address, nil) 72 | } 73 | 74 | // GetTransactionCount gets the transaction count of an account on the Cosmos protocol 75 | func (p *CosmosProtocol) GetTransactionCount(address common.Address) (uint64, error) { 76 | return p.client.PendingNonceAt(context.Background(), address) 77 | } 78 | 79 | // GetBlockByNumber gets a block by number on the Cosmos protocol 80 | func (p *CosmosProtocol) GetBlockByNumber(number uint64) (*types.Block, error) { 81 | return p.client.BlockByNumber(context.Background(), big.NewInt(int64(number))) 82 | } 83 | 84 | // GetBlockByHash gets a block by hash on the Cosmos protocol 85 | func (p *CosmosProtocol) GetBlockByHash(hash common.Hash) (*types.Block, error) { 86 | return p.client.BlockByHash(context.Background(), hash) 87 | } 88 | 89 | // GetTransactionByHash gets a transaction by hash on the Cosmos protocol 90 | func (p *CosmosProtocol) GetTransactionByHash(hash common.Hash) (*types.Transaction, bool, error) { 91 | return p.client.TransactionByHash(context.Background(), hash) 92 | } 93 | 94 | // GetTransactionReceipt gets a transaction receipt on the Cosmos protocol 95 | func (p *CosmosProtocol) GetTransactionReceipt(hash common.Hash) (*types.Receipt, error) { 96 | return p.client.TransactionReceipt(context.Background(), hash) 97 | } 98 | -------------------------------------------------------------------------------- /blockchain/pi_network/node/pi_node.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "context" 5 | "crypto/ecdsa" 6 | "encoding/json" 7 | "fmt" 8 | "log" 9 | "net/http" 10 | "sync" 11 | 12 | "github.com/gorilla/mux" 13 | "github.com/pi-network/pi-node/types" 14 | "github.com/pi-network/pi-node/utils" 15 | ) 16 | 17 | // PiNode represents a node in the Pi Network 18 | type PiNode struct { 19 | // Node configuration 20 | config *types.Config 21 | 22 | // Node private key 23 | privateKey *ecdsa.PrivateKey 24 | 25 | // Node public key 26 | publicKey *ecdsa.PublicKey 27 | 28 | // Node address 29 | address string 30 | 31 | // Node port 32 | port int 33 | 34 | // Node router 35 | router *mux.Router 36 | 37 | // Node server 38 | server *http.Server 39 | 40 | // Node mutex 41 | mutex sync.Mutex 42 | } 43 | 44 | // NewPiNode creates a new Pi Node 45 | func NewPiNode(config *types.Config) (*PiNode, error) { 46 | privateKey, err := utils.GeneratePrivateKey() 47 | if err != nil { 48 | return nil, err 49 | } 50 | 51 | publicKey, err := utils.GeneratePublicKey(privateKey) 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | address, err := utils.GenerateAddress(publicKey) 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | node := &PiNode{ 62 | config: config, 63 | privateKey: privateKey, 64 | publicKey: publicKey, 65 | address: address, 66 | port: config.Port, 67 | router: mux.NewRouter(), 68 | } 69 | 70 | node.router.HandleFunc("/api/v1/node", node.handleNodeRequest).Methods("GET") 71 | node.router.HandleFunc("/api/v1/transactions", node.handleTransactionsRequest).Methods("POST") 72 | 73 | node.server = &http.Server{ 74 | Addr: fmt.Sprintf(":%d", node.port), 75 | Handler: node.router, 76 | } 77 | 78 | return node, nil 79 | } 80 | 81 | // Start starts the Pi Node 82 | func (n *PiNode) Start() error { 83 | log.Println("Starting Pi Node...") 84 | 85 | n.mutex.Lock() 86 | defer n.mutex.Unlock() 87 | 88 | err := n.server.ListenAndServe() 89 | if err != nil { 90 | return err 91 | } 92 | 93 | log.Println("Pi Node started successfully!") 94 | 95 | return nil 96 | } 97 | 98 | // Stop stops the Pi Node 99 | func (n *PiNode) Stop() error { 100 | log.Println("Stopping Pi Node...") 101 | 102 | n.mutex.Lock() 103 | defer n.mutex.Unlock() 104 | 105 | err := n.server.Close() 106 | if err != nil { 107 | return err 108 | } 109 | 110 | log.Println("Pi Node stopped successfully!") 111 | 112 | return nil 113 | } 114 | 115 | // handleNodeRequest handles requests to the /api/v1/node endpoint 116 | func (n *PiNode) handleNodeRequest(w http.ResponseWriter, r *http.Request) { 117 | log.Println("Received request to /api/v1/node") 118 | 119 | nodeInfo := &types.NodeInfo{ 120 | Address: n.address, 121 | Port: n.port, 122 | } 123 | 124 | json.NewEncoder(w).Encode(nodeInfo) 125 | } 126 | 127 | // handleTransactionsRequest handles requests to the /api/v1/transactions endpoint 128 | func (n *PiNode) handleTransactionsRequest(w http.ResponseWriter, r *http.Request) { 129 | log.Println("Received request to /api/v1/transactions") 130 | 131 | transactions := make([]*types.Transaction, 0) 132 | 133 | // Process transactions here... 134 | 135 | json.NewEncoder(w).Encode(transactions) 136 | } 137 | -------------------------------------------------------------------------------- /interoperability/protocol/pi_interoperability_test.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPIInteroperability_SendMessage(t *testing.T) { 8 | conn := &websocket.Conn{} 9 | .pi := NewPIInteroperability(conn) 10 | message := &PIMessage{Type: "hello", Payload: []byte("world")} 11 | err := pi.SendMessage(message) 12 | if err != nil { 13 | t.Errorf("Expected SendMessage to succeed, but got error: %s", err) 14 | } 15 | } 16 | 17 | func TestPIInteroperability_ReceiveMessage(t *testing.T) { 18 | conn := &websocket.Conn{} 19 | .pi := NewPIInteroperability(conn) 20 | message := &PIMessage{Type: "hello", Payload: []byte("world")} 21 | err := pi.conn.WriteMessage(websocket.TextMessage, message) 22 | if err != nil { 23 | t.Errorf("Expected WriteMessage to succeed, but got error: %s", err) 24 | } 25 | receivedMessage, err := pi.ReceiveMessage() 26 | if err != nil { 27 | t.Errorf("Expected ReceiveMessage to succeed, but got error: %s", err) 28 | } 29 | if receivedMessage.Type != message.Type { 30 | t.Errorf("Expected received message type to match sent message type, but got %s", receivedMessage.Type) 31 | } 32 | } 33 | 34 | func TestPIInteroperability_Close(t *testing.T) { 35 | conn := &websocket.Conn{} 36 | .pi := NewPIInteroperability(conn) 37 | err := pi.Close() 38 | if err != nil { 39 | t.Errorf("Expected Close to succeed, but got error: %s", err) 40 | } 41 | } 42 | 43 | func TestPIMessage_UnmarshalPayload(t *testing.T) { 44 | message := &PIMessage{Payload: []byte(`{"key": "value"}`)} 45 | var payload struct { 46 | Key string `json:"key"` 47 | Value string `json:"value"` 48 | } 49 | err := message.UnmarshalPayload(&payload) 50 | if err != nil { 51 | t.Errorf("Expected UnmarshalPayload to succeed, but got error: %s", err) 52 | } 53 | if payload.Key != "value" { 54 | t.Errorf("Expected payload key to be 'value', but got %s", payload.Key) 55 | } 56 | } 57 | 58 | func TestPIMessage_MarshalPayload(t *testing.T) { 59 | message := &PIMessage{} 60 | payload := struct { 61 | Key string `json:"key"` 62 | Value string `json:"value"` 63 | }{Key: "value", Value: "hello"} 64 | err := message.MarshalPayload(payload) 65 | if err!= nil { 66 | t.Errorf("Expected MarshalPayload to succeed, but got error: %s", err) 67 | } 68 | if string(message.Payload)!= `{"key":"value","value":"hello"}` { 69 | t.Errorf("Expected payload to be marshaled correctly, but got %s", message.Payload) 70 | } 71 | } 72 | 73 | func TestPIProtoMessage_Marshal(t *testing.T) { 74 | message := &PIProtoMessage{Type: "hello", Payload: []byte("world")} 75 | data, err := message.Marshal() 76 | if err!= nil { 77 | t.Errorf("Expected Marshal to succeed, but got error: %s", err) 78 | } 79 | if len(data) == 0 { 80 | t.Errorf("Expected marshaled data to be non-empty") 81 | } 82 | } 83 | 84 | func TestPIProtoMessage_Unmarshal(t *testing.T) { 85 | data := []byte{0x0a, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64} 86 | message := &PIProtoMessage{} 87 | err := message.Unmarshal(data) 88 | if err!= nil { 89 | t.Errorf("Expected Unmarshal to succeed, but got error: %s", err) 90 | } 91 | if message.Type!= "hello" { 92 | t.Errorf("Expected unmarshaled type to be 'hello', but got %s", message.Type) 93 | } 94 | if string(message.Payload)!= "world" { 95 | t.Errorf("Expected unmarshaled payload to be 'world', but got %s", message.Payload) 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /network/node/pi_node.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "context" 5 | "crypto/ecdsa" 6 | "crypto/elliptic" 7 | "crypto/rand" 8 | "encoding/hex" 9 | "encoding/json" 10 | "fmt" 11 | "math/big" 12 | "net" 13 | "sync" 14 | "time" 15 | 16 | "github.com/libp2p/go-libp2p-core/host" 17 | "github.com/libp2p/go-libp2p-core/network" 18 | "github.com/libp2p/go-libp2p-core/peer" 19 | "github.com/multiformats/go-multiaddr" 20 | ) 21 | 22 | // PiNode represents a node in the Pi network 23 | type PiNode struct { 24 | host.Host 25 | privateKey *ecdsa.PrivateKey 26 | publicKey *ecdsa.PublicKey 27 | peerInfo peer.AddrInfo 28 | } 29 | 30 | // NewPiNode creates a new PiNode instance 31 | func NewPiNode(ctx context.Context, privateKey *ecdsa.PrivateKey) (*PiNode, error) { 32 | h, err := host.New(ctx) 33 | if err!= nil { 34 | return nil, err 35 | } 36 | publicKey := &privateKey.PublicKey 37 | peerInfo, err := peer.AddrInfoFromP2pAddr(multiaddr.StringCast("/ip4/127.0.0.1/tcp/0")) 38 | if err!= nil { 39 | return nil, err 40 | } 41 | return &PiNode{ 42 | Host: h, 43 | privateKey: privateKey, 44 | publicKey: publicKey, 45 | peerInfo: peerInfo, 46 | }, nil 47 | } 48 | 49 | // Start starts the PiNode 50 | func (n *PiNode) Start(ctx context.Context) error { 51 | return n.Host.SetStreamHandler(protocol.ID("/pi/1.0.0"), n.handleStream) 52 | } 53 | 54 | // handleStream handles incoming streams 55 | func (n *PiNode) handleStream(s network.Stream) { 56 | fmt.Println("Received stream from", s.Conn().RemotePeer()) 57 | // Handle the stream... 58 | } 59 | 60 | // Send sends a message to another node 61 | func (n *PiNode) Send(ctx context.Context, to peer.ID, message []byte) error { 62 | s, err := n.Host.NewStream(ctx, to, protocol.ID("/pi/1.0.0")) 63 | if err!= nil { 64 | return err 65 | } 66 | _, err = s.Write(message) 67 | return err 68 | } 69 | 70 | // GenerateKeyPair generates a new key pair 71 | func GenerateKeyPair() (*ecdsa.PrivateKey, *ecdsa.PublicKey, error) { 72 | privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 73 | if err!= nil { 74 | return nil, nil, err 75 | } 76 | publicKey := &privateKey.PublicKey 77 | return privateKey, publicKey, nil 78 | } 79 | 80 | // MarshalJSON marshals the PiNode to JSON 81 | func (n *PiNode) MarshalJSON() ([]byte, error) { 82 | return json.Marshal(struct { 83 | PublicKey string `json:"public_key"` 84 | PeerInfo string `json:"peer_info"` 85 | }{ 86 | PublicKey: hex.EncodeToString(n.publicKey.X.Bytes()), 87 | PeerInfo: n.peerInfo.String(), 88 | }) 89 | } 90 | 91 | // UnmarshalJSON unmarshals a JSON byte slice to a PiNode 92 | func UnmarshalJSON(data []byte) (*PiNode, error) { 93 | var jsonNode struct { 94 | PublicKey string `json:"public_key"` 95 | PeerInfo string `json:"peer_info"` 96 | } 97 | err := json.Unmarshal(data, &jsonNode) 98 | if err!= nil { 99 | return nil, err 100 | } 101 | publicKeyX, err := hex.DecodeString(jsonNode.PublicKey) 102 | if err!= nil { 103 | return nil, err 104 | } 105 | publicKey := &ecdsa.PublicKey{ 106 | Curve: elliptic.P256(), 107 | X: publicKeyX, 108 | Y: new(big.Int).SetBytes([]byte{}), 109 | } 110 | peerInfo, err := peer.AddrInfoFromP2pAddr(jsonNode.PeerInfo) 111 | if err!= nil { 112 | return nil, err 113 | } 114 | return &PiNode{ 115 | publicKey: publicKey, 116 | peerInfo: peerInfo, 117 | }, nil 118 | } 119 | -------------------------------------------------------------------------------- /blockchain/cosmos/utils/cosmos_utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/ethereum/go-ethereum/accounts" 7 | "github.com/ethereum/go-ethereum/common" 8 | "github.com/ethereum/go-ethereum/crypto" 9 | ) 10 | 11 | func TestGeneratePrivateKey(t *testing.T) { 12 | privateKey, err := GeneratePrivateKey() 13 | if err != nil { 14 | t.Fatal(err) 15 | } 16 | fmt.Printf("Private key: %s\n", PrivateKeyToString(privateKey)) 17 | } 18 | 19 | func TestGetAccountFromPrivateKey(t *testing.T) { 20 | privateKey, err := GeneratePrivateKey() 21 | if err != nil { 22 | t.Fatal(err) 23 | } 24 | account, err := GetAccountFromPrivateKey(privateKey) 25 | if err != nil { 26 | t.Fatal(err) 27 | } 28 | fmt.Printf("Account: %v\n", account) 29 | } 30 | 31 | func TestGetPublicKeyFromPrivateKey(t *testing.T) { 32 | privateKey, err := GeneratePrivateKey() 33 | if err != nil { 34 | t.Fatal(err) 35 | } 36 | publicKey, err := GetPublicKeyFromPrivateKey(privateKey) 37 | if err != nil { 38 | t.Fatal(err) 39 | } 40 | fmt.Printf("Public key: %s\n", PublicKeyToString(publicKey)) 41 | } 42 | 43 | func TestGetAddressFromPublicKey(t *testing.T) { 44 | privateKey, err := GeneratePrivateKey() 45 | if err != nil { 46 | t.Fatal(err) 47 | } 48 | publicKey, err := GetPublicKeyFromPrivateKey(privateKey) 49 | if err != nil { 50 | t.Fatal(err) 51 | } 52 | address, err := GetAddressFromPublicKey(publicKey) 53 | if err != nil { 54 | t.Fatal(err) 55 | } 56 | fmt.Printf("Address: %s\n", address.Hex()) 57 | } 58 | 59 | func TestHexToPrivateKey(t *testing.T) { 60 | hexString := "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" 61 | privateKey, err := HexToPrivateKey(hexString) 62 | if err != nil { 63 | t.Fatal(err) 64 | } 65 | fmt.Printf("Private key: %s\n", PrivateKeyToString(privateKey)) 66 | } 67 | 68 | func TestHexToAddress(t *testing.T) { 69 | hexString := "0x742d35Cc6634C0532925a3b844Bc454e4438f44e" 70 | address, err := HexToAddress(hexString) 71 | if err!= nil { 72 | t.Fatal(err) 73 | } 74 | fmt.Printf("Address: %s\n", address.Hex()) 75 | } 76 | 77 | func TestAddressToString(t *testing.T) { 78 | address := common.HexToAddress("0x742d35Cc6634C0532925a3b844Bc454e4438f44e") 79 | str := AddressToString(address) 80 | fmt.Printf("Address string: %s\n", str) 81 | } 82 | 83 | func TestPrivateKeyToString(t *testing.T) { 84 | privateKey, err := GeneratePrivateKey() 85 | if err!= nil { 86 | t.Fatal(err) 87 | } 88 | str := PrivateKeyToString(privateKey) 89 | fmt.Printf("Private key string: %s\n", str) 90 | } 91 | 92 | func TestPublicKeyToString(t *testing.T) { 93 | privateKey, err := GeneratePrivateKey() 94 | if err!= nil { 95 | t.Fatal(err) 96 | } 97 | publicKey, err := GetPublicKeyFromPrivateKey(privateKey) 98 | if err!= nil { 99 | t.Fatal(err) 100 | } 101 | str := PublicKeyToString(publicKey) 102 | fmt.Printf("Public key string: %s\n", str) 103 | } 104 | 105 | func TestRandomHex(t *testing.T) { 106 | hexString, err := RandomHex(32) 107 | if err!= nil { 108 | t.Fatal(err) 109 | } 110 | fmt.Printf("Random hex: %s\n", hexString) 111 | } 112 | 113 | func TestSplitAddress(t *testing.T) { 114 | address := common.HexToAddress("0x742d35Cc6634C0532925a3b844Bc454e4438f44e") 115 | prefix, hex, err := SplitAddress(address) 116 | if err!= nil { 117 | t.Fatal(err) 118 | } 119 | fmt.Printf("Prefix: %s, Hex: %s\n", prefix, hex) 120 | } 121 | -------------------------------------------------------------------------------- /crypto/utils/crypto_utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | "crypto/hmac" 8 | "crypto/rand" 9 | "crypto/rsa" 10 | "crypto/sha256" 11 | "encoding/base64" 12 | "errors" 13 | "io" 14 | ) 15 | 16 | // GenerateRandomBytes generates a random byte slice of the given length 17 | func GenerateRandomBytes(length int) ([]byte, error) { 18 | b := make([]byte, length) 19 | _, err := rand.Read(b) 20 | return b, err 21 | } 22 | 23 | // HashSHA256 hashes the given data using SHA-256 24 | func HashSHA256(data []byte) ([]byte, error) { 25 | hash := sha256.New() 26 | _, err := hash.Write(data) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return hash.Sum(nil), nil 31 | } 32 | 33 | // EncryptAES encrypts the given plaintext using AES-256-CBC 34 | func EncryptAES(plaintext []byte, key []byte) ([]byte, error) { 35 | block, err := aes.NewCipher(key) 36 | if err != nil { 37 | return nil, err 38 | } 39 | ciphertext := make([]byte, aes.BlockSize+len(plaintext)) 40 | iv := ciphertext[:aes.BlockSize] 41 | _, err = rand.Read(iv) 42 | if err != nil { 43 | return nil, err 44 | } 45 | cfb := cipher.NewCFBEncrypter(block, iv) 46 | cfb.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) 47 | return ciphertext, nil 48 | } 49 | 50 | // DecryptAES decrypts the given ciphertext using AES-256-CBC 51 | func DecryptAES(ciphertext []byte, key []byte) ([]byte, error) { 52 | block, err := aes.NewCipher(key) 53 | if err != nil { 54 | return nil, err 55 | } 56 | if len(ciphertext) < aes.BlockSize { 57 | return nil, errors.New("ciphertext too short") 58 | } 59 | iv := ciphertext[:aes.BlockSize] 60 | ciphertext = ciphertext[aes.BlockSize:] 61 | cfb := cipher.NewCFBDecrypter(block, iv) 62 | cfb.XORKeyStream(ciphertext, ciphertext) 63 | return ciphertext, nil 64 | } 65 | 66 | // SignRSA signs the given data using RSA 67 | func SignRSA(data []byte, privateKey *rsa.PrivateKey) ([]byte, error) { 68 | hash, err := HashSHA256(data) 69 | if err != nil { 70 | return nil, err 71 | } 72 | return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hash) 73 | } 74 | 75 | // VerifyRSA verifies the given signature using RSA 76 | func VerifyRSA(data []byte, signature []byte, publicKey *rsa.PublicKey) error { 77 | hash, err := HashSHA256(data) 78 | if err != nil { 79 | return err 80 | } 81 | return rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hash, signature) 82 | } 83 | 84 | // GenerateHMAC generates an HMAC (Message Authentication Code) for the given data 85 | func GenerateHMAC(data []byte, key []byte) ([]byte, error) { 86 | mac := hmac.New(sha256.New, key) 87 | _, err := mac.Write(data) 88 | if err != nil { 89 | return nil, err 90 | } 91 | return mac.Sum(nil), nil 92 | } 93 | 94 | // VerifyHMAC verifies the given HMAC for the given data 95 | func VerifyHMAC(data []byte, hmac []byte, key []byte) error { 96 | expectedHMAC, err := GenerateHMAC(data, key) 97 | if err != nil { 98 | return err 99 | } 100 | if !hmac.Equal(expectedHMAC, hmac) { 101 | return errors.New("HMAC verification failed") 102 | } 103 | return nil 104 | } 105 | 106 | // Base64Encode encodes the given data using Base64 107 | func Base64Encode(data []byte) (string, error) { 108 | return base64.StdEncoding.EncodeToString(data), nil 109 | } 110 | 111 | // Base64Decode decodes the given Base64-encoded string 112 | func Base64Decode(encoded string) ([]byte, error) { 113 | return base64.StdEncoding.DecodeString(encoded) 114 | } 115 | -------------------------------------------------------------------------------- /crypto/decryption/pi_decryption_test.go: -------------------------------------------------------------------------------- 1 | package decryption 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestNewPiDecryption(t *testing.T) { 8 | key := make([]byte, 32) 9 | _, err := rand.Read(key) 10 | if err != nil { 11 | t.Fatal(err) 12 | } 13 | pd, err := NewPiDecryption(key) 14 | if err != nil { 15 | t.Errorf("Expected NewPiDecryption to succeed, but got error: %s", err) 16 | } 17 | if pd == nil { 18 | t.Errorf("Expected pd to be non-nil, but got nil") 19 | } 20 | } 21 | 22 | func TestDecrypt(t *testing.T) { 23 | key := make([]byte, 32) 24 | _, err := rand.Read(key) 25 | if err != nil { 26 | t.Fatal(err) 27 | } 28 | pd, err := NewPiDecryption(key) 29 | if err != nil { 30 | t.Fatal(err) 31 | } 32 | ciphertext := []byte("encrypted data") 33 | decrypted, err := pd.Decrypt(ciphertext) 34 | if err != nil { 35 | t.Errorf("Expected Decrypt to succeed, but got error: %s", err) 36 | } 37 | if string(decrypted) != "decrypted data" { 38 | t.Errorf("Expected decrypted text to match original plaintext, but got %s", decrypted) 39 | } 40 | } 41 | 42 | func TestDecryptBase64(t *testing.T) { 43 | key := make([]byte, 32) 44 | _, err := rand.Read(key) 45 | if err != nil { 46 | t.Fatal(err) 47 | } 48 | pd, err := NewPiDecryption(key) 49 | if err != nil { 50 | t.Fatal(err) 51 | } 52 | ciphertext := "VGhlIHN0cmluZyBpcyBzdGF0aWM=" 53 | decrypted, err := pd.DecryptBase64(ciphertext) 54 | if err != nil { 55 | t.Errorf("Expected DecryptBase64 to succeed, but got error: %s", err) 56 | } 57 | if string(decrypted) != "The string is static" { 58 | t.Errorf("Expected decrypted text to match original plaintext, but got %s", decrypted) 59 | } 60 | } 61 | 62 | func TestDecryptWithMAC(t *testing.T) { 63 | key := make([]byte, 32) 64 | _, err := rand.Read(key) 65 | if err != nil { 66 | t.Fatal(err) 67 | } 68 | pd, err := NewPiDecryption(key) 69 | if err != nil { 70 | t.Fatal(err) 71 | } 72 | ciphertext := []byte("encrypted data") 73 | mac := pd.calculateMAC(ciphertext) 74 | decrypted, err := pd.DecryptWithMAC(ciphertext, mac) 75 | if err != nil { 76 | t.Errorf("Expected DecryptWithMAC to succeed, but got error: %s", err) 77 | } 78 | if string(decrypted) != "decrypted data" { 79 | t.Errorf("Expected decrypted text to match original plaintext, but got %s", decrypted) 80 | } 81 | } 82 | 83 | func TestInvalidKeyLength(t *testing.T) { 84 | key := make([]byte, 16) 85 | _, err := NewPiDecryption(key) 86 | if err == nil { 87 | t.Errorf("Expected NewPiDecryption to fail with invalid key length, but got nil error") 88 | } 89 | } 90 | 91 | func TestInvalidCiphertext(t *testing.T) { 92 | key := make([]byte, 32) 93 | _, err := rand.Read(key) 94 | if err != nil { 95 | t.Fatal(err) 96 | } 97 | pd, err := NewPiDecryption(key) 98 | if err != nil { 99 | t.Fatal(err) 100 | } 101 | ciphertext := []byte("invalid ciphertext") 102 | _, err = pd.Decrypt(ciphertext) 103 | if err == nil { 104 | t.Errorf("Expected Decrypt to fail with invalid ciphertext, but got nil error") 105 | } 106 | } 107 | 108 | func TestInvalidMAC(t *testing.T) { 109 | key := make([]byte, 32) 110 | _, err := rand.Read(key) 111 | if err != nil { 112 | t.Fatal(err) 113 | } 114 | pd, err := NewPiDecryption(key) 115 | if err != nil { 116 | t.Fatal(err) 117 | } 118 | ciphertext := []byte("encrypted data") 119 | mac := []byte("invalid mac") 120 | _, err = pd.DecryptWithMAC(ciphertext, mac) 121 | if err == nil { 122 | t.Errorf("Expected DecryptWithMAC to fail with invalid MAC, but got nil error") 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /blockchain/polkadot/protocol/polkadot_protocol.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "context" 5 | "crypto/ecdsa" 6 | "encoding/json" 7 | "fmt" 8 | "math/big" 9 | "strings" 10 | "time" 11 | 12 | "github.com/centrifuge/go-substrate-rpc-client/v4/types" 13 | "github.com/ethereum/go-ethereum/accounts" 14 | "github.com/ethereum/go-ethereum/common" 15 | "github.com/ethereum/go-ethereum/core/types" 16 | "github.com/ethereum/go-ethereum/crypto" 17 | ) 18 | 19 | // PolkadotProtocol represents the Polkadot protocol 20 | type PolkadotProtocol struct { 21 | nodeURL string 22 | client *types.Client 23 | } 24 | 25 | // NewPolkadotProtocol creates a new PolkadotProtocol instance 26 | func NewPolkadotProtocol(nodeURL string) (*PolkadotProtocol, error) { 27 | client, err := types.NewClient(nodeURL) 28 | if err!= nil { 29 | return nil, err 30 | } 31 | return &PolkadotProtocol{nodeURL: nodeURL, client: client}, nil 32 | } 33 | 34 | // GetBlockHash returns the block hash at a given height 35 | func (p *PolkadotProtocol) GetBlockHash(height uint64) (string, error) { 36 | hash, err := p.client.RPC.BlockHash(context.Background(), height) 37 | if err!= nil { 38 | return "", err 39 | } 40 | return hash.Hex(), nil 41 | } 42 | 43 | // GetBlock returns the block at a given hash 44 | func (p *PolkadotProtocol) GetBlock(hash string) (*types.Block, error) { 45 | block, err := p.client.RPC.Block(context.Background(), hash) 46 | if err!= nil { 47 | return nil, err 48 | } 49 | return block, nil 50 | } 51 | 52 | // GetFinalizedHead returns the finalized head of the chain 53 | func (p *PolkadotProtocol) GetFinalizedHead() (*types.Header, error) { 54 | header, err := p.client.RPC.FinalizedHead(context.Background()) 55 | if err!= nil { 56 | return nil, err 57 | } 58 | return header, nil 59 | } 60 | 61 | // GetBestNumber returns the best block number 62 | func (p *PolkadotProtocol) GetBestNumber() (uint64, error) { 63 | number, err := p.client.RPC.BestNumber(context.Background()) 64 | if err!= nil { 65 | return 0, err 66 | } 67 | return number, nil 68 | } 69 | 70 | // GetMetadata returns the metadata of the chain 71 | func (p *PolkadotProtocol) GetMetadata() (*types.Metadata, error) { 72 | metadata, err := p.client.RPC.Metadata(context.Background()) 73 | if err!= nil { 74 | return nil, err 75 | } 76 | return metadata, nil 77 | } 78 | 79 | // GetStorage returns the storage value at a given key 80 | func (p *PolkadotProtocol) GetStorage(key string) (string, error) { 81 | data, err := p.client.RPC.Storage(context.Background(), key) 82 | if err!= nil { 83 | return "", err 84 | } 85 | return data.Hex(), nil 86 | } 87 | 88 | // ExtrinsicSign signs an extrinsic with a given signer 89 | func (p *PolkadotProtocol) ExtrinsicSign(ext *types.Extrinsic, signer *ecdsa.PrivateKey) (*types.Extrinsic, error) { 90 | signedExt, err := ext.Sign(signer) 91 | if err!= nil { 92 | return nil, err 93 | } 94 | return signedExt, nil 95 | } 96 | 97 | // SubmitExtrinsic submits an extrinsic to the network 98 | func (p *PolkadotProtocol) SubmitExtrinsic(ext *types.Extrinsic) (string, error) { 99 | hash, err := p.client.RPC.SubmitExtrinsic(context.Background(), ext) 100 | if err!= nil { 101 | return "", err 102 | } 103 | return hash.Hex(), nil 104 | } 105 | 106 | // QuerySubscribe subscribes to a query 107 | func (p *PolkadotProtocol) QuerySubscribe(query *types.Query) (*types.Subscriber, error) { 108 | subscriber, err := p.client.RPC.QuerySubscribe(context.Background(), query) 109 | if err!= nil { 110 | return nil, err 111 | } 112 | return subscriber, nil 113 | } 114 | -------------------------------------------------------------------------------- /sharding/utils/sharding_utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestGenerateShardID(t *testing.T) { 10 | data := []byte("hello world") 11 | shardID, err := GenerateShardID(data) 12 | assert.NoError(t, err) 13 | assert.Len(t, shardID, ShardIDSize) 14 | } 15 | 16 | func TestShardIDToString(t *testing.T) { 17 | shardID := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} 18 | shardIDStr := ShardIDToString(shardID) 19 | assert.Equal(t, "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", shardIDStr) 20 | } 21 | 22 | func TestStringToShardID(t *testing.T) { 23 | shardIDStr := "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" 24 | shardID, err := StringToShardID(shardIDStr) 25 | assert.NoError(t, err) 26 | assert.Equal(t, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}, shardID) 27 | } 28 | 29 | func TestCalculateShardIndex(t *testing.T) { 30 | shardID := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} 31 | shardCount := 1024 32 | shardIndex, err := CalculateShardIndex(shardID, shardCount) 33 | assert.NoError(t, err) 34 | assert.Equal(t, 123, shardIndex) 35 | } 36 | 37 | func TestSplitDataIntoShards(t *testing.T) { 38 | data := []byte("hello world hello world hello world") 39 | shardSize := 10 40 | shards := SplitDataIntoShards(data, shardSize) 41 | assert.Len(t, shards, 3) 42 | assert.Equal(t, []byte("hello wor"), shards[0]) 43 | assert.Equal(t, []byte("ld hello w"), shards[1]) 44 | assert.Equal(t, []byte("orld"), shards[2]) 45 | } 46 | 47 | func TestMergeShards(t *testing.T) { 48 | shards := [][]byte{ 49 | []byte("hello wor"), 50 | []byte("ld hello w"), 51 | []byte("orld"), 52 | } 53 | data := MergeShards(shards) 54 | assert.Equal(t, []byte("hello world hello world"), data) 55 | } 56 | 57 | func BenchmarkGenerateShardID(b *testing.B) { 58 | data := []byte("hello world") 59 | for i := 0; i < b.N; i++ { 60 | _, err := GenerateShardID(data) 61 | if err!= nil { 62 | b.Errorf("Expected GenerateShardID to succeed, but got error: %s", err) 63 | } 64 | } 65 | } 66 | 67 | func BenchmarkShardIDToString(b *testing.B) { 68 | shardID := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} 69 | for i := 0; i < b.N; i++ { 70 | ShardIDToString(shardID) 71 | } 72 | } 73 | 74 | func BenchmarkStringToShardID(b *testing.B) { 75 | shardIDStr := "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" 76 | for i := 0; i < b.N; i++ { 77 | _, err := StringToShardID(shardIDStr) 78 | if err!= nil { 79 | b.Errorf("Expected StringToShardID to succeed, but got error: %s", err) 80 | } 81 | } 82 | } 83 | 84 | func BenchmarkCalculateShardIndex(b *testing.B) { 85 | shardID := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} 86 | shardCount := 1024 87 | for i := 0; i < b.N; i++ { 88 | _, err := CalculateShardIndex(shardID, shardCount) 89 | if err!= nil { 90 | b.Errorf("Expected CalculateShardIndex to succeed, but got error: %s", err) 91 | } 92 | } 93 | } 94 | 95 | func BenchmarkSplitDataIntoShards(b *testing.B) { 96 | data := []byte("hello world hello world hello world") 97 | shardSize := 10 98 | for i := 0; i < b.N; i++ { 99 | SplitDataIntoShards(data, shardSize) 100 | } 101 | } 102 | 103 | func BenchmarkMergeShards(b *testing.B) { 104 | shards := [][]byte{ 105 | []byte("hello wor"), 106 | []byte("ld hello w"), 107 | []byte("orld"), 108 | } 109 | for i := 0; i < b.N; i++ { 110 | MergeShards(shards) 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /blockchain/pi_network/node/pi_node_test.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/pi-network/pi-node/types" 7 | "github.com/pi-network/pi-node/utils" 8 | ) 9 | 10 | func TestNewPiNode(t *testing.T) { 11 | config := &types.Config{ 12 | Port: 8080, 13 | } 14 | 15 | node, err := NewPiNode(config) 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | 20 | if node.config.Port != 8080 { 21 | t.Errorf("Expected port to be 8080, but got %d", node.config.Port) 22 | } 23 | 24 | if node.privateKey == nil { 25 | t.Errorf("Expected private key to be generated, but got nil") 26 | } 27 | 28 | if node.publicKey == nil { 29 | t.Errorf("Expected public key to be generated, but got nil") 30 | } 31 | 32 | if node.address == "" { 33 | t.Errorf("Expected address to be generated, but got empty string") 34 | } 35 | } 36 | 37 | func TestStartPiNode(t *testing.T) { 38 | config := &types.Config{ 39 | Port: 8080, 40 | } 41 | 42 | node, err := NewPiNode(config) 43 | if err != nil { 44 | t.Fatal(err) 45 | } 46 | 47 | err = node.Start() 48 | if err != nil { 49 | t.Fatal(err) 50 | } 51 | 52 | // Check if node is listening on port 8080 53 | resp, err := http.Get("http://localhost:8080/api/v1/node") 54 | if err != nil { 55 | t.Fatal(err) 56 | } 57 | 58 | defer resp.Body.Close() 59 | 60 | if resp.StatusCode != http.StatusOK { 61 | t.Errorf("Expected status code to be 200, but got %d", resp.StatusCode) 62 | } 63 | } 64 | 65 | func TestStopPiNode(t *testing.T) { 66 | config := &types.Config{ 67 | Port: 8080, 68 | } 69 | 70 | node, err := NewPiNode(config) 71 | if err != nil { 72 | t.Fatal(err) 73 | } 74 | 75 | err = node.Start() 76 | if err != nil { 77 | t.Fatal(err) 78 | } 79 | 80 | err = node.Stop() 81 | if err != nil { 82 | t.Fatal(err) 83 | } 84 | 85 | // Check if node is no longer listening on port 8080 86 | resp, err := http.Get("http://localhost:8080/api/v1/node") 87 | if err == nil { 88 | t.Errorf("Expected error, but got nil") 89 | } 90 | 91 | if resp != nil { 92 | defer resp.Body.Close() 93 | } 94 | } 95 | 96 | func TestHandleNodeRequest(t *testing.T) { 97 | config := &types.Config{ 98 | Port: 8080, 99 | } 100 | 101 | node, err := NewPiNode(config) 102 | if err != nil { 103 | t.Fatal(err) 104 | } 105 | 106 | req, err := http.NewRequest("GET", "/api/v1/node", nil) 107 | if err != nil { 108 | t.Fatal(err) 109 | } 110 | 111 | w := httptest.NewRecorder() 112 | node.handleNodeRequest(w, req) 113 | 114 | if w.Code != http.StatusOK { 115 | t.Errorf("Expected status code to be 200, but got %d", w.Code) 116 | } 117 | 118 | var nodeInfo types.NodeInfo 119 | err = json.Unmarshal(w.Body.Bytes(), &nodeInfo) 120 | if err != nil { 121 | t.Fatal(err) 122 | } 123 | 124 | if nodeInfo.Address != node.address { 125 | t.Errorf("Expected address to be %s, but got %s", node.address, nodeInfo.Address) 126 | } 127 | 128 | if nodeInfo.Port != node.port { 129 | t.Errorf("Expected port to be %d, but got %d", node.port, nodeInfo.Port) 130 | } 131 | } 132 | 133 | func TestHandleTransactionsRequest(t *testing.T) { 134 | config := &types.Config{ 135 | Port: 8080, 136 | } 137 | 138 | node, err := NewPiNode(config) 139 | if err != nil { 140 | t.Fatal(err) 141 | } 142 | 143 | req, err := http.NewRequest("POST", "/api/v1/transactions", nil) 144 | if err != nil { 145 | t.Fatal(err) 146 | } 147 | 148 | w := httptest.NewRecorder() 149 | node.handleTransactionsRequest(w, req) 150 | 151 | if w.Code != http.StatusOK { 152 | t.Errorf("Expected status code to be 200, but got %d", w.Code) 153 | } 154 | 155 | var transactions []*types.Transaction 156 | err = json.Unmarshal(w.Body.Bytes(), &transactions) 157 | if err != nil { 158 | t.Fatal(err) 159 | } 160 | 161 | if len(transactions) != 0 { 162 | t.Errorf("Expected transactions to be empty, but got %d transactions", len(transactions)) 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /blockchain/pi_network/protocol/pi_protocol_test.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/pi-network/pi-node/types" 7 | "github.com/pi-network/pi-node/utils" 8 | ) 9 | 10 | func TestNewPiProtocol(t *testing.T) { 11 | privateKey, err := utils.GeneratePrivateKey() 12 | if err != nil { 13 | t.Fatal(err) 14 | } 15 | 16 | publicKey, err := utils.GeneratePublicKey(privateKey) 17 | if err != nil { 18 | t.Fatal(err) 19 | } 20 | 21 | address, err := utils.GenerateAddress(publicKey) 22 | if err != nil { 23 | t.Fatal(err) 24 | } 25 | 26 | protocol := NewPiProtocol(privateKey, publicKey, address, 8080) 27 | if protocol == nil { 28 | t.Errorf("Expected protocol to be created, but got nil") 29 | } 30 | } 31 | 32 | func TestHandleMessage(t *testing.T) { 33 | privateKey, err := utils.GeneratePrivateKey() 34 | if err != nil { 35 | t.Fatal(err) 36 | } 37 | 38 | publicKey, err := utils.GeneratePublicKey(privateKey) 39 | if err != nil { 40 | t.Fatal(err) 41 | } 42 | 43 | address, err := utils.GenerateAddress(publicKey) 44 | if err != nil { 45 | t.Fatal(err) 46 | } 47 | 48 | protocol := NewPiProtocol(privateKey, publicKey, address, 8080) 49 | 50 | nodeInfoMessage := &types.Message{ 51 | Type: types.MessageTypeNodeInfo, 52 | Data: []byte(`{"address":"localhost:8080","port":8080}`), 53 | } 54 | 55 | err = protocol.HandleMessage(nodeInfoMessage) 56 | if err != nil { 57 | t.Errorf("Expected node info message to be handled, but got error: %s", err) 58 | } 59 | 60 | transactionMessage := &types.Message{ 61 | Type: types.MessageTypeTransaction, 62 | Data: []byte(`{"id":"transaction-id","from":"from-address","to":"to-address","amount":10}`), 63 | } 64 | 65 | err = protocol.HandleMessage(transactionMessage) 66 | if err != nil { 67 | t.Errorf("Expected transaction message to be handled, but got error: %s", err) 68 | } 69 | 70 | blockMessage := &types.Message{ 71 | Type: types.MessageTypeBlock, 72 | Data: []byte(`{"hash":"block-hash","previousBlockHash":"previous-block-hash","transactions":[{"id":"transaction-id","from":"from-address","to":"to-address","amount":10}]}`), 73 | } 74 | 75 | err = protocol.HandleMessage(blockMessage) 76 | if err != nil { 77 | t.Errorf("Expected block message to be handled, but got error: %s", err) 78 | } 79 | } 80 | 81 | func TestCreateBlock(t *testing.T) { 82 | privateKey, err := utils.GeneratePrivateKey() 83 | if err != nil { 84 | t.Fatal(err) 85 | } 86 | 87 | publicKey, err := utils.GeneratePublicKey(privateKey) 88 | if err != nil { 89 | t.Fatal(err) 90 | } 91 | 92 | address, err := utils.GenerateAddress(publicKey) 93 | if err != nil { 94 | t.Fatal(err) 95 | } 96 | 97 | protocol := NewPiProtocol(privateKey, publicKey, address, 8080) 98 | 99 | transaction := &types.Transaction{ 100 | ID: "transaction-id", 101 | From: "from-address", 102 | To: "to-address", 103 | Amount: 10, 104 | } 105 | 106 | protocol.transactionPool[transaction.ID] = transaction 107 | 108 | block, err := protocol.CreateBlock() 109 | if err != nil { 110 | t.Errorf("Expected block to be created, but got error: %s", err) 111 | } 112 | 113 | if block == nil { 114 | t.Errorf("Expected block to be created, but got nil") 115 | } 116 | 117 | if len(block.Transactions) != 1 { 118 | t.Errorf("Expected block to have 1 transaction, but got %d", len(block.Transactions)) 119 | } 120 | } 121 | 122 | func TestGetBlockChain(t *testing.T) { 123 | privateKey, err := utils.GeneratePrivateKey() 124 | if err != nil { 125 | t.Fatal(err) 126 | } 127 | 128 | publicKey, err := utils.GeneratePublicKey(privateKey) 129 | if err != nil { 130 | t.Fatal(err) 131 | } 132 | 133 | address, err := utils.GenerateAddress(publicKey) 134 | if err != nil { 135 | t.Fatal(err) 136 | } 137 | 138 | protocol := NewPiProtocol(privateKey, publicKey, address, 8080) 139 | 140 | blockChain := protocol.GetBlockChain() 141 | if blockChain == nil { 142 | t.Errorf("Expected block chain to be returned, but got nil") 143 | } 144 | 145 | if len(blockChain) != 0 { 146 | t.Errorf("Expected block chain to be empty, but got %d blocks", len(blockChain)) 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /interoperability/utils/interoperability_utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGenerateRandomString(t *testing.T) { 8 | length := 16 9 | result := GenerateRandomString(length) 10 | if len(result)!= length*2 { 11 | t.Errorf("Expected generated string to be %d characters long, but got %d", length*2, len(result)) 12 | } 13 | } 14 | 15 | func TestComputeHMAC(t *testing.T) { 16 | message := []byte("hello") 17 | secretKey := []byte("secret") 18 | result, err := ComputeHMAC(message, secretKey) 19 | if err!= nil { 20 | t.Errorf("Expected ComputeHMAC to succeed, but got error: %s", err) 21 | } 22 | if len(result)!= 32 { 23 | t.Errorf("Expected HMAC to be 32 bytes long, but got %d", len(result)) 24 | } 25 | } 26 | 27 | func TestBase64Encode(t *testing.T) { 28 | data := []byte("hello") 29 | encoded := Base64Encode(data) 30 | if encoded!= "aGVsbG8=" { 31 | t.Errorf("Expected base64-encoded string to be 'aGVsbG8=', but got %s", encoded) 32 | } 33 | } 34 | 35 | func TestBase64Decode(t *testing.T) { 36 | encoded := "aGVsbG8=" 37 | data, err := Base64Decode(encoded) 38 | if err!= nil { 39 | t.Errorf("Expected Base64Decode to succeed, but got error: %s", err) 40 | } 41 | if string(data)!= "hello" { 42 | t.Errorf("Expected decoded string to be 'hello', but got %s", data) 43 | } 44 | } 45 | 46 | func TestJSONMarshal(t *testing.T) { 47 | structure := struct { 48 | Foo string `json:"foo"` 49 | Bar int `json:"bar"` 50 | }{Foo: "hello", Bar: 42} 51 | data, err := JSONMarshal(structure) 52 | if err!= nil { 53 | t.Errorf("Expected JSONMarshal to succeed, but got error: %s", err) 54 | } 55 | if string(data)!= `{"foo":"hello","bar":42}` { 56 | t.Errorf("Expected marshaled JSON to be '{\"foo\":\"hello\",\"bar\":42}', but got %s", data) 57 | } 58 | } 59 | 60 | func TestJSONUnmarshal(t *testing.T) { 61 | data := []byte(`{"foo":"hello","bar":42}`) 62 | structure := struct { 63 | Foo string `json:"foo"` 64 | Bar int `json:"bar"` 65 | }{} 66 | err := JSONUnmarshal(data, &structure) 67 | if err!= nil { 68 | t.Errorf("Expected JSONUnmarshal to succeed, but got error: %s", err) 69 | } 70 | if structure.Foo!= "hello" { 71 | t.Errorf("Expected unmarshaled foo to be 'hello', but got %s", structure.Foo) 72 | } 73 | if structure.Bar!= 42 { 74 | t.Errorf("Expected unmarshaled bar to be 42, but got %d", structure.Bar) 75 | } 76 | } 77 | 78 | func TestHTTPGet(t *testing.T) { 79 | url := "https://example.com" 80 | data, err := HTTPGet(url) 81 | if err!= nil { 82 | t.Errorf("Expected HTTPGet to succeed, but got error: %s", err) 83 | } 84 | if len(data) == 0 { 85 | t.Errorf("Expected HTTP response to be non-empty") 86 | } 87 | } 88 | 89 | func TestURLParse(t *testing.T) { 90 | urlString := "https://example.com/path?query=string" 91 | url, err := URLParse(urlString) 92 | if err!= nil { 93 | t.Errorf("Expected URLParse to succeed, but got error: %s", err) 94 | } 95 | if url.Scheme!= "https" { 96 | t.Errorf("Expected URL scheme to be 'https', but got %s", url.Scheme) 97 | } 98 | if url.Host!= "example.com" { 99 | t.Errorf("Expected URL host to be 'example.com', but got %s", url.Host) 100 | } 101 | if url.Path!= "/path" { 102 | t.Errorf("Expected URL path to be '/path', but got %s", url.Path) 103 | } 104 | if url.Query().Get("query")!= "string" { 105 | t.Errorf("Expected URL query to be 'query=string', but got %s", url.Query()) 106 | } 107 | } 108 | 109 | func TestURLQueryEscape(t *testing.T) { 110 | query := "hello world" 111 | escaped := URLQueryEscape(query) 112 | if escaped!= "hello+world" { 113 | t.Errorf("Expected URL-escaped query to be 'hello+world', but got %s", escaped) 114 | } 115 | } 116 | 117 | func TestErrorString(t *testing.T) { 118 | err := errors.New("test error") 119 | if ErrorString(err)!= "test error" { 120 | t.Errorf("Expected ErrorString to return 'test error', but got %s", ErrorString(err)) 121 | } 122 | } 123 | 124 | func TestIsError(t *testing.T) { 125 | err := errors.New("test error") 126 | if!IsError(err) { 127 | t.Errorf("Expected IsError to return true, but got false") 128 | } 129 | if IsError(nil) { 130 | t.Errorf("Expected IsError to return false, but got true") 131 | } 132 | } 133 | 134 | -------------------------------------------------------------------------------- /blockchain/pi_network/protocol/pi_protocol.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "encoding/json" 6 | "fmt" 7 | "log" 8 | "math/big" 9 | "sync" 10 | "time" 11 | 12 | "github.com/pi-network/pi-node/types" 13 | "github.com/pi-network/pi-node/utils" 14 | ) 15 | 16 | // PiProtocol represents the Pi protocol 17 | type PiProtocol struct { 18 | // Node private key 19 | privateKey *ecdsa.PrivateKey 20 | 21 | // Node public key 22 | publicKey *ecdsa.PublicKey 23 | 24 | // Node address 25 | address string 26 | 27 | // Node port 28 | port int 29 | 30 | // Protocol mutex 31 | mutex sync.Mutex 32 | 33 | // Transaction pool 34 | transactionPool map[string]*types.Transaction 35 | 36 | // Block chain 37 | blockChain []*types.Block 38 | } 39 | 40 | // NewPiProtocol creates a new Pi protocol 41 | func NewPiProtocol(privateKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey, address string, port int) *PiProtocol { 42 | protocol := &PiProtocol{ 43 | privateKey: privateKey, 44 | publicKey: publicKey, 45 | address: address, 46 | port: port, 47 | transactionPool: make(map[string]*types.Transaction), 48 | blockChain: make([]*types.Block, 0), 49 | } 50 | 51 | return protocol 52 | } 53 | 54 | // HandleMessage handles a message 55 | func (p *PiProtocol) HandleMessage(message *types.Message) error { 56 | p.mutex.Lock() 57 | defer p.mutex.Unlock() 58 | 59 | switch message.Type { 60 | case types.MessageTypeNodeInfo: 61 | return p.handleNodeInfoMessage(message) 62 | case types.MessageTypeTransaction: 63 | return p.handleTransactionMessage(message) 64 | case types.MessageTypeBlock: 65 | return p.handleBlockMessage(message) 66 | default: 67 | return fmt.Errorf("unknown message type: %s", message.Type) 68 | } 69 | } 70 | 71 | func (p *PiProtocol) handleNodeInfoMessage(message *types.Message) error { 72 | log.Println("Received node info message") 73 | 74 | nodeInfo := &types.NodeInfo{} 75 | err := json.Unmarshal(message.Data, nodeInfo) 76 | if err != nil { 77 | return err 78 | } 79 | 80 | log.Println("Node info:", nodeInfo) 81 | 82 | return nil 83 | } 84 | 85 | func (p *PiProtocol) handleTransactionMessage(message *types.Message) error { 86 | log.Println("Received transaction message") 87 | 88 | transaction := &types.Transaction{} 89 | err := json.Unmarshal(message.Data, transaction) 90 | if err != nil { 91 | return err 92 | } 93 | 94 | log.Println("Transaction:", transaction) 95 | 96 | p.transactionPool[transaction.ID] = transaction 97 | 98 | return nil 99 | } 100 | 101 | func (p *PiProtocol) handleBlockMessage(message *types.Message) error { 102 | log.Println("Received block message") 103 | 104 | block := &types.Block{} 105 | err := json.Unmarshal(message.Data, block) 106 | if err != nil { 107 | return err 108 | } 109 | 110 | log.Println("Block:", block) 111 | 112 | p.blockChain = append(p.blockChain, block) 113 | 114 | return nil 115 | } 116 | 117 | // CreateBlock creates a new block 118 | func (p *PiProtocol) CreateBlock() (*types.Block, error) { 119 | p.mutex.Lock() 120 | defer p.mutex.Unlock() 121 | 122 | block := &types.Block{ 123 | Timestamp: time.Now().Unix(), 124 | Transactions: make([]*types.Transaction, 0), 125 | PreviousBlockHash: p.getPreviousBlockHash(), 126 | } 127 | 128 | for _, transaction := range p.transactionPool { 129 | block.Transactions = append(block.Transactions, transaction) 130 | delete(p.transactionPool, transaction.ID) 131 | } 132 | 133 | blockHash, err := p.calculateBlockHash(block) 134 | if err != nil { 135 | return nil, err 136 | } 137 | 138 | block.Hash = blockHash 139 | 140 | return block, nil 141 | } 142 | 143 | func (p *PiProtocol) getPreviousBlockHash() string { 144 | if len(p.blockChain) == 0 { 145 | return "" 146 | } 147 | 148 | return p.blockChain[len(p.blockChain)-1].Hash 149 | } 150 | 151 | func (p *PiProtocol) calculateBlockHash(block *types.Block) (string, error) { 152 | blockBytes, err := json.Marshal(block) 153 | if err != nil { 154 | return "", err 155 | } 156 | 157 | hash, err := utils.GenerateHash(blockBytes) 158 | if err != nil { 159 | return "", err 160 | } 161 | 162 | return hash, nil 163 | } 164 | 165 | // GetBlockChain returns the block chain 166 | func (p *PiProtocol) GetBlockChain() []*types.Block { 167 | p.mutex.Lock() 168 | defer p.mutex.Unlock() 169 | 170 | return p.blockChain 171 | } 172 | -------------------------------------------------------------------------------- /blockchain/polkadot/utils/polkadot_utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "encoding/hex" 6 | "encoding/json" 7 | "fmt" 8 | "math/big" 9 | "strings" 10 | "testing" 11 | "time" 12 | 13 | "github.com/centrifuge/go-substrate-rpc-client/v4/types" 14 | "github.com/ethereum/go-ethereum/accounts" 15 | "github.com/ethereum/go-ethereum/common" 16 | "github.com/ethereum/go-ethereum/core/types" 17 | "github.com/ethereum/go-ethereum/crypto" 18 | ) 19 | 20 | func TestHexToBytes(t *testing.T) { 21 | hexString := "0x1234567890abcdef" 22 | bytes, err := HexToBytes(hexString) 23 | if err!= nil { 24 | t.Fatal(err) 25 | } 26 | fmt.Printf("Bytes: %x\n", bytes) 27 | } 28 | 29 | func TestBytesToHex(t *testing.T) { 30 | bytes := []byte{0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef} 31 | hexString := BytesToHex(bytes) 32 | fmt.Printf("Hex string: %s\n", hexString) 33 | } 34 | 35 | func TestU256ToBigInt(t *testing.T) { 36 | u256 := types.U256{0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef} 37 | bigInt := U256ToBigInt(u256) 38 | fmt.Printf("Big int: %s\n", bigInt) 39 | } 40 | 41 | func TestBigIntToU256(t *testing.T) { 42 | bigInt := big.NewInt(0x1234567890abcdef) 43 | u256 := BigIntToU256(bigInt) 44 | fmt.Printf("U256: %x\n", u256) 45 | } 46 | 47 | func TestSignMessage(t *testing.T) { 48 | privateKey, err := crypto.GenerateKey() 49 | if err!= nil { 50 | t.Fatal(err) 51 | } 52 | message := []byte("Hello, World!") 53 | signature, err := SignMessage(privateKey, message) 54 | if err!= nil { 55 | t.Fatal(err) 56 | } 57 | fmt.Printf("Signature: %x\n", signature) 58 | } 59 | 60 | func TestVerifySignature(t *testing.T) { 61 | privateKey, err := crypto.GenerateKey() 62 | if err!= nil { 63 | t.Fatal(err) 64 | } 65 | publicKey := &privateKey.PublicKey 66 | message := []byte("Hello, World!") 67 | signature, err := SignMessage(privateKey, message) 68 | if err!= nil { 69 | t.Fatal(err) 70 | } 71 | valid := VerifySignature(publicKey, message, signature) 72 | if!valid { 73 | t.Fatal("Invalid signature") 74 | } 75 | fmt.Println("Signature is valid") 76 | } 77 | 78 | func TestGenerateKey(t *testing.T) { 79 | privateKey, publicKey, err := GenerateKey() 80 | if err!= nil { 81 | t.Fatal(err) 82 | } 83 | fmt.Printf("Private key: %x\n", privateKey.D.Bytes()) 84 | fmt.Printf("Public key: %x\n", publicKey.X.Bytes()) 85 | } 86 | 87 | func TestGetAccountAddressFromPrivateKey(t *testing.T) { 88 | privateKey, err := crypto.GenerateKey() 89 | if err!= nil { 90 | t.Fatal(err) 91 | } 92 | address := GetAccountAddressFromPrivateKey(privateKey) 93 | fmt.Printf("Account address: %s\n", address.Hex()) 94 | } 95 | 96 | func TestGetAccountAddressFromPublicKey(t *testing.T) { 97 | privateKey, err := crypto.GenerateKey() 98 | if err!= nil { 99 | t.Fatal(err) 100 | } 101 | publicKey := &privateKey.PublicKey 102 | address := GetAccountAddressFromPublicKey(publicKey) 103 | fmt.Printf("Account address: %s\n", address.Hex()) 104 | } 105 | 106 | func TestEncodeExtrinsic(t *testing.T) { 107 | ext := &types.Extrinsic{ 108 | Call: &types.Call{ 109 | Module: "balances", 110 | Func: "transfer", 111 | Args: []types.Arg{ 112 | types.NewArg("amount", types.NewU128(100)), 113 | types.NewArg("dest", types.NewAccountId("0x1234567890abcdef")), 114 | }, 115 | }, 116 | } 117 | data, err := EncodeExtrinsic(ext) 118 | if err!= nil { 119 | t.Fatal(err) 120 | } 121 | fmt.Printf("Encoded extrinsic: %s\n", data) 122 | } 123 | 124 | func TestDecodeExtrinsic(t *testing.T) { 125 | data := []byte(`{"call":{"module":"balances","func":"transfer","args":[{"name":"amount","value":"100"},{"name":"dest","value":"0x1234567890abcdef"}]}}`) 126 | ext, err := DecodeExtrinsic(data) 127 | if err!= nil { 128 | t.Fatal(err) 129 | } 130 | fmt.Printf("Decoded extrinsic: %+v\n", ext) 131 | } 132 | 133 | func TestEncodeBlock(t *testing.T) { 134 | block := &types.Block{ 135 | Header: &types.Header{ 136 | Number: 100, 137 | Hash: types.NewHash("0x1234567890abcdef"), 138 | }, 139 | } 140 | data, err := EncodeBlock(block) 141 | if err!= nil { 142 | t.Fatal(err) 143 | } 144 | fmt.Printf("Encoded block: %s\n", data) 145 | } 146 | 147 | func TestDecodeBlock(t *testing.T) { 148 | data := []byte(`{"header":{"number":100,"hash":"0x1234567890abcdef"}}`) 149 | block, err := DecodeBlock(data) 150 | if err!= nil { 151 | t.Fatal(err) 152 | } 153 | fmt.Printf("Decoded block: %+v\n", block) 154 | } 155 | -------------------------------------------------------------------------------- /crypto/utils/crypto_utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGenerateRandomBytes(t *testing.T) { 8 | b, err := GenerateRandomBytes(32) 9 | if err != nil { 10 | t.Errorf("Expected GenerateRandomBytes to succeed, but got error: %s", err) 11 | } 12 | if len(b) != 32 { 13 | t.Errorf("Expected GenerateRandomBytes to return 32 bytes, but got %d", len(b)) 14 | } 15 | } 16 | 17 | func TestHashSHA256(t *testing.T) { 18 | data := []byte("hello world") 19 | hash, err := HashSHA256(data) 20 | if err != nil { 21 | t.Errorf("Expected HashSHA256 to succeed, but got error: %s", err) 22 | } 23 | if len(hash) != 32 { 24 | t.Errorf("Expected HashSHA256 to return 32 bytes, but got %d", len(hash)) 25 | } 26 | } 27 | 28 | func TestEncryptAES(t *testing.T) { 29 | key := make([]byte, 32) 30 | _, err := rand.Read(key) 31 | if err!= nil { 32 | t.Fatal(err) 33 | } 34 | plaintext := []byte("hello world") 35 | ciphertext, err := EncryptAES(plaintext, key) 36 | if err!= nil { 37 | t.Errorf("Expected EncryptAES to succeed, but got error: %s", err) 38 | } 39 | if len(ciphertext) < len(plaintext) { 40 | t.Errorf("Expected ciphertext to be at least as long as plaintext") 41 | } 42 | } 43 | 44 | func TestDecryptAES(t *testing.T) { 45 | key := make([]byte, 32) 46 | _, err := rand.Read(key) 47 | if err!= nil { 48 | t.Fatal(err) 49 | } 50 | plaintext := []byte("hello world") 51 | ciphertext, err := EncryptAES(plaintext, key) 52 | if err!= nil { 53 | t.Errorf("Expected EncryptAES to succeed, but got error: %s", err) 54 | } 55 | decrypted, err := DecryptAES(ciphertext, key) 56 | if err!= nil { 57 | t.Errorf("Expected DecryptAES to succeed, but got error: %s", err) 58 | } 59 | if string(decrypted)!= string(plaintext) { 60 | t.Errorf("Expected decrypted text to match original plaintext, but got %s", decrypted) 61 | } 62 | } 63 | 64 | func TestSignRSA(t *testing.T) { 65 | privateKey, err := rsa.GenerateKey(rand.Reader, 2048) 66 | if err!= nil { 67 | t.Fatal(err) 68 | } 69 | data := []byte("hello world") 70 | signature, err := SignRSA(data, privateKey) 71 | if err!= nil { 72 | t.Errorf("Expected SignRSA to succeed, but got error: %s", err) 73 | } 74 | if len(signature) == 0 { 75 | t.Errorf("Expected signature to be non-empty") 76 | } 77 | } 78 | 79 | func TestVerifyRSA(t *testing.T) { 80 | privateKey, err := rsa.GenerateKey(rand.Reader, 2048) 81 | if err!= nil { 82 | t.Fatal(err) 83 | } 84 | publicKey := &privateKey.PublicKey 85 | data := []byte("hello world") 86 | signature, err := SignRSA(data, privateKey) 87 | if err!= nil { 88 | t.Errorf("Expected SignRSA to succeed, but got error: %s", err) 89 | } 90 | err = VerifyRSA(data, signature, publicKey) 91 | if err!= nil { 92 | t.Errorf("Expected VerifyRSA to succeed, but got error: %s", err) 93 | } 94 | } 95 | 96 | func TestGenerateHMAC(t *testing.T) { 97 | key := make([]byte, 32) 98 | _, err := rand.Read(key) 99 | if err!= nil { 100 | t.Fatal(err) 101 | } 102 | data := []byte("hello world") 103 | hmac, err := GenerateHMAC(data, key) 104 | if err!= nil { 105 | t.Errorf("Expected GenerateHMAC to succeed, but got error: %s", err) 106 | } 107 | if len(hmac) == 0 { 108 | t.Errorf("Expected HMAC to be non-empty") 109 | } 110 | } 111 | 112 | func TestVerifyHMAC(t *testing.T) { 113 | key := make([]byte, 32) 114 | _, err := rand.Read(key) 115 | if err!= nil { 116 | t.Fatal(err) 117 | } 118 | data := []byte("hello world") 119 | hmac, err := GenerateHMAC(data, key) 120 | if err!= nil { 121 | t.Errorf("Expected GenerateHMAC to succeed, but got error: %s", err) 122 | } 123 | err = VerifyHMAC(data, hmac, key) 124 | if err!= nil { 125 | t.Errorf("Expected VerifyHMAC to succeed, but got error: %s", err) 126 | } 127 | } 128 | 129 | func TestBase64Encode(t *testing.T) { 130 | data := []byte("hello world") 131 | encoded, err := Base64Encode(data) 132 | if err!= nil { 133 | t.Errorf("Expected Base64Encode to succeed, but got error: %s", err) 134 | } 135 | if len(encoded) == 0 { 136 | t.Errorf("Expected encoded string to be non-empty") 137 | } 138 | } 139 | 140 | func TestBase64Decode(t *testing.T) { 141 | encoded := "SGVsbG8gd29ybGQ=" 142 | data, err := Base64Decode(encoded) 143 | if err!= nil { 144 | t.Errorf("Expected Base64Decode to succeed, but got error: %s", err) 145 | } 146 | if string(data)!= "hello world" { 147 | t.Errorf("Expected decoded data to match original data, but got %s", data) 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /network/protocol/pi_protocol_test.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "context" 5 | "crypto/ecdsa" 6 | "testing" 7 | 8 | "github.com/libp2p/go-libp2p-core/network" 9 | "github.com/libp2p/go-libp2p-core/peer" 10 | "github.com/multiformats/go-multibase" 11 | ) 12 | 13 | func TestNewPiProtocol(t *testing.T) { 14 | privateKey, _, err := GenerateKeyPair() 15 | if err!= nil { 16 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 17 | } 18 | piProtocol, err := NewPiProtocol(privateKey) 19 | if err!= nil { 20 | t.Errorf("Expected NewPiProtocol to succeed, but got error: %s", err) 21 | } 22 | if piProtocol.ID == nil { 23 | t.Errorf("Expected piProtocol.ID to be non-nil") 24 | } 25 | } 26 | 27 | func TestHandleStream(t *testing.T) { 28 | privateKey, _, err := GenerateKeyPair() 29 | if err!= nil { 30 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 31 | } 32 | piProtocol, err := NewPiProtocol(privateKey) 33 | if err!= nil { 34 | t.Errorf("Expected NewPiProtocol to succeed, but got error: %s", err) 35 | } 36 | stream, err := piProtocol.Host().NewStream(context.Background(), piProtocol.ID, ProtocolID) 37 | if err!= nil { 38 | t.Errorf("Expected NewStream to succeed, but got error: %s", err) 39 | } 40 | go piProtocol.HandleStream(stream) 41 | time.Sleep(100 * time.Millisecond) 42 | // Verify that the stream was handled correctly... 43 | } 44 | 45 | func TestSendMessage(t *testing.T) { 46 | privateKey, _, err := GenerateKeyPair() 47 | if err!= nil { 48 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 49 | } 50 | piProtocol, err := NewPiProtocol(privateKey) 51 | if err!= nil { 52 | t.Errorf("Expected NewPiProtocol to succeed, but got error: %s", err) 53 | } 54 | peerID, err := peer.IDFromPrivateKey(privateKey) 55 | if err!= nil { 56 | t.Errorf("Expected peer.IDFromPrivateKey to succeed, but got error: %s", err) 57 | } 58 | msg := []byte("Hello, world!") 59 | err = piProtocol.SendMessage(context.Background(), peerID, msg) 60 | if err!= nil { 61 | t.Errorf("Expected SendMessage to succeed, but got error: %s", err) 62 | } 63 | // Verify that the message was sent correctly... 64 | } 65 | 66 | func TestProcessMessage(t *testing.T) { 67 | privateKey, _, err := GenerateKeyPair() 68 | if err!= nil { 69 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 70 | } 71 | piProtocol, err := NewPiProtocol(privateKey) 72 | if err!= nil { 73 | t.Errorf("Expected NewPiProtocol to succeed, but got error: %s", err) 74 | } 75 | msg := []byte(`{"type": "hello", "data": "Hello, world!"}`) 76 | piProtocol.processMessage(msg) 77 | // Verify that the message was processed correctly... 78 | } 79 | 80 | func TestReadMessage(t *testing.T) { 81 | privateKey, _, err := GenerateKeyPair() 82 | if err!= nil { 83 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 84 | } 85 | piProtocol, err := NewPiProtocol(privateKey) 86 | if err!= nil { 87 | t.Errorf("Expected NewPiProtocol to succeed, but got error: %s", err) 88 | } 89 | stream, err := piProtocol.Host().NewStream(context.Background(), piProtocol.ID, ProtocolID) 90 | if err!= nil { 91 | t.Errorf("Expected NewStream to succeed, but got error: %s", err) 92 | } 93 | msg := []byte("Hello, world!") 94 | err = writeMessage(stream, msg) 95 | if err!= nil { 96 | t.Errorf("Expected writeMessage to succeed, but got error: %s", err) 97 | } 98 | readMsg, err := readMessage(stream) 99 | if err!= nil { 100 | t.Errorf("Expected readMessage to succeed, but got error: %s", err) 101 | } 102 | if!bytes.Equal(readMsg, msg) { 103 | t.Errorf("Expected read message to match written message") 104 | } 105 | } 106 | 107 | func TestWriteMessage(t *testing.T) { 108 | privateKey, _, err := GenerateKeyPair() 109 | if err!= nil { 110 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 111 | } 112 | piProtocol, err := NewPiProtocol(privateKey) 113 | if err!= nil { 114 | t.Errorf("Expected NewPiProtocol to succeed, but got error: %s", err) 115 | } 116 | stream, err := piProtocol.Host().NewStream(context.Background(), piProtocol.ID, ProtocolID) 117 | if err!= nil { 118 | t.Errorf("Expected NewStream to succeed, but got error: %s", err) 119 | } 120 | msg := []byte("Hello, world!") 121 | err = writeMessage(stream, msg) 122 | if err!= nil { 123 | t.Errorf("Expected writeMessage to succeed, but got error: %s", err) 124 | } 125 | // Verify that the message was written correctly... 126 | } 127 | -------------------------------------------------------------------------------- /consensus/algorithm/pi_consensus.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/sha256" 6 | "encoding/hex" 7 | "fmt" 8 | "math/big" 9 | "sync" 10 | "time" 11 | 12 | "github.com/pi-network/pi/types" 13 | ) 14 | 15 | // PiConsensus is the interface for the Pi consensus algorithm 16 | type PiConsensus interface { 17 | Initialize() error 18 | Start() error 19 | Stop() error 20 | VerifyBlock(*types.Block) (bool, error) 21 | VerifyTransaction(*types.Transaction) (bool, error) 22 | } 23 | 24 | // piConsensus is the implementation of the Pi consensus algorithm 25 | type piConsensus struct { 26 | privateKey *ecdsa.PrivateKey 27 | publicKey *ecdsa.PublicKey 28 | address string 29 | chain []*types.Block 30 | transactionPool map[string]*types.Transaction 31 | mu sync.RWMutex 32 | } 33 | 34 | // NewPiConsensus creates a new instance of the Pi consensus algorithm 35 | func NewPiConsensus(privateKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey, address string) PiConsensus { 36 | return &piConsensus{ 37 | privateKey: privateKey, 38 | publicKey: publicKey, 39 | address: address, 40 | chain: make([]*types.Block, 0), 41 | transactionPool: make(map[string]*types.Transaction), 42 | } 43 | } 44 | 45 | // Initialize initializes the Pi consensus algorithm 46 | func (pc *piConsensus) Initialize() error { 47 | // Initialize the chain with the genesis block 48 | genesisBlock := &types.Block{ 49 | Hash: "genesis-block", 50 | PreviousHash: "", 51 | Transactions: make([]*types.Transaction, 0), 52 | Timestamp: time.Now().Unix(), 53 | } 54 | pc.chain = append(pc.chain, genesisBlock) 55 | return nil 56 | } 57 | 58 | // Start starts the Pi consensus algorithm 59 | func (pc *piConsensus) Start() error { 60 | // Start the consensus loop 61 | go pc.consensusLoop() 62 | return nil 63 | } 64 | 65 | // Stop stops the Pi consensus algorithm 66 | func (pc *piConsensus) Stop() error { 67 | // Stop the consensus loop 68 | return nil 69 | } 70 | 71 | // VerifyBlock verifies a block 72 | func (pc *piConsensus) VerifyBlock(block *types.Block) (bool, error) { 73 | // Verify the block hash 74 | hash, err := pc.calculateBlockHash(block) 75 | if err != nil { 76 | return false, err 77 | } 78 | if hash != block.Hash { 79 | return false, fmt.Errorf("invalid block hash") 80 | } 81 | 82 | // Verify the block transactions 83 | for _, transaction := range block.Transactions { 84 | valid, err := pc.VerifyTransaction(transaction) 85 | if err != nil { 86 | return false, err 87 | } 88 | if !valid { 89 | return false, fmt.Errorf("invalid transaction") 90 | } 91 | } 92 | 93 | return true, nil 94 | } 95 | 96 | // VerifyTransaction verifies a transaction 97 | func (pc *piConsensus) VerifyTransaction(transaction *types.Transaction) (bool, error) { 98 | // Verify the transaction hash 99 | hash, err := pc.calculateTransactionHash(transaction) 100 | if err != nil { 101 | return false, err 102 | } 103 | if hash != transaction.Hash { 104 | return false, fmt.Errorf("invalid transaction hash") 105 | } 106 | 107 | // Verify the transaction signature 108 | signatureValid, err := pc.verifyTransactionSignature(transaction) 109 | if err != nil { 110 | return false, err 111 | } 112 | if !signatureValid { 113 | return false, fmt.Errorf("invalid transaction signature") 114 | } 115 | 116 | return true, nil 117 | } 118 | 119 | func (pc *piConsensus) consensusLoop() { 120 | for { 121 | // Select a random transaction from the transaction pool 122 | transaction := pc.selectRandomTransaction() 123 | if transaction == nil { 124 | continue 125 | } 126 | 127 | // Create a new block with the transaction 128 | block := pc.createBlock(transaction) 129 | 130 | // Broadcast the block to the network 131 | pc.broadcastBlock(block) 132 | 133 | // Add the block to the chain 134 | pc.addBlockToChain(block) 135 | } 136 | } 137 | 138 | func (pc *piConsensus) calculateBlockHash(block *types.Block) (string, error) { 139 | hash := sha256.Sum256([]byte(block.Hash + block.PreviousHash + block.Timestamp)) 140 | return hex.EncodeToString(hash[:]), nil 141 | } 142 | 143 | func (pc *piConsensus) calculateTransactionHash(transaction *types.Transaction) (string, error) { 144 | hash := sha256.Sum256([]byte(transaction.ID + transaction.From + transaction.To + fmt.Sprintf("%d", transaction.Amount))) 145 | return hex.EncodeToString(hash[:]), nil 146 | } 147 | 148 | func (pc *piConsensus) verifyTransactionSignature(transaction *types.Transaction) (bool, error) { 149 | signature, err := hex.DecodeString(transaction.Signature) 150 | if err != nil { 151 | return false, err 152 | } 153 | r := big.NewInt(0).SetBytes(signature[:len(signature)/2]) 154 | s := big.NewInt(0).SetBytes(signature[len(signature)/2:]) 155 | if ecd 156 | -------------------------------------------------------------------------------- /consensus/algorithm/pi_consensus_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/pi-network/pi/types" 8 | ) 9 | 10 | func TestPiConsensus_Initialize(t *testing.T) { 11 | privateKey, err := utils.GeneratePrivateKey() 12 | if err != nil { 13 | t.Fatal(err) 14 | } 15 | publicKey, err := utils.GeneratePublicKey(privateKey) 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | address, err := utils.GenerateAddress(publicKey) 20 | if err != nil { 21 | t.Fatal(err) 22 | } 23 | 24 | pc := NewPiConsensus(privateKey, publicKey, address) 25 | err = pc.Initialize() 26 | if err != nil { 27 | t.Errorf("Expected Initialize to succeed, but got error: %s", err) 28 | } 29 | } 30 | 31 | func TestPiConsensus_Start(t *testing.T) { 32 | privateKey, err := utils.GeneratePrivateKey() 33 | if err != nil { 34 | t.Fatal(err) 35 | } 36 | publicKey, err := utils.GeneratePublicKey(privateKey) 37 | if err != nil { 38 | t.Fatal(err) 39 | } 40 | address, err := utils.GenerateAddress(publicKey) 41 | if err != nil { 42 | t.Fatal(err) 43 | } 44 | 45 | pc := NewPiConsensus(privateKey, publicKey, address) 46 | err = pc.Initialize() 47 | if err != nil { 48 | t.Fatal(err) 49 | } 50 | err = pc.Start() 51 | if err != nil { 52 | t.Errorf("Expected Start to succeed, but got error: %s", err) 53 | } 54 | } 55 | 56 | func TestPiConsensus_Stop(t *testing.T) { 57 | privateKey, err := utils.GeneratePrivateKey() 58 | if err != nil { 59 | t.Fatal(err) 60 | } 61 | publicKey, err := utils.GeneratePublicKey(privateKey) 62 | if err != nil { 63 | t.Fatal(err) 64 | } 65 | address, err := utils.GenerateAddress(publicKey) 66 | if err != nil { 67 | t.Fatal(err) 68 | } 69 | 70 | pc := NewPiConsensus(privateKey, publicKey, address) 71 | err = pc.Initialize() 72 | if err != nil { 73 | t.Fatal(err) 74 | } 75 | err = pc.Start() 76 | if err != nil { 77 | t.Fatal(err) 78 | } 79 | err = pc.Stop() 80 | if err != nil { 81 | t.Errorf("Expected Stop to succeed, but got error: %s", err) 82 | } 83 | } 84 | 85 | func TestPiConsensus_VerifyBlock(t *testing.T) { 86 | privateKey, err := utils.GeneratePrivateKey() 87 | if err!= nil { 88 | t.Fatal(err) 89 | } 90 | publicKey, err := utils.GeneratePublicKey(privateKey) 91 | if err!= nil { 92 | t.Fatal(err) 93 | } 94 | address, err := utils.GenerateAddress(publicKey) 95 | if err!= nil { 96 | t.Fatal(err) 97 | } 98 | 99 | pc := NewPiConsensus(privateKey, publicKey, address) 100 | err = pc.Initialize() 101 | if err!= nil { 102 | t.Fatal(err) 103 | } 104 | 105 | block := &types.Block{ 106 | Hash: "block-hash", 107 | PreviousHash: "previous-block-hash", 108 | Transactions: []*types.Transaction{ 109 | { 110 | ID: "transaction-id", 111 | From: "from-address", 112 | To: "to-address", 113 | Amount: 10, 114 | Signature: "signature", 115 | }, 116 | }, 117 | Timestamp: time.Now().Unix(), 118 | } 119 | 120 | valid, err := pc.VerifyBlock(block) 121 | if err!= nil { 122 | t.Errorf("Expected VerifyBlock to succeed, but got error: %s", err) 123 | } 124 | if!valid { 125 | t.Errorf("Expected block to be valid, but got invalid") 126 | } 127 | } 128 | 129 | func TestPiConsensus_VerifyTransaction(t *testing.T) { 130 | privateKey, err := utils.GeneratePrivateKey() 131 | if err!= nil { 132 | t.Fatal(err) 133 | } 134 | publicKey, err := utils.GeneratePublicKey(privateKey) 135 | if err!= nil { 136 | t.Fatal(err) 137 | } 138 | address, err := utils.GenerateAddress(publicKey) 139 | if err!= nil { 140 | t.Fatal(err) 141 | } 142 | 143 | pc := NewPiConsensus(privateKey, publicKey, address) 144 | err = pc.Initialize() 145 | if err!= nil { 146 | t.Fatal(err) 147 | } 148 | 149 | transaction := &types.Transaction{ 150 | ID: "transaction-id", 151 | From: "from-address", 152 | To: "to-address", 153 | Amount: 10, 154 | Signature: "signature", 155 | } 156 | 157 | valid, err := pc.VerifyTransaction(transaction) 158 | if err!= nil { 159 | t.Errorf("Expected VerifyTransaction to succeed, but got error: %s", err) 160 | } 161 | if!valid { 162 | t.Errorf("Expected transaction to be valid, but got invalid") 163 | } 164 | } 165 | 166 | func TestPiConsensus_consensusLoop(t *testing.T) { 167 | privateKey, err := utils.GeneratePrivateKey() 168 | if err!= nil { 169 | t.Fatal(err) 170 | } 171 | publicKey, err := utils.GeneratePublicKey(privateKey) 172 | if err!= nil { 173 | t.Fatal(err) 174 | } 175 | address, err := utils.GenerateAddress(publicKey) 176 | if err!= nil { 177 | t.Fatal(err) 178 | } 179 | 180 | pc := NewPiConsensus(privateKey, publicKey, address) 181 | err = pc.Initialize() 182 | if err!= nil { 183 | t.Fatal(err) 184 | } 185 | err = pc.Start() 186 | if err!= nil { 187 | t.Fatal(err) 188 | } 189 | 190 | // Wait for the consensus loop to run for a few seconds 191 | time.Sleep(5 * time.Second) 192 | 193 | // Stop the consensus loop 194 | err = pc.Stop() 195 | if err!= nil { 196 | t.Errorf("Expected Stop to succeed, but got error: %s", err) 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /blockchain/polkadot/node/polkadot_node_test.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "testing" 5 | "github.com/centrifuge/go-substrate-rpc-client/v4/types" 6 | "github.com/centrifuge/go-substrate-rpc-client/v4/types/primitive" 7 | "github.com/centrifuge/go-substrate-rpc-client/v4/types/sr25519" 8 | ) 9 | 10 | func TestNewPolkadotNode(t *testing.T) { 11 | url := "ws://localhost:9944" 12 | node, err := NewPolkadotNode(url) 13 | if err!= nil { 14 | t.Fatal(err) 15 | } 16 | defer node.Client.Close() 17 | } 18 | 19 | func TestGetBlockHash(t *testing.T) { 20 | url := "ws://localhost:9944" 21 | node, err := NewPolkadotNode(url) 22 | if err!= nil { 23 | t.Fatal(err) 24 | } 25 | defer node.Client.Close() 26 | 27 | height := uint64(100) 28 | hash, err := node.GetBlockHash(height) 29 | if err!= nil { 30 | t.Fatal(err) 31 | } 32 | fmt.Printf("Block hash at height %d: %s\n", height, hash.Hex()) 33 | } 34 | 35 | func TestGetBlock(t *testing.T) { 36 | url := "ws://localhost:9944" 37 | node, err := NewPolkadotNode(url) 38 | if err!= nil { 39 | t.Fatal(err) 40 | } 41 | defer node.Client.Close() 42 | 43 | hash, err := types.HexDecodeString("0x1234567890abcdef") 44 | if err!= nil { 45 | t.Fatal(err) 46 | } 47 | block, err := node.GetBlock(hash) 48 | if err!= nil { 49 | t.Fatal(err) 50 | } 51 | fmt.Printf("Block at hash %s: %+v\n", hash.Hex(), block) 52 | } 53 | 54 | func TestGetFinalizedHead(t *testing.T) { 55 | url := "ws://localhost:9944" 56 | node, err := NewPolkadotNode(url) 57 | if err!= nil { 58 | t.Fatal(err) 59 | } 60 | defer node.Client.Close() 61 | 62 | header, err := node.GetFinalizedHead() 63 | if err!= nil { 64 | t.Fatal(err) 65 | } 66 | fmt.Printf("Finalized head: %+v\n", header) 67 | } 68 | 69 | func TestGetBestNumber(t *testing.T) { 70 | url := "ws://localhost:9944" 71 | node, err := NewPolkadotNode(url) 72 | if err!= nil { 73 | t.Fatal(err) 74 | } 75 | defer node.Client.Close() 76 | 77 | number, err := node.GetBestNumber() 78 | if err!= nil { 79 | t.Fatal(err) 80 | } 81 | fmt.Printf("Best block number: %d\n", number) 82 | } 83 | 84 | func TestGetMetadata(t *testing.T) { 85 | url := "ws://localhost:9944" 86 | node, err := NewPolkadotNode(url) 87 | if err!= nil { 88 | t.Fatal(err) 89 | } 90 | defer node.Client.Close() 91 | 92 | metadata, err := node.GetMetadata() 93 | if err!= nil { 94 | t.Fatal(err) 95 | } 96 | fmt.Printf("Metadata: %+v\n", metadata) 97 | } 98 | 99 | func TestGetStorage(t *testing.T) { 100 | url := "ws://localhost:9944" 101 | node, err := NewPolkadotNode(url) 102 | if err!= nil { 103 | t.Fatal(err) 104 | } 105 | defer node.Client.Close() 106 | 107 | item := types.StorageKey("0x1234567890abcdef") 108 | data, err := node.GetStorage(item) 109 | if err!= nil { 110 | t.Fatal(err) 111 | } 112 | fmt.Printf("Storage value at key %s: %s\n", item.Hex(), data.Hex()) 113 | } 114 | 115 | func TestExtrinsicSign(t *testing.T) { 116 | url := "ws://localhost:9944" 117 | node, err := NewPolkadotNode(url) 118 | if err!= nil { 119 | t.Fatal(err) 120 | } 121 | defer node.Client.Close() 122 | 123 | ext := extrinsic.NewExtrinsic(primitive.Call{ 124 | Module: "balances", 125 | Func: "transfer", 126 | Args: []primitive.Data{ 127 | primitive.NewU128(100), 128 | primitive.NewAccountId("0x1234567890abcdef"), 129 | }, 130 | }) 131 | signer, err := sr25519.NewPairFromSeed("0x1234567890abcdef", nil) 132 | if err!= nil { 133 | t.Fatal(err) 134 | } 135 | signedExt, err := node.ExtrinsicSign(ext, signer) 136 | if err!= nil { 137 | t.Fatal(err) 138 | } 139 | fmt.Printf("Signed extrinsic: %+v\n", signedExt) 140 | } 141 | 142 | func TestSubmitExtrinsic(t *testing.T) { 143 | url := "ws://localhost:9944" 144 | node, err := NewPolkadotNode(url) 145 | if err!= nil { 146 | t.Fatal(err) 147 | } 148 | defer node.Client.Close() 149 | 150 | ext := extrinsic.NewExtrinsic(primitive.Call{ 151 | Module: "balances", 152 | Func: "transfer", 153 | Args: []primitive.Data{ 154 | primitive.NewU128(100), 155 | primitive.NewAccountId("0x1234567890abcdef"), 156 | }, 157 | }) 158 | signer, err := sr25519.NewPairFromSeed("0x1234567890abcdef", nil) 159 | if err!= nil { 160 | t.Fatal(err) 161 | } 162 | signedExt, err := node.ExtrinsicSign(ext, signer) 163 | if err!= nil { 164 | t.Fatal(err) 165 | } 166 | hash, err := node.SubmitExtrinsic(signedExt) 167 | if err!= nil { 168 | t.Fatal(err) 169 | } 170 | fmt.Printf("Submitted extrinsic with hash %s\n", hash.Hex()) 171 | } 172 | 173 | func TestQuerySubscribe(t *testing.T) { 174 | url := "ws://localhost:9944" 175 | node, err := NewPolkadotNode(url) 176 | if err!= nil { 177 | t.Fatal(err) 178 | } 179 | defer node.Client.Close() 180 | 181 | query := query.NewSubscription("system_events", "NewHead") 182 | subscriber, err := node.QuerySubscribe(query) 183 | if err!= nil { 184 | t.Fatal(err) 185 | } 186 | defer subscriber.Unsubscribe() 187 | 188 | for { 189 | select { 190 | case <-subscriber.Done(): 191 | return 192 | case event := <-subscriber.Chan(): 193 | fmt.Printf("Received event: %+v\n", event) 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /network/node/pi_node_test.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | ) 7 | 8 | func TestNewPiNode(t *testing.T) { 9 | ctx := context.Background() 10 | privateKey, _, err := GenerateKeyPair() 11 | if err!= nil { 12 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 13 | } 14 | node, err := NewPiNode(ctx, privateKey) 15 | if err!= nil { 16 | t.Errorf("Expected NewPiNode to succeed, but got error: %s", err) 17 | } 18 | if node.Host == nil { 19 | t.Errorf("Expected node.Host to be non-nil") 20 | } 21 | if node.privateKey == nil { 22 | t.Errorf("Expected node.privateKey to be non-nil") 23 | } 24 | } 25 | 26 | func TestStart(t *testing.T) { 27 | ctx := context.Background() 28 | privateKey, _, err := GenerateKeyPair() 29 | if err!= nil { 30 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 31 | } 32 | node, err := NewPiNode(ctx, privateKey) 33 | if err!= nil { 34 | t.Errorf("Expected NewPiNode to succeed, but got error: %s", err) 35 | } 36 | err = node.Start(ctx) 37 | if err!= nil { 38 | t.Errorf("Expected node.Start to succeed, but got error: %s", err) 39 | } 40 | } 41 | 42 | func TestSend(t *testing.T) { 43 | ctx := context.Background() 44 | privateKey1, _, err := GenerateKeyPair() 45 | if err!= nil { 46 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 47 | } 48 | node1, err := NewPiNode(ctx, privateKey1) 49 | if err!= nil { 50 | t.Errorf("Expected NewPiNode to succeed, but got error: %s", err) 51 | } 52 | err = node1.Start(ctx) 53 | if err!= nil { 54 | t.Errorf("Expected node1.Start to succeed, but got error: %s", err) 55 | } 56 | privateKey2, _, err := GenerateKeyPair() 57 | if err!= nil { 58 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 59 | } 60 | node2, err := NewPiNode(ctx, privateKey2) 61 | if err!= nil { 62 | t.Errorf("Expected NewPiNode to succeed, but got error: %s", err) 63 | } 64 | err = node2.Start(ctx) 65 | if err!= nil { 66 | t.Errorf("Expected node2.Start to succeed, but got error: %s", err) 67 | } 68 | message := []byte("Hello, world!") 69 | err = node1.Send(ctx, node2.peerInfo.ID, message) 70 | if err!= nil { 71 | t.Errorf("Expected node1.Send to succeed, but got error: %s", err) 72 | } 73 | } 74 | 75 | func TestMarshalJSON(t *testing.T) { 76 | ctx := context.Background() 77 | privateKey, _, err := GenerateKeyPair() 78 | if err!= nil { 79 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 80 | } 81 | node, err := NewPiNode(ctx, privateKey) 82 | if err!= nil { 83 | t.Errorf("Expected NewPiNode to succeed, but got error: %s", err) 84 | } 85 | jsonData, err := node.MarshalJSON() 86 | if err!= nil { 87 | t.Errorf("Expected node.MarshalJSON to succeed, but got error: %s", err) 88 | } 89 | var jsonNode struct { 90 | PublicKey string `json:"public_key"` 91 | PeerInfo string `json:"peer_info"` 92 | } 93 | err = json.Unmarshal(jsonData, &jsonNode) 94 | if err!= nil { 95 | t.Errorf("Expected json.Unmarshal to succeed, but got error: %s", err) 96 | } 97 | if jsonNode.PublicKey!= hex.EncodeToString(node.publicKey.X.Bytes()) { 98 | t.Errorf("Expected jsonNode.PublicKey to match node.publicKey.X") 99 | } 100 | if jsonNode.PeerInfo!= node.peerInfo.String() { 101 | t.Errorf("Expected jsonNode.PeerInfo to match node.peerInfo") 102 | } 103 | } 104 | 105 | func TestUnmarshalJSON(t *testing.T) { 106 | ctx := context.Background() 107 | privateKey, _, err := GenerateKeyPair() 108 | if err!= nil { 109 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 110 | } 111 | node, err := NewPiNode(ctx, privateKey) 112 | if err!= nil { 113 | t.Errorf("Expected NewPiNode to succeed, but got error: %s", err) 114 | } 115 | jsonData, err := node.MarshalJSON() 116 | if err!= nil { 117 | t.Errorf("Expected node.MarshalJSON to succeed, but got error: %s", err) 118 | } 119 | unmarshaledNode, err := UnmarshalJSON(jsonData) 120 | if err!= nil { 121 | t.Errorf("Expected UnmarshalJSON to succeed, but got error: %s", err) 122 | } 123 | if unmarshaledNode.publicKey.X.Cmp(node.publicKey.X)!= 0 { 124 | t.Errorf("Expected unmarshaledNode.publicKey.X to match node.publicKey.X") 125 | } 126 | if unmarshaledNode.peerInfo.ID!= node.peerInfo.ID { 127 | t.Errorf("Expected unmarshaledNode.peerInfo.ID to match node.peerInfo.ID") 128 | } 129 | } 130 | 131 | func TestHandleStream(t *testing.T) { 132 | ctx := context.Background() 133 | privateKey, _, err := GenerateKeyPair() 134 | if err!= nil { 135 | t.Errorf("Expected GenerateKeyPair to succeed, but got error: %s", err) 136 | } 137 | node, err := NewPiNode(ctx, privateKey) 138 | if err!= nil { 139 | t.Errorf("Expected NewPiNode to succeed, but got error: %s", err) 140 | } 141 | err = node.Start(ctx) 142 | if err!= nil { 143 | t.Errorf("Expected node.Start to succeed, but got error: %s", err) 144 | } 145 | stream, err := node.Host.NewStream(ctx, node.peerInfo.ID, protocol.ID("/pi/1.0.0")) 146 | if err!= nil { 147 | t.Errorf("Expected node.Host.NewStream to succeed, but got error: %s", err) 148 | } 149 | go node.handleStream(stream) 150 | time.Sleep(100 * time.Millisecond) 151 | // Verify that the stream was handled correctly... 152 | } 153 | 154 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------