You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

154 lines
3.5 KiB

package node
import (
"crypto/ecdsa"
"time"
"github.com/arnaucube/slowlorisdb/core"
)
// Node
type Node struct {
PrivK *ecdsa.PrivateKey
Addr core.Address
Bc *core.Blockchain
Miner bool // indicates if the node is running as a miner
PendingTxs []core.Tx
}
// NewNode creates a new node
func NewNode(privK *ecdsa.PrivateKey, bc *core.Blockchain, isMiner bool) (*Node, error) {
addr := core.AddressFromPrivK(privK)
node := &Node{
PrivK: privK,
Addr: addr,
Bc: bc,
Miner: isMiner,
PendingTxs: []core.Tx{},
}
return node, nil
}
// SignBlock performs a signature of a byte array with the node private key
func (node *Node) Sign(m []byte) (*core.Signature, error) {
return core.Sign(node.PrivK, m)
}
// SignBlock performs a signature of a block with the node private key
func (node *Node) SignBlock(block *core.Block) error {
block.CalculateHash()
sig, err := core.Sign(node.PrivK, block.Hash[:])
if err != nil {
return err
}
block.Signature = sig.Bytes()
return nil
}
// AddToPendingTxs adds a transaction the the node.PendingTxs
func (node *Node) AddToPendingTxs(tx core.Tx) {
node.PendingTxs = append(node.PendingTxs, tx)
}
// BlockFromPendingTxs creates a new block from the pending transactions
func (node *Node) BlockFromPendingTxs() (*core.Block, error) {
block, err := node.NewBlock(node.PendingTxs)
if err != nil {
return nil, err
}
block.PrevHash = node.Bc.LastBlock.Hash
err = block.CalculatePoW(node.Bc.Difficulty)
if err != nil {
return nil, err
}
err = node.SignBlock(block)
if err != nil {
return nil, err
}
block.CalculateHash()
return block, nil
}
// NewBlock creates a new block with the given txs
func (node *Node) NewBlock(txs []core.Tx) (*core.Block, error) {
block := &core.Block{
Height: node.Bc.GetHeight() + 1,
PrevHash: node.Bc.LastBlock.Hash,
Txs: txs,
Miner: core.Address{},
MinerPubK: &node.PrivK.PublicKey,
Timestamp: time.Now(),
Nonce: 0,
Hash: core.Hash{},
Signature: []byte{},
}
block.CalculateHash()
err := node.SignBlock(block)
if err != nil {
return nil, err
}
return block, nil
}
// CreateGenesis creates the genesis block
// pubK is the wallet where the first coins will be created
// amount is the amount of coins that will be created
func (node *Node) CreateGenesis(pubK *ecdsa.PublicKey, amount uint64) (*core.Block, error) {
in := core.Input{
TxId: core.GenesisHashTxInput,
Vout: 0,
Value: amount,
}
var ins []core.Input
ins = append(ins, in)
out := core.Output{
Value: amount,
}
var outs []core.Output
outs = append(outs, out)
tx := core.Tx{
From: &ecdsa.PublicKey{},
To: pubK,
InputCount: uint64(0),
Inputs: []core.Input{},
Outputs: outs,
Signature: []byte{},
}
// calculate TxId
// tx.CalculateTxId()
tx.TxId = core.GenesisHashTxInput
// sign transaction
var txs []core.Tx
txs = append(txs, tx)
block := &core.Block{
Height: node.Bc.LastBlock.Height + 1,
PrevHash: node.Bc.LastBlock.Hash,
Txs: txs,
Miner: node.Addr,
MinerPubK: &node.PrivK.PublicKey,
Timestamp: time.Now(),
Nonce: uint64(0),
Hash: core.Hash{},
Signature: []byte{},
}
block.CalculateHash()
err := node.SignBlock(block)
if err != nil {
return nil, err
}
return block, nil
}
// ParseReceivedBlock is just a caller of node.Bc.AddBlock() at the Node level
func (node *Node) ParseReceivedBlock(block *core.Block) error {
err := node.Bc.AddBlock(block)
return err
}