aboutsummaryrefslogtreecommitdiff
path: root/pkg/block
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/block')
-rw-r--r--pkg/block/block.go90
-rw-r--r--pkg/block/transaction.go128
2 files changed, 218 insertions, 0 deletions
diff --git a/pkg/block/block.go b/pkg/block/block.go
new file mode 100644
index 0000000..843f43f
--- /dev/null
+++ b/pkg/block/block.go
@@ -0,0 +1,90 @@
+package block
+
+import (
+ "Chain/pkg/pro"
+ "crypto/sha256"
+ "fmt"
+ "google.golang.org/protobuf/proto"
+)
+
+// Header provides information about the Block.
+// Version is the Block's version.
+// PreviousHash is the hash of the previous Block.
+// MerkleRoot is the hash of all the Block's Transactions.
+// DifficultyTarget is the difficulty of achieving a winning Nonce.
+// Nonce is a "number only used once" that satisfies the DifficultyTarget.
+// Timestamp is when the Block was successfully mined.
+type Header struct {
+ Version uint32
+ PreviousHash string
+ MerkleRoot string
+ DifficultyTarget string
+ Nonce uint32
+ Timestamp uint32
+}
+
+// Block includes a Header and a slice of Transactions.
+type Block struct {
+ Header *Header
+ Transactions []*Transaction
+}
+
+// EncodeHeader returns a pro.Header given a Header.
+func EncodeHeader(header *Header) *pro.Header {
+ return &pro.Header{
+ Version: header.Version,
+ PreviousHash: header.PreviousHash,
+ MerkleRoot: header.MerkleRoot,
+ DifficultyTarget: header.DifficultyTarget,
+ Nonce: header.Nonce,
+ Timestamp: header.Timestamp,
+ }
+}
+
+// DecodeHeader returns a Header given a pro.Header.
+func DecodeHeader(pheader *pro.Header) *Header {
+ return &Header{
+ Version: pheader.GetVersion(),
+ PreviousHash: pheader.GetPreviousHash(),
+ MerkleRoot: pheader.GetMerkleRoot(),
+ DifficultyTarget: pheader.GetDifficultyTarget(),
+ Nonce: pheader.GetNonce(),
+ Timestamp: pheader.GetTimestamp(),
+ }
+}
+
+// EncodeBlock returns a pro.Block given a Block.
+func EncodeBlock(b *Block) *pro.Block {
+ var ptxs []*pro.Transaction
+ for _, tx := range b.Transactions {
+ ptxs = append(ptxs, EncodeTransaction(tx))
+ }
+ return &pro.Block{
+ Header: EncodeHeader(b.Header),
+ Transactions: ptxs,
+ }
+}
+
+// DecodeBlock returns a Block given a pro.Block.
+func DecodeBlock(pb *pro.Block) *Block {
+ var txs []*Transaction
+ for _, ptx := range pb.GetTransactions() {
+ txs = append(txs, DecodeTransaction(ptx))
+ }
+ return &Block{
+ Header: DecodeHeader(pb.GetHeader()),
+ Transactions: txs,
+ }
+}
+
+// Hash returns the hash of the block (which is done via the header)
+func (block *Block) Hash() string {
+ h := sha256.New()
+ pb := EncodeHeader(block.Header)
+ bytes, err := proto.Marshal(pb)
+ if err != nil {
+ fmt.Errorf("[block.Hash()] Unable to marshal block")
+ }
+ h.Write(bytes)
+ return fmt.Sprintf("%x", h.Sum(nil))
+}
diff --git a/pkg/block/transaction.go b/pkg/block/transaction.go
new file mode 100644
index 0000000..0102120
--- /dev/null
+++ b/pkg/block/transaction.go
@@ -0,0 +1,128 @@
+package block
+
+import (
+ "Chain/pkg/pro"
+ "crypto/sha256"
+ "fmt"
+ "google.golang.org/protobuf/proto"
+)
+
+// TransactionInput is used as the input to create a TransactionOutput.
+// Recall that TransactionInputs generate TransactionOutputs which in turn
+// generate new TransactionInputs and so forth.
+// ReferenceTransactionHash is the hash of the parent TransactionOutput's Transaction.
+// OutputIndex is the index of the parent TransactionOutput's Transaction.
+// Signature verifies that the payer can spend the referenced TransactionOutput.
+type TransactionInput struct {
+ ReferenceTransactionHash string
+ OutputIndex uint32
+ UnlockingScript string
+}
+
+// TransactionOutput is an output created from a TransactionInput.
+// Recall that TransactionOutputs generate TransactionInputs which in turn
+// generate new TransactionOutputs and so forth.
+// Amount is how much this TransactionOutput is worth.
+// PublicKey is used to verify the payee's signature.
+type TransactionOutput struct {
+ Amount uint32
+ LockingScript string
+}
+
+// Transaction contains information about a transaction.
+// Version is the version of this transaction.
+// Inputs is a slice of TransactionInputs.
+// Outputs is a slice of TransactionOutputs.
+// LockTime is the future time after which the Transaction is valid.
+type Transaction struct {
+ Version uint32
+ Inputs []*TransactionInput
+ Outputs []*TransactionOutput
+ LockTime uint32
+}
+
+// EncodeTransactionInput returns a pro.TransactionInput input
+// given a TransactionInput.
+func EncodeTransactionInput(txi *TransactionInput) *pro.TransactionInput {
+ return &pro.TransactionInput{
+ ReferenceTransactionHash: txi.ReferenceTransactionHash,
+ OutputIndex: txi.OutputIndex,
+ UnlockingScript: txi.UnlockingScript,
+ }
+}
+
+// DecodeTransactionInput returns a TransactionInput given
+// a pro.TransactionInput.
+func DecodeTransactionInput(ptxi *pro.TransactionInput) *TransactionInput {
+ return &TransactionInput{
+ ReferenceTransactionHash: ptxi.GetReferenceTransactionHash(),
+ OutputIndex: ptxi.GetOutputIndex(),
+ UnlockingScript: ptxi.GetUnlockingScript(),
+ }
+}
+
+// EncodeTransactionOutput returns a pro.TransactionOutput given
+// a TransactionOutput.
+func EncodeTransactionOutput(txo *TransactionOutput) *pro.TransactionOutput {
+ return &pro.TransactionOutput{
+ Amount: txo.Amount,
+ LockingScript: txo.LockingScript,
+ }
+}
+
+// DecodeTransactionOutput returns a TransactionOutput given
+// a pro.TransactionOutput.
+func DecodeTransactionOutput(ptxo *pro.TransactionOutput) *TransactionOutput {
+ return &TransactionOutput{
+ Amount: ptxo.GetAmount(),
+ LockingScript: ptxo.GetLockingScript(),
+ }
+}
+
+// EncodeTransaction returns a pro.Transaction given a Transaction.
+func EncodeTransaction(tx *Transaction) *pro.Transaction {
+ var ptxis []*pro.TransactionInput
+ for _, txi := range tx.Inputs {
+ ptxis = append(ptxis, EncodeTransactionInput(txi))
+ }
+ var ptxos []*pro.TransactionOutput
+ for _, txo := range tx.Outputs {
+ ptxos = append(ptxos, EncodeTransactionOutput(txo))
+ }
+ return &pro.Transaction{
+ Version: tx.Version,
+ Inputs: ptxis,
+ Outputs: ptxos,
+ LockTime: tx.LockTime,
+ }
+}
+
+// DecodeTransaction returns a Transaction given a pro.Transaction.
+func DecodeTransaction(ptx *pro.Transaction) *Transaction {
+ var txis []*TransactionInput
+ for _, ptxi := range ptx.GetInputs() {
+ txis = append(txis, DecodeTransactionInput(ptxi))
+ }
+ var txos []*TransactionOutput
+ for _, ptxo := range ptx.GetOutputs() {
+ txos = append(txos, DecodeTransactionOutput(ptxo))
+ }
+ return &Transaction{
+ Version: ptx.GetVersion(),
+ Inputs: txis,
+ Outputs: txos,
+ LockTime: ptx.GetLockTime(),
+ }
+}
+
+// Hash returns the hash of the transaction
+func (tx *Transaction) Hash() string {
+ h := sha256.New()
+ pt := EncodeTransaction(tx)
+ bytes, err := proto.Marshal(pt)
+ if err != nil {
+ fmt.Errorf("[tx.Hash()] Unable to marshal transaction")
+ }
+ h.Write(bytes)
+ return fmt.Sprintf("%x", h.Sum(nil))
+}