Skip to content

Commit

Permalink
Merge pull request #7 from 0xsharma/shivam/add-p2p
Browse files Browse the repository at this point in the history
init : p2p gRPC
  • Loading branch information
0xsharma authored Oct 17, 2023
2 parents 677ad30 + ffb772d commit f439216
Show file tree
Hide file tree
Showing 26 changed files with 1,717 additions and 98 deletions.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,11 @@ lintci-deps:

test:
$(GOTEST) --timeout 5m -shuffle=on ./...

devtools:
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
@type "protoc" 2> /dev/null || echo '\n\nPlease install protoc\n Linux : apt install -y protobuf-compiler\n Mac : brew install protobuf\n Windows : choco install protoc\n'

protoc:
protoc --go_out=. --go-grpc_out=. ./protos/*.proto
46 changes: 39 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,53 @@
# Compact-Chain

## About <a name = "about"></a>

This is a simple implentation of Blockchain in Golang. This is still in development and is not ready. This project is undertaken to enhance my knowlege on advanced(p2p, db, state-transitions) blockchain concepts. This can be used by anyone who wants to learn about blockchain and how it works.
# Compact-Chain
This is a simple implentation of Blockchain in Golang. This project is undertaken to enhance my knowlege on advanced(p2p, db, state-transitions) blockchain concepts. This can be used by anyone who wants to learn about blockchain and how it works.

### Prerequisites

What things you need to install the software and how to install them.

```
Golang 1.19+
Golang 1.20+
```

### Run
### Run Demo Chain

```
go mod tidy
go run main.go start
go run main.go demo
```

### Run Multiple Nodes Chain

```
go mod tidy
go run main.go start <NODE_ID>
for example :
terminal/instance 1 : go run main.go start 1
terminal/instance 2 : go run main.go start 2
terminal/instance 3 : go run main.go start 3
And so on....
```

### Run Tests

```
make test
```

### Modules Implemented

```
- Consensus (POW)
- p2p (gRPC)
- DbStore
- State Executor
- RPC (add and get Transactions)
- TxPool
- Encoding
- Hashing
```
### License
The entire code is licensed under the [GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html).

50 changes: 46 additions & 4 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import (
"fmt"
"math/big"
"os"
"strconv"
"time"

"github.com/0xsharma/compact-chain/config"
"github.com/0xsharma/compact-chain/core"
"github.com/0xsharma/compact-chain/types"
"github.com/0xsharma/compact-chain/util"
"github.com/spf13/cobra"
)

Expand All @@ -27,6 +29,16 @@ var (
startCmd = &cobra.Command{
Use: "start",
Short: "Start the Compact-Chain node",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Starting Compact-Chain node\n\n")
nodeID, _ := strconv.ParseInt(args[0], 10, 0)
startBlockchainNode(nodeID)
},
}

demoCmd = &cobra.Command{
Use: "demo",
Short: "Demo the Compact-Chain node",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Starting Compact-Chain node\n\n")
demoBlockchain()
Expand All @@ -42,6 +54,7 @@ func Execute() error {
func init() {
rootCmd.AddCommand(versionCmd)
rootCmd.AddCommand(startCmd)
rootCmd.AddCommand(demoCmd)
}

var (
Expand All @@ -54,11 +67,15 @@ func demoBlockchain() {
config := &config.Config{
ConsensusDifficulty: 16,
ConsensusName: "pow",
DBDir: dbPath,
StateDBDir: stateDbPath,
DBDir: dbPath + "demo",
StateDBDir: stateDbPath + "demo",
MinFee: big.NewInt(100),
RPCPort: ":6999",
RPCPort: ":1711",
BalanceAlloc: map[string]*big.Int{},
P2PPort: ":6060",
Peers: []string{"localhost:6061"},
BlockTime: 2,
SignerPrivateKey: util.HexToPrivateKey("c3fc038a9abc0f483e2e1f8a0b4db676bce3eaebd7d9afc68e1e7e28ca8738a1"),
}

chain := core.NewBlockchain(config)
Expand All @@ -72,7 +89,32 @@ func demoBlockchain() {

for i := lastNumber.Int64() + 1; i <= lastNumber.Int64()+10; i++ {
time.Sleep(2 * time.Second)
chain.AddBlock([]byte(fmt.Sprintf("Block %d", i)), []*types.Transaction{})

err := chain.AddBlock([]byte(fmt.Sprintf("Block %d", i)), []*types.Transaction{}, make(chan bool), config.SignerPrivateKey)
if err != nil {
fmt.Println("Error Adding Block", err)
}

fmt.Println("Number : ", chain.LastBlock.Number, "Hash : ", chain.LastBlock.DeriveHash().String())
}
}

func startBlockchainNode(nodeId int64) {
fmt.Println("Starting node", nodeId)

config := &config.Config{
ConsensusDifficulty: 20,
ConsensusName: "pow",
DBDir: dbPath + fmt.Sprint(nodeId),
StateDBDir: stateDbPath + fmt.Sprint(nodeId),
MinFee: big.NewInt(100),
RPCPort: ":1711" + fmt.Sprint(nodeId),
BalanceAlloc: map[string]*big.Int{},
P2PPort: ":6060" + fmt.Sprint(nodeId),
Peers: []string{"localhost:60601", "localhost:60602", "localhost:60603"},
BlockTime: 4,
SignerPrivateKey: util.HexToPrivateKey("c3fc038a9abc0f483e2e1f8a0b4db676bce3eaebd7d9afc68e1e7e28ca8738a" + fmt.Sprint(nodeId)),
}

core.StartBlockchain(config)
}
5 changes: 5 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ type Config struct {
SignerPrivateKey *ecdsa.PrivateKey
Mine bool
BalanceAlloc map[string]*big.Int
P2PPort string
Peers []string
BlockTime int
}

func DefaultConfig() *Config {
Expand All @@ -33,6 +36,8 @@ func DefaultConfig() *Config {
StateDBDir: stateDbPath,
MinFee: big.NewInt(100),
RPCPort: ":1711",
P2PPort: ":6060",
BlockTime: 4,
}

return cfg
Expand Down
3 changes: 2 additions & 1 deletion consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ type Consensus interface {
GetDifficulty() *big.Int
SetDifficulty(d *big.Int)
GetTarget() *big.Int
Mine(b *types.Block) *types.Block
Mine(b *types.Block, mineInterrupt chan bool) *types.Block
Validate(b *types.Block) bool
}
57 changes: 48 additions & 9 deletions consensus/pow/pow.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package pow

import (
"crypto/rand"
"fmt"
"math/big"

Expand Down Expand Up @@ -38,7 +39,7 @@ func (c *POW) GetTarget() *big.Int {
}

// Mine mines the block with the proof of work consensus with the given difficulty.
func (c *POW) Mine(b *types.Block) *types.Block {
func (c *POW) Mine(b *types.Block, mineInterrupt chan bool) *types.Block {
nonce := big.NewInt(0)

validTxs := []*types.Transaction{}
Expand All @@ -59,18 +60,56 @@ func (c *POW) Mine(b *types.Block) *types.Block {
b.Transactions = validTxs

for {
b.SetNonce(nonce)
hash := b.DeriveHash()
select {
case <-mineInterrupt:
return nil

hashBytes := hash.Bytes()
hashBig := new(big.Int).SetBytes(hashBytes)
default:
b.SetNonce(nonce)
hash := b.DeriveHash()

if hashBig.Cmp(c.GetTarget()) < 0 {
break
hashBytes := hash.Bytes()
hashBig := new(big.Int).SetBytes(hashBytes)

if hashBig.Cmp(c.GetTarget()) < 0 {
return b
}

n, _ := rand.Int(rand.Reader, big.NewInt(100))
nonce.Add(nonce, big.NewInt(n.Int64()))
}
}
}

// Validate validates the block with the proof of work consensus.
func (c *POW) Validate(b *types.Block) bool {
validTxs := []*types.Transaction{}

for _, tx := range b.Transactions {
if c.TxProcessor.IsValid(tx) {
err := c.TxProcessor.ProcessTx(tx)
if err == nil {
validTxs = append(validTxs, tx)
} else {
fmt.Println("Failed to execute Tx :", "tx :", tx, "error", err)
return false
}
} else {
fmt.Println("Invalid Tx :", "tx :", tx)
return false
}
}

b.Transactions = validTxs

hash := b.DeriveHash()
hashBytes := hash.Bytes()
hashBig := new(big.Int).SetBytes(hashBytes)

nonce.Add(nonce, big.NewInt(1))
if hashBig.Cmp(c.GetTarget()) > 0 {
fmt.Println("Invalid block hash for POW :", hashBig, "target :", c.GetTarget())
return false
}

return b
return true
}
Loading

0 comments on commit f439216

Please sign in to comment.