package node
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"time"
|
|
|
|
"github.com/arnaucube/slowlorisdb/core"
|
|
)
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func (node *Node) Sign(m []byte) (*core.Signature, error) {
|
|
return core.Sign(node.PrivK, m)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func (node *Node) AddToPendingTxs(tx core.Tx) {
|
|
node.PendingTxs = append(node.PendingTxs, tx)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func (node *Node) CreateGenesis(pubK *ecdsa.PublicKey, amount uint64) (*core.Block, error) {
|
|
// pubK is the wallet where the first coins will be created
|
|
// amount is the amount of coins that will be created
|
|
|
|
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
|
|
}
|