-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
33 changed files
with
4,323 additions
and
4,211 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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++ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.