-
Notifications
You must be signed in to change notification settings - Fork 1
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
1 parent
252fb95
commit 3accb08
Showing
15 changed files
with
733 additions
and
133 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
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 |
---|---|---|
@@ -1 +1,4 @@ | ||
# Update this file to run your own code | ||
# Update this file to run your own code | ||
cd src | ||
go mod tidy | ||
go run main.go |
Binary file not shown.
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
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,113 @@ | ||
package mining | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"encoding/binary" | ||
"encoding/hex" | ||
"io" | ||
"os" | ||
|
||
txn "github.com/humblenginr/btc-miner/transaction" | ||
) | ||
|
||
// Data types taken from: https://developer.bitcoin.org/reference/block_chain.html | ||
type BlockHeader struct { | ||
Version int32 `json:"version"` | ||
PrevBlockHash [32]byte | ||
MerkleRoot [32]byte | ||
// Unix timestamp | ||
Time int64 | ||
// Compact representation of difficulty target | ||
Bits uint32 | ||
Nonce uint32 | ||
} | ||
|
||
func (bh *BlockHeader) Serialize(w io.Writer) error { | ||
buf := make([]byte, 4) | ||
|
||
binary.LittleEndian.PutUint32(buf[:4], uint32(bh.Version)) | ||
if _, err := w.Write(buf[:4]); err != nil { | ||
return err | ||
} | ||
|
||
if _, err := w.Write(bh.PrevBlockHash[:]); err != nil { | ||
return err | ||
} | ||
|
||
if _, err := w.Write(bh.MerkleRoot[:]); err != nil { | ||
return err | ||
} | ||
|
||
binary.LittleEndian.PutUint32(buf[:4], uint32(bh.Time)) | ||
if _, err := w.Write(buf[:4]); err != nil { | ||
return err | ||
} | ||
|
||
binary.LittleEndian.PutUint32(buf[:4], bh.Bits) | ||
if _, err := w.Write(buf[:4]); err != nil { | ||
return err | ||
} | ||
|
||
binary.LittleEndian.PutUint32(buf[:4], bh.Nonce) | ||
if _, err := w.Write(buf[:4]); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func NewBlockHeader(version int32, prevBlockHash [32]byte, merkleRoot [32]byte, time int64, bits uint32, nonce uint32) BlockHeader { | ||
return BlockHeader{version, prevBlockHash, merkleRoot, time, bits, nonce} | ||
} | ||
|
||
|
||
type Block struct { | ||
BlockHeader BlockHeader | ||
Coinbase txn.Transaction | ||
Transactions []txn.Transaction | ||
} | ||
|
||
func (b *Block) AddTransaction (t txn.Transaction) { | ||
b.Transactions = append(b.Transactions, t) | ||
} | ||
|
||
func (b *Block) WriteToFile(filePath string) error { | ||
/* | ||
First line: The block header. | ||
Second line: The serialized coinbase transaction. | ||
Following lines: The transaction IDs (txids) of the transactions mined in the block, in order. The first txid should be that of the coinbase transaction | ||
*/ | ||
f, err := os.Create(filePath) | ||
if err != nil { | ||
return err | ||
} | ||
defer f.Close() | ||
|
||
w := bufio.NewWriter(f) | ||
|
||
// Block header | ||
buf := bytes.NewBuffer(make([]byte, 0, 80)) | ||
b.BlockHeader.Serialize(buf) | ||
w.WriteString(hex.EncodeToString(buf.Bytes())+"\n") | ||
|
||
// Serialized coinbase transaction | ||
cb := b.Coinbase | ||
w.WriteString(hex.EncodeToString(cb.RawHex())+"\n") | ||
|
||
// Txid of coinbase transaction | ||
w.WriteString(hex.EncodeToString(cb.TxHash())+"\n") | ||
|
||
// Txid of rest of the transactions | ||
for _, txn := range b.Transactions { | ||
txid := txn.TxHash() | ||
w.WriteString(hex.EncodeToString(txid)+"\n") | ||
} | ||
w.Flush() | ||
return nil | ||
} | ||
|
||
func NewBlock(header BlockHeader, coinbase txn.Transaction, txns []txn.Transaction) Block { | ||
return Block{header, coinbase, txns} | ||
} | ||
|
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,69 @@ | ||
package mining | ||
|
||
import ( | ||
"encoding/hex" | ||
|
||
txn "github.com/humblenginr/btc-miner/transaction" | ||
"github.com/humblenginr/btc-miner/utils" | ||
) | ||
|
||
var MaxVoutIndex uint32 = 0xffffffff | ||
var WitnessReserveHexString = "0000000000000000000000000000000000000000000000000000000000000000" | ||
// in satoshis | ||
var BlockSubsidy int = 0 | ||
var CoinbaseTransactionVersion int32 = 1 | ||
|
||
func NewCoinbaseTransaction(fees int) txn.Transaction { | ||
var zeroTxid [32]byte | ||
t := txn.Transaction{} | ||
t.Version = CoinbaseTransactionVersion | ||
t.Locktime = 0 | ||
|
||
vin := txn.Vin{} | ||
vin.IsCoinbase = true | ||
vin.Txid = hex.EncodeToString(zeroTxid[:]) | ||
vin.Vout = int(MaxVoutIndex) | ||
// push 3 bytes, 951a06 - which is the block height | ||
vin.ScriptSig = "03951a06" | ||
vin.ScriptSigAsm = "PUSH_3 951a06" | ||
vin.Sequence = 0 | ||
t.Vin = append(t.Vin, vin) | ||
|
||
vout := txn.Vout{} | ||
// OP_TRUE - anyone can redeem this | ||
vout.ScriptPubKey = "51" | ||
vout.ScriptPubKeyAsm = "OP_TRUE" | ||
vout.Value = BlockSubsidy + fees | ||
t.Vout = append(t.Vout, vout) | ||
|
||
return t | ||
} | ||
|
||
func AddWitnessCommitment(coinbase *txn.Transaction, txns []*txn.Transaction) error { | ||
var witnessNonce [32]byte | ||
|
||
coinbase.Vin[0].Witness = append(coinbase.Vin[0].Witness, WitnessReserveHexString) | ||
witnessMerkleRoot := CalcMerkleRoot(txns, true) | ||
|
||
var witnessPreimage [64]byte | ||
copy(witnessPreimage[:32], witnessMerkleRoot[:]) | ||
copy(witnessPreimage[32:], witnessNonce[:]) | ||
witnessCommitment := utils.DoubleHash(witnessPreimage[:]) | ||
witnessScript := []byte{ | ||
// OP_RETURN | ||
0x6a, | ||
// OP_DATA36 | ||
0x36, | ||
0xaa, | ||
0x21, | ||
0xa9, | ||
0xed, | ||
} | ||
witnessScript = append(witnessScript, witnessCommitment...) | ||
witnessOut := txn.Vout{} | ||
witnessOut.Value = 0 | ||
witnessOut.ScriptPubKey = hex.EncodeToString(witnessScript) | ||
coinbase.Vout = append(coinbase.Vout, witnessOut) | ||
|
||
return nil | ||
} |
Oops, something went wrong.