Skip to content

Commit

Permalink
solution-trial 2
Browse files Browse the repository at this point in the history
  • Loading branch information
OsauravO committed Apr 23, 2024
1 parent fa1106f commit df01f46
Show file tree
Hide file tree
Showing 33 changed files with 4,323 additions and 4,211 deletions.
47 changes: 47 additions & 0 deletions Blockchain/mine.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package Blockchain

import (
"encoding/hex"
"fmt"
"os"
"time"

"github.com/pred695/code-challenge-2024-pred695/Structs"
"github.com/pred695/code-challenge-2024-pred695/Utils"
)

var Bh Structs.BlockHeader = Structs.BlockHeader{
Version: 7,
PrevBlockHash: "0000000000000000000000000000000000000000000000000000000000000000",
MerkleRoot: "",
Time: time.Now().Unix(),
Bits: 0x1f00ffff,
Nonce: 0,
}

func MineBlock() {
netReward, TxIDs, _ := Utils.Prioritize()

cbTx := Utils.CreateCoinbase(netReward)
serializedcbTx, _ := Utils.SerializeTransaction(cbTx)
fmt.Printf("CBTX: %x\n", serializedcbTx)
TxIDs = append([]string{hex.EncodeToString(Utils.ReverseBytes(Utils.To_sha(Utils.To_sha(serializedcbTx))))}, TxIDs...)
mkr := Utils.NewMerkleTree(TxIDs)
Bh.MerkleRoot = hex.EncodeToString(mkr.Data)
cbtxbase := Utils.CalculateBaseSize(cbTx)
cbtxwitness := Utils.CalculateWitnessSize(cbTx)
fmt.Println("Cbtx wt: ", cbtxwitness+(cbtxbase*4))
if ProofOfWork(&Bh) {
file, _ := os.Create("output.txt")
defer file.Close()
// fmt.Println(Bh.merkleRoot)
// fmt.Println(Bh.nonce)
serializedBh := Utils.SerializeBlockHeader(&Bh)
segserialized, _ := Utils.SegWitSerialize(cbTx)
file.WriteString(hex.EncodeToString(serializedBh) + "\n")
file.WriteString(hex.EncodeToString(segserialized) + "\n")
for _, tx := range TxIDs {
file.WriteString(tx + "\n")
}
}
}
46 changes: 46 additions & 0 deletions Blockchain/pow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package Blockchain

import (
"encoding/hex"
"fmt"

"github.com/pred695/code-challenge-2024-pred695/Structs"
"github.com/pred695/code-challenge-2024-pred695/Utils"
)

const target string = "0000ffff00000000000000000000000000000000000000000000000000000000"

func CompareByteArrays(a, b []byte) int {
if len(a) != len(b) {
panic("Arrays must have the same length")
}

for i := range a {
if a[i] < b[i] {
return -1
} else if a[i] > b[i] {
return 1
}
}

return 0
}

func ProofOfWork(bh *Structs.BlockHeader) bool {
targetBytes, _ := hex.DecodeString(target)
// fmt.Printf("Target: %v\n", targetBytes)
for {
serialized := Utils.SerializeBlockHeader(bh)
hash := Utils.ReverseBytes(Utils.To_sha(Utils.To_sha(serialized)))

if CompareByteArrays(hash, targetBytes) == -1 {
fmt.Println("Block Mined", hex.EncodeToString(hash))
return true
}
if bh.Nonce < 0x0 || bh.Nonce > 0xffffffff {
fmt.Println("FUCKED")
return false
}
bh.Nonce++
}
}
66 changes: 0 additions & 66 deletions README.md

This file was deleted.

58 changes: 58 additions & 0 deletions Structs/struct.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package Structs

type BlockHeader struct {
Version uint32
PrevBlockHash string
MerkleRoot string
Time int64
Bits uint32
Nonce uint32
}

type Input struct {
TxID string `json:"txid"`
Vout uint32 `json:"vout"`
Prevout Prevout `json:"prevout"`
Scriptsig string `json:"scriptsig"`
ScriptsigAsm string `json:"scriptsig_asm"`
Witness []string `json:"witness"`
IsCoinbase bool `json:"is_coinbase"`
Sequence uint32 `json:"sequence"`
}

