From b1a2c9a8dd741810645fb91b5c26af31c391172c Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Tue, 21 May 2024 08:52:55 -0300 Subject: [PATCH 01/15] setting the Block and Blockchain structure also with a simple hash function implemented --- internal/blockchain/block.go | 23 ++++++++++++++++++++++- internal/blockchain/blockchain.go | 5 +++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 internal/blockchain/blockchain.go diff --git a/internal/blockchain/block.go b/internal/blockchain/block.go index bcf7467..b04eb7d 100644 --- a/internal/blockchain/block.go +++ b/internal/blockchain/block.go @@ -1 +1,22 @@ -package blockchain +package main + +import ( + "bytes" + "crypto/sha256" + "strconv" +) + +type Block struct { + Timestamp int64 + Data []byte // Transactions + prevBlockHash []byte + Hash []byte + Counter uint64 // Nonce +} + +func (b *Block) SetHash() { + timestamp := []byte(strconv.FormatInt(b.Timestamp, 10)) + headers := bytes.Join([][]byte{b.prevBlockHash, b.Data, timestamp}, []byte{}) + hash := sha256.Sum256(headers) + b.Hash = hash[:] +} diff --git a/internal/blockchain/blockchain.go b/internal/blockchain/blockchain.go new file mode 100644 index 0000000..cd14191 --- /dev/null +++ b/internal/blockchain/blockchain.go @@ -0,0 +1,5 @@ +package main + +type Blockchain struct { + blocks []*Block +} From 0f65aa32c1788531459389d26ddf784c58b42558 Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Tue, 21 May 2024 08:54:24 -0300 Subject: [PATCH 02/15] Content Validation Function implemented --- internal/blockchain/proof_of_work.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 internal/blockchain/proof_of_work.go diff --git a/internal/blockchain/proof_of_work.go b/internal/blockchain/proof_of_work.go new file mode 100644 index 0000000..d8d5730 --- /dev/null +++ b/internal/blockchain/proof_of_work.go @@ -0,0 +1,20 @@ +package main + +import ( + "math/rand" + "strconv" + "time" +) + +//  T is the target value when using a proof of work algorithm +func GenerateT() string { + rand.New(rand.NewSource(time.Now().UnixNano())) + + prefix := rand.Intn(90) + 10 + + suffix := rand.Intn(10000000) + + T := strconv.Itoa(prefix) + strconv.Itoa(suffix) + + return T +} From 5aae8826285b2925846516365ee1c993ea85dcdb Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Tue, 21 May 2024 09:51:54 -0300 Subject: [PATCH 03/15] Input Contribution Function Implemented --- internal/blockchain/proof_of_work.go | 52 +++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/internal/blockchain/proof_of_work.go b/internal/blockchain/proof_of_work.go index d8d5730..d140c22 100644 --- a/internal/blockchain/proof_of_work.go +++ b/internal/blockchain/proof_of_work.go @@ -1,20 +1,54 @@ package main import ( - "math/rand" - "strconv" + "fmt" + "math/big" + "reflect" "time" ) -//  T is the target value when using a proof of work algorithm -func GenerateT() string { - rand.New(rand.NewSource(time.Now().UnixNano())) +type Receive func() string +type Input func() string - prefix := rand.Intn(90) + 10 +type ProofOfWork struct { + block *Block + T big.Int +} + +// Simple Content Validation Predicate implementation from backbone protocol +func ContentValidatePredicate(x *Blockchain) bool { + + if len(x.blocks) == 0 { + return false + } + + for i := range x.blocks { + if i == 0 { + continue + } + if reflect.DeepEqual(x.blocks[i].Hash, x.blocks[i-1].Hash) { + return false + } + } + return true +} + +func InputContributionFunction(data []byte, cr *Blockchain, round int, input Input, receive Receive) { + + input_data := input() + receive_data := receive() + + concat_data := input_data + receive_data - suffix := rand.Intn(10000000) + // creating new block - T := strconv.Itoa(prefix) + strconv.Itoa(suffix) + newBlock := &Block{time.Now().Unix(), []byte(concat_data), cr.blocks[len(cr.blocks)-1].Hash, []byte{}, round} + cr.blocks = append(cr.blocks, newBlock) - return T + if !ContentValidatePredicate(cr) { + fmt.Println("Content Validation Failed") + cr.blocks = cr.blocks[:len(cr.blocks)-1] + } else { + fmt.Println("Content Validation Passed") + } } From 2575feea594dddcb5cf8eecafe8540c7428727cb Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Tue, 21 May 2024 09:53:06 -0300 Subject: [PATCH 04/15] now target type is int --- internal/blockchain/block.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/blockchain/block.go b/internal/blockchain/block.go index b04eb7d..231563a 100644 --- a/internal/blockchain/block.go +++ b/internal/blockchain/block.go @@ -11,7 +11,7 @@ type Block struct { Data []byte // Transactions prevBlockHash []byte Hash []byte - Counter uint64 // Nonce + Counter int // Nonce } func (b *Block) SetHash() { From 169abe8b0764a1f0728357e01505e10027c76f47 Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Tue, 21 May 2024 10:14:51 -0300 Subject: [PATCH 05/15] Chain read function implemented --- internal/blockchain/proof_of_work.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/internal/blockchain/proof_of_work.go b/internal/blockchain/proof_of_work.go index d140c22..85fbd58 100644 --- a/internal/blockchain/proof_of_work.go +++ b/internal/blockchain/proof_of_work.go @@ -39,7 +39,6 @@ func InputContributionFunction(data []byte, cr *Blockchain, round int, input Inp receive_data := receive() concat_data := input_data + receive_data - // creating new block newBlock := &Block{time.Now().Unix(), []byte(concat_data), cr.blocks[len(cr.blocks)-1].Hash, []byte{}, round} @@ -52,3 +51,12 @@ func InputContributionFunction(data []byte, cr *Blockchain, round int, input Inp fmt.Println("Content Validation Passed") } } + +// Function to read the chain +func ChainReadFunction(c *Blockchain) string { + data := "" + for i := range c.blocks { + data += string(c.blocks[i].Data) + } + return data +} From 3cc3fbfba2ab25d1783920062600068a46291667 Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Tue, 21 May 2024 10:48:23 -0300 Subject: [PATCH 06/15] reorganizing proof_of_work.go and separating it in two files --- internal/blockchain/proof_of_work.go | 52 ---------------------------- 1 file changed, 52 deletions(-) diff --git a/internal/blockchain/proof_of_work.go b/internal/blockchain/proof_of_work.go index 85fbd58..772ed17 100644 --- a/internal/blockchain/proof_of_work.go +++ b/internal/blockchain/proof_of_work.go @@ -1,62 +1,10 @@ package main import ( - "fmt" "math/big" - "reflect" - "time" ) -type Receive func() string -type Input func() string - type ProofOfWork struct { block *Block T big.Int } - -// Simple Content Validation Predicate implementation from backbone protocol -func ContentValidatePredicate(x *Blockchain) bool { - - if len(x.blocks) == 0 { - return false - } - - for i := range x.blocks { - if i == 0 { - continue - } - if reflect.DeepEqual(x.blocks[i].Hash, x.blocks[i-1].Hash) { - return false - } - } - return true -} - -func InputContributionFunction(data []byte, cr *Blockchain, round int, input Input, receive Receive) { - - input_data := input() - receive_data := receive() - - concat_data := input_data + receive_data - // creating new block - - newBlock := &Block{time.Now().Unix(), []byte(concat_data), cr.blocks[len(cr.blocks)-1].Hash, []byte{}, round} - cr.blocks = append(cr.blocks, newBlock) - - if !ContentValidatePredicate(cr) { - fmt.Println("Content Validation Failed") - cr.blocks = cr.blocks[:len(cr.blocks)-1] - } else { - fmt.Println("Content Validation Passed") - } -} - -// Function to read the chain -func ChainReadFunction(c *Blockchain) string { - data := "" - for i := range c.blocks { - data += string(c.blocks[i].Data) - } - return data -} From dfa3158c26d3a853c115872e944965b3014f8aac Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Tue, 21 May 2024 10:50:28 -0300 Subject: [PATCH 07/15] validations separated from proof_of_work.go --- internal/blockchain/validantions.go | 67 +++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 internal/blockchain/validantions.go diff --git a/internal/blockchain/validantions.go b/internal/blockchain/validantions.go new file mode 100644 index 0000000..708b11e --- /dev/null +++ b/internal/blockchain/validantions.go @@ -0,0 +1,67 @@ +package main + +import ( + "fmt" + "math/rand" + "reflect" + "time" +) + +type Receive func() string +type Input func() string + +// Simple Content Validation Predicate implementation from backbone protocol +func ContentValidatePredicate(x *Blockchain) bool { + + if len(x.blocks) == 0 { + return false + } + + for i := range x.blocks { + if i == 0 { + continue + } + if reflect.DeepEqual(x.blocks[i].Hash, x.blocks[i-1].Hash) { + return false + } + } + return true +} + +func InputContributionFunction(data []byte, cr *Blockchain, round int, input Input, receive Receive) { + + input_data := input() + receive_data := receive() + + concat_data := input_data + receive_data + // creating new block + + newBlock := &Block{time.Now().Unix(), []byte(concat_data), cr.blocks[len(cr.blocks)-1].Hash, []byte{}, round} + cr.blocks = append(cr.blocks, newBlock) + + if !ContentValidatePredicate(cr) { + fmt.Println("Content Validation Failed") + cr.blocks = cr.blocks[:len(cr.blocks)-1] + } else { + fmt.Println("Content Validation Passed") + } +} + +// Function to read the chain +func ChainReadFunction(c *Blockchain) string { + data := "" + for i := range c.blocks { + data += string(c.blocks[i].Data) + } + return data +} + +func ChainValidationPredicate(c *Blockchain) { + b := ContentValidatePredicate(c) + + if b && c != nil { + temp_chain := c + c.blocks[rand.Intn(len(c.blocks))].SetHash() + + } +} From e589afe5bcf4e7efc9d300ec6e19d9aabe655713 Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Tue, 21 May 2024 11:47:19 -0300 Subject: [PATCH 08/15] implementing ValidateBlock and Chain Validation --- internal/blockchain/validantions.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/internal/blockchain/validantions.go b/internal/blockchain/validantions.go index 708b11e..fe70d26 100644 --- a/internal/blockchain/validantions.go +++ b/internal/blockchain/validantions.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "math/rand" "reflect" "time" ) @@ -10,6 +9,10 @@ import ( type Receive func() string type Input func() string +func ValidateBlockPredicate(b *Block) bool { + +} + // Simple Content Validation Predicate implementation from backbone protocol func ContentValidatePredicate(x *Blockchain) bool { @@ -56,12 +59,18 @@ func ChainReadFunction(c *Blockchain) string { return data } -func ChainValidationPredicate(c *Blockchain) { +/*func ChainValidationPredicate(c *Blockchain) bool { b := ContentValidatePredicate(c) if b && c != nil { + index := rand.Intn(len(c.blocks)) temp_chain := c - c.blocks[rand.Intn(len(c.blocks))].SetHash() + c.blocks[index].SetHash() + for i := true; i; b = false{ + if + } } + return b } +*/ From fa031f87385e040aa6ed693516fd80c9ddff9647 Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Wed, 22 May 2024 17:31:10 -0300 Subject: [PATCH 09/15] setup hash function to proof of work --- internal/blockchain/proof_of_work.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/internal/blockchain/proof_of_work.go b/internal/blockchain/proof_of_work.go index 772ed17..4cbde97 100644 --- a/internal/blockchain/proof_of_work.go +++ b/internal/blockchain/proof_of_work.go @@ -1,10 +1,31 @@ package main import ( + "bytes" "math/big" + "strconv" ) +const targetBits = 24 + type ProofOfWork struct { block *Block T big.Int } + +// Prepare pow data, this function hashes the data and returns it + +func (pow *ProofOfWork) prepareData(nonce int) []byte { + data := bytes.Join( + [][]byte{ + pow.block.prevBlockHash, + pow.block.Data, + []byte(strconv.FormatInt(pow.block.Timestamp, 10)), + []byte(strconv.FormatInt(targetBits, 10)), + []byte(strconv.FormatInt(int64(nonce), 10)), + }, + []byte{}, + ) + + return data +} From 34170834e185033e6c9a3f8ae8353c9fb719f69c Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Wed, 22 May 2024 17:34:29 -0300 Subject: [PATCH 10/15] blockvalidate function done --- internal/blockchain/validantions.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/internal/blockchain/validantions.go b/internal/blockchain/validantions.go index fe70d26..dd2ef14 100644 --- a/internal/blockchain/validantions.go +++ b/internal/blockchain/validantions.go @@ -1,7 +1,10 @@ package main import ( + "crypto/sha256" "fmt" + "math/big" + "math/rand" "reflect" "time" ) @@ -9,8 +12,15 @@ import ( type Receive func() string type Input func() string -func ValidateBlockPredicate(b *Block) bool { +func ValidateBlockPredicate(pow *ProofOfWork) bool { + var hashInt big.Int + data := pow.prepareData(pow.block.Counter) + hash := sha256.Sum256(data) + hashInt.SetBytes(hash[:]) + + validation := hashInt.Cmp(&pow.T) == -1 + return validation } // Simple Content Validation Predicate implementation from backbone protocol @@ -59,7 +69,7 @@ func ChainReadFunction(c *Blockchain) string { return data } -/*func ChainValidationPredicate(c *Blockchain) bool { +func ChainValidationPredicate(c *Blockchain) bool { b := ContentValidatePredicate(c) if b && c != nil { @@ -67,10 +77,9 @@ func ChainReadFunction(c *Blockchain) string { temp_chain := c c.blocks[index].SetHash() - for i := true; i; b = false{ - if + for i := true; i; b = false { + } } return b } -*/ From 3d0be4953ccc6b94bfe9c80558a85367dff644c4 Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Wed, 22 May 2024 17:49:27 -0300 Subject: [PATCH 11/15] genesis block created --- internal/blockchain/block.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/internal/blockchain/block.go b/internal/blockchain/block.go index 231563a..131978c 100644 --- a/internal/blockchain/block.go +++ b/internal/blockchain/block.go @@ -20,3 +20,15 @@ func (b *Block) SetHash() { hash := sha256.Sum256(headers) b.Hash = hash[:] } + +func (b *Block) GenesisBlock() *Block { + gen := &Block{ + Timestamp: 0, + Data: []byte("Genesis Block"), + prevBlockHash: []byte{}, + Hash: []byte{}, + Counter: 0, + } + + return gen +} From e867bd39fcdef82f522e3f79b04f8c91572a1478 Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Wed, 22 May 2024 18:01:55 -0300 Subject: [PATCH 12/15] chain validate predicate function implemented --- internal/blockchain/validantions.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/internal/blockchain/validantions.go b/internal/blockchain/validantions.go index dd2ef14..9ad8cb5 100644 --- a/internal/blockchain/validantions.go +++ b/internal/blockchain/validantions.go @@ -4,7 +4,6 @@ import ( "crypto/sha256" "fmt" "math/big" - "math/rand" "reflect" "time" ) @@ -69,16 +68,23 @@ func ChainReadFunction(c *Blockchain) string { return data } +// Function to validate the chain func ChainValidationPredicate(c *Blockchain) bool { b := ContentValidatePredicate(c) - if b && c != nil { - index := rand.Intn(len(c.blocks)) - temp_chain := c - c.blocks[index].SetHash() - - for i := true; i; b = false { - + if b { + temp_chain := c.blocks[len(c.blocks)-1] + s_ := sha256.Sum256(temp_chain.Data) + proof_ := &ProofOfWork{temp_chain, *big.NewInt(1)} + + for i := true; i; b = false || c == nil { + if ValidateBlockPredicate(proof_) && reflect.DeepEqual(temp_chain.Hash, s_) { + s_ = [32]byte{} + copy(s_[:], temp_chain.Data) + c.blocks = c.blocks[:len(c.blocks)-1] + } else { + b = false + } } } return b From 62e1a2f0b24a9e664a6a4275c19a9fe7fde1af51 Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Wed, 22 May 2024 18:10:52 -0300 Subject: [PATCH 13/15] function to find the best blockchain in a list implemented --- internal/blockchain/validantions.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/internal/blockchain/validantions.go b/internal/blockchain/validantions.go index 9ad8cb5..dfd5fde 100644 --- a/internal/blockchain/validantions.go +++ b/internal/blockchain/validantions.go @@ -89,3 +89,25 @@ func ChainValidationPredicate(c *Blockchain) bool { } return b } + +// Function to find the best chain + +func MaxChain(c [][]Blockchain) []*Block { + temp_chain := []*Block{} + + for i := 1; i < len(c); i++ { + if ChainValidationPredicate(&c[i][0]) { + temp_chain = maxBlocks(temp_chain, c[i][0].blocks) + } + } + + return temp_chain +} + +// compare blockchains length +func maxBlocks(a, b []*Block) []*Block { + if len(a) > len(b) { + return a + } + return b +} From 07544866ceb99b710b0f1c83bd9d0d4b19429f79 Mon Sep 17 00:00:00 2001 From: gabrielfnayres Date: Wed, 22 May 2024 18:34:31 -0300 Subject: [PATCH 14/15] proof of work function implemented (we now have to test it) --- internal/blockchain/proof_of_work.go | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/internal/blockchain/proof_of_work.go b/internal/blockchain/proof_of_work.go index 4cbde97..0173871 100644 --- a/internal/blockchain/proof_of_work.go +++ b/internal/blockchain/proof_of_work.go @@ -2,12 +2,16 @@ package main import ( "bytes" + "crypto/sha256" + "math" "math/big" "strconv" ) const targetBits = 24 +var maxNonce = math.MaxInt64 + type ProofOfWork struct { block *Block T big.Int @@ -29,3 +33,32 @@ func (pow *ProofOfWork) prepareData(nonce int) []byte { return data } + +func (pow *ProofOfWork) RunProofOfWork() (int, []byte) { + var hashInt big.Int + var hash [32]byte + nonce := 0 + + if pow.block == nil { + pow.block.Data = pow.block.GenesisBlock().Data + } else { + temp_block := pow.block + temp_block.SetHash() + pow.block = temp_block + } + + for nonce < maxNonce { + data := pow.prepareData(nonce) + hash = sha256.Sum256(data) + + hashInt.SetBytes(hash[:]) + if hashInt.Cmp(&pow.T) == -1 { + break + } else { + nonce++ + } + } + + return nonce, hash[:] + +} From 0abd32e796da9e072c0c295be960da5711811037 Mon Sep 17 00:00:00 2001 From: Nicholas Rodrigues <104515007+NicholasRodrigues@users.noreply.github.com> Date: Wed, 22 May 2024 19:16:29 -0300 Subject: [PATCH 15/15] Delete github/workflows directory --- github/workflows/ci.yml | 79 ----------------------------------------- 1 file changed, 79 deletions(-) delete mode 100644 github/workflows/ci.yml diff --git a/github/workflows/ci.yml b/github/workflows/ci.yml deleted file mode 100644 index b6ea394..0000000 --- a/github/workflows/ci.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: CI - -on: - pull_request: - branches: [main] - push: - branches: [main] - -jobs: - tests: - name: Tests - runs-on: ubuntu-latest - - steps: - - name: Check out code - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.22.1' - - - name: Install dependencies - run: go mod download - - - name: Run Tests - run: go test -v -coverprofile=coverage.out ./... - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 - with: - file: coverage.out - - style: - name: Style - runs-on: ubuntu-latest - - steps: - - name: Check out code - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.22.1' - - - name: Check formatting - run: gofmt -l . || exit 1 - - - name: Install staticcheck - run: go install honnef.co/go/tools/cmd/staticcheck@latest - - - name: Run staticcheck - run: staticcheck ./... - - - name: Install gosec - run: go install github.com/securego/gosec/v2/cmd/gosec@latest - - - name: Run gosec - run: gosec ./... - - lint: - name: Lint - runs-on: ubuntu-latest - - steps: - - name: Check out code - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.22.1' - - - name: Install golangci-lint - run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest - - - name: Run golangci-lint - run: golangci-lint run ./...