diff options
Diffstat (limited to 'pkg/block')
-rw-r--r-- | pkg/block/block.go | 90 | ||||
-rw-r--r-- | pkg/block/transaction.go | 128 |
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)) +} |