type Prevout struct {
Scriptpubkey string `json:"scriptpubkey"`
ScriptpubkeyAsm string `json:"scriptpubkey_asm"`
ScriptpubkeyType string `json:"scriptpubkey_type"`
ScriptpubkeyAddress string `json:"scriptpubkey_address"`
Value uint64 `json:"value"`
}

type Transaction struct {
Version uint32 `json:"version"`
Locktime uint32 `json:"locktime"`
Vin []Input `json:"vin"`
Vout []Prevout `json:"vout"`
}

type TxInfo struct {
TxID string
WTxID string
Fee uint64
Weight uint64
}
type TxWeight struct {
BaseSize int `json:"base_size"` // Size of non-witness data in bytes
WitnessSize int `json:"witness_size"` // Size of witness data in bytes
Weight int `json:"weight"` // Total weight in weight units
}

type MerkleNode struct {
Left *MerkleNode
Data []byte
Right *MerkleNode
}

type MerkleTree struct {
MerkleRoot *MerkleNode
}
45 changes: 45 additions & 0 deletions Utils/coinbase.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package Utils

import "github.com/pred695/code-challenge-2024-pred695/Structs"

func CreateCoinbase(netReward uint64) *Structs.Transaction {
witnessCommitment := CreateWitnessMerkle()
coinbaseTx := Structs.Transaction{
Version: 1,
Vin: []Structs.Input{
{
TxID: "0000000000000000000000000000000000000000000000000000000000000000",
Vout: 0xffffffff,
Prevout: Structs.Prevout{
Scriptpubkey: "0014df4bf9f3621073202be59ae590f55f42879a21a0",
ScriptpubkeyAsm: "0014df4bf9f3621073202be59ae590f55f42879a21a0",
ScriptpubkeyType: "p2pkh",
ScriptpubkeyAddress: "bc1qma9lnumzzpejq2l9ntjepa2lg2re5gdqn3nf0c",
Value: uint64(netReward),
},
IsCoinbase: true,
Sequence: 0xffffffff,
Scriptsig: "03951a0604f15ccf5609013803062b9b5a0100072f425443432f20",
Witness: []string{"0000000000000000000000000000000000000000000000000000000000000000"},
},
},
Vout: []Structs.Prevout{
{
Scriptpubkey: "0014df4bf9f3621073202be59ae590f55f42879a21a0",
ScriptpubkeyAsm: "0014df4bf9f3621073202be59ae590f55f42879a21a0",
ScriptpubkeyType: "p2pkh",
ScriptpubkeyAddress: "bc1qma9lnumzzpejq2l9ntjepa2lg2re5gdqn3nf0c",
Value: uint64(netReward),
},
{
Scriptpubkey: "6a24" + "aa21a9ed" + witnessCommitment, //OPRETURN +OP_PUSHBYTES_36+ commitment header + witnessCommitment
ScriptpubkeyAsm: "OP_RETURN" + "OP_PUSHBYTES_36" + "aa21a9ed" + witnessCommitment,
ScriptpubkeyType: "op_return",
ScriptpubkeyAddress: "bc1qma9lnumzzpejq2l9ntjepa2lg2re5gdqn3nf0c",
Value: uint64(0),
},
},
Locktime: 0,
}
return &coinbaseTx
}
59 changes: 59 additions & 0 deletions Utils/merkle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package Utils

import (
"encoding/hex"
"fmt"

"github.com/pred695/code-challenge-2024-pred695/Structs"
)

func NewMerkleNode(lnode *Structs.MerkleNode, rnode *Structs.MerkleNode, data []byte) *Structs.MerkleNode {
var mNode Structs.MerkleNode = Structs.MerkleNode{}
if lnode == nil && rnode == nil {
//hash256 of the data
mNode.Data = ReverseBytes(data)
} else {
var prevHash []byte = append(lnode.Data, rnode.Data...)
mNode.Data = To_sha(To_sha(prevHash))
}
mNode.Left = lnode
mNode.Right = rnode
return &mNode
}

