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 ./... diff --git a/internal/blockchain/proof_of_work.go b/internal/blockchain/proof_of_work.go index 42705f6..dcdbc05 100644 --- a/internal/blockchain/proof_of_work.go +++ b/internal/blockchain/proof_of_work.go @@ -1,9 +1,17 @@ package blockchain import ( + "bytes" + "crypto/sha256" + "math" "math/big" + "strconv" ) +const targetBits = 24 + +var maxNonce = math.MaxInt64 + const Difficulty = 16 type ProofOfWork struct { @@ -11,6 +19,51 @@ type ProofOfWork struct { 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 +} + +func (pow *ProofOfWork) RunProofOfWork() (int, []byte) { + var hashInt big.Int + var hash [32]byte + nonce := 0 + + if pow.block == nil { + pow.block.Data = NewGenesisBlock().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[:] +} + func NewProofOfWork(b *Block) *ProofOfWork { target := big.NewInt(1) target.Lsh(target, uint(256-Difficulty)) diff --git a/internal/blockchain/validantions.go b/internal/blockchain/validantions.go index c75aa10..2252c2a 100644 --- a/internal/blockchain/validantions.go +++ b/internal/blockchain/validantions.go @@ -1,7 +1,9 @@ package blockchain import ( + "crypto/sha256" "fmt" + "math/big" "reflect" "time" ) @@ -9,11 +11,16 @@ 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 func ContentValidatePredicate(x *Blockchain) bool { @@ -61,18 +68,46 @@ func ChainReadFunction(c *Blockchain) string { return data } -/*func ChainValidationPredicate(c *Blockchain) bool { +// 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() + 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 +} + +// Function to find the best chain - for i := true; i; b = false{ - if +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 } -*/