func NewMerkleTree(leaves []string) *Structs.MerkleNode {
var nodes []Structs.MerkleNode

for _, leaf := range leaves {
data, _ := hex.DecodeString(leaf)
var node Structs.MerkleNode = *NewMerkleNode(nil, nil, data)
nodes = append(nodes, node)
}

for len(nodes) > 1 {
var newLevel []Structs.MerkleNode
for i := 0; i < len(nodes); i += 2 {
// Handle case where the total number of nodes is odd.
if len(nodes)%2 != 0 {
nodes = append(nodes, nodes[len(nodes)-1])
}
node := *NewMerkleNode(&nodes[i], &nodes[i+1], nil)
newLevel = append(newLevel, node)
}
nodes = newLevel
}
return &nodes[0]

}

func CreateWitnessMerkle() string {
_, _, wTxIDs := Prioritize()
wTxIDs = append([]string{"0000000000000000000000000000000000000000000000000000000000000000"}, wTxIDs...)
merkleRoot := NewMerkleTree(wTxIDs)
fmt.Println("WMKR: ", hex.EncodeToString(merkleRoot.Data))
commitment_string := hex.EncodeToString(merkleRoot.Data) + "0000000000000000000000000000000000000000000000000000000000000000"
WitnessCommitment, _ := hex.DecodeString(commitment_string)
WitnessCommitment = To_sha(To_sha(WitnessCommitment))
fmt.Println("Witness Commitment: ", hex.EncodeToString(WitnessCommitment))
return hex.EncodeToString(WitnessCommitment)
}
59 changes: 59 additions & 0 deletions Utils/prioritize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package Utils

import (
"encoding/hex"
"encoding/json"
"fmt"
"os"
"sort"

"github.com/pred695/code-challenge-2024-pred695/Structs"
)

func Comp(a, b Structs.TxInfo) bool {
return float64(a.Fee)/float64(a.Weight) > float64(b.Fee)/float64(b.Weight)
}
func Prioritize() (uint64, []string, []string) {
var permittedTxIDs []string
var permittedWTxIDs []string
dir := "./mempool"
files, _ := os.ReadDir(dir)
var txInfo []Structs.TxInfo
for _, file := range files {
txData, err := JsonData(dir + "/" + file.Name())
Handle(err)
var tx Structs.Transaction
err = json.Unmarshal([]byte(txData), &tx)
var fee uint64 = 0
for _, vin := range tx.Vin {
fee += vin.Prevout.Value
}
for _, vout := range tx.Vout {
fee -= vout.Value
}
serialized, _ := SerializeTransaction(&tx)
segserialized, _ := SegWitSerialize(&tx)
txID := ReverseBytes(To_sha(To_sha(serialized)))
wtxID := ReverseBytes(To_sha(To_sha(segserialized)))
txInfo = append(txInfo, Structs.TxInfo{TxID: hex.EncodeToString(txID), WTxID: hex.EncodeToString(wtxID), Fee: fee, Weight: uint64(CalculateWitnessSize(&tx) + CalculateBaseSize(&tx)*4)})

}
sort.Slice(txInfo, func(i, j int) bool {
return Comp(txInfo[i], txInfo[j])
})
var PermissibleTxs []Structs.TxInfo
var PermissibleWeight uint64 = 3999300
var reward uint64 = 0
for _, tx := range txInfo {
if PermissibleWeight >= tx.Weight {
PermissibleTxs = append(PermissibleTxs, tx)
PermissibleWeight -= tx.Weight
permittedTxIDs = append(permittedTxIDs, tx.TxID)
permittedWTxIDs = append(permittedWTxIDs, tx.WTxID)
reward += tx.Fee
}
}
fmt.Println("weight: ", PermissibleWeight)
fmt.Println("reward: ", reward)
return reward, permittedTxIDs, permittedWTxIDs
}
Loading

0 comments on commit df01f46

Please sign in to comment.