@ -0,0 +1,73 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"time" |
|||
) |
|||
|
|||
type Input struct { |
|||
} |
|||
type Output struct { |
|||
} |
|||
|
|||
// Tx holds the data structure of a transaction
|
|||
type Tx struct { |
|||
From Address |
|||
To Address |
|||
InputCount uint64 |
|||
Inputs []Input |
|||
Outputs []Output |
|||
} |
|||
|
|||
func NewTx(from, to Address, in []Input, out []Output) *Tx { |
|||
tx := &Tx{ |
|||
From: from, |
|||
To: to, |
|||
InputCount: uint64(len(in)), |
|||
Inputs: in, |
|||
Outputs: out, |
|||
} |
|||
return tx |
|||
} |
|||
|
|||
// Block holds the data structure for the block
|
|||
type Block struct { |
|||
Height uint64 |
|||
PrevHash Hash |
|||
NextHash Hash |
|||
Txs []Tx |
|||
Miner Address |
|||
Timestamp time.Time |
|||
Nonce uint64 |
|||
Hash Hash |
|||
Signature []byte |
|||
} |
|||
|
|||
// Bytes outputs a byte array containing the data of the Block
|
|||
func (blk Block) Bytes() []byte { |
|||
b, _ := json.Marshal(blk) |
|||
return b |
|||
} |
|||
|
|||
func (blk *Block) GetNonce() uint64 { |
|||
return blk.Nonce |
|||
} |
|||
|
|||
func (blk *Block) IncrementNonce() { |
|||
blk.Nonce++ |
|||
} |
|||
func (block *Block) CalculatePoW(difficulty int) error { |
|||
hash := HashBytes(block.Bytes()) |
|||
for !CheckPoW(hash, difficulty) { |
|||
block.IncrementNonce() |
|||
hash = HashBytes(block.Bytes()) |
|||
} |
|||
block.Hash = hash |
|||
return nil |
|||
} |
|||
|
|||
func BlockFromBytes(b []byte) (*Block, error) { |
|||
var block *Block |
|||
err := json.Unmarshal(b, &block) |
|||
return block, err |
|||
} |
@ -0,0 +1,68 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"testing" |
|||
"time" |
|||
|
|||
"github.com/stretchr/testify/assert" |
|||
) |
|||
|
|||
func TestBlock(t *testing.T) { |
|||
block := &Block{ |
|||
PrevHash: HashBytes([]byte("prevhash")), |
|||
NextHash: HashBytes([]byte("nextHash")), |
|||
Txs: []Tx{}, |
|||
Miner: Address(HashBytes([]byte("addrfromminer"))), |
|||
Timestamp: time.Now(), |
|||
Nonce: 0, |
|||
Hash: HashBytes([]byte("blockhash")), |
|||
} |
|||
|
|||
block, err := BlockFromBytes(block.Bytes()) |
|||
assert.Nil(t, err) |
|||
assert.Equal(t, block.Bytes(), block.Bytes()) |
|||
|
|||
difficulty := 2 |
|||
nonce, err := CalculatePoW(block, difficulty) |
|||
assert.Nil(t, err) |
|||
block.Nonce = nonce |
|||
h := HashBytes(block.Bytes()) |
|||
|
|||
// CheckPoW
|
|||
assert.True(t, CheckPoW(h, difficulty)) |
|||
} |
|||
|
|||
func TestNewBlock(t *testing.T) { |
|||
block := &Block{ |
|||
PrevHash: HashBytes([]byte("prevhash")), |
|||
NextHash: HashBytes([]byte("nextHash")), |
|||
Txs: []Tx{}, |
|||
Miner: Address(HashBytes([]byte("addrfromminer"))), |
|||
Timestamp: time.Now(), |
|||
Nonce: 0, |
|||
Hash: HashBytes([]byte("blockhash")), |
|||
} |
|||
|
|||
block2, err := BlockFromBytes(block.Bytes()) |
|||
assert.Nil(t, err) |
|||
assert.Equal(t, block2.Bytes(), block.Bytes()) |
|||
|
|||
difficulty := 2 |
|||
nonce, err := CalculatePoW(block, difficulty) |
|||
assert.Nil(t, err) |
|||
block.Nonce = nonce |
|||
h := HashBytes(block.Bytes()) |
|||
|
|||
// CheckPoW
|
|||
assert.True(t, CheckPoW(h, difficulty)) |
|||
} |
|||
|
|||
func TestTx(t *testing.T) { |
|||
addr0 := Address(HashBytes([]byte("addr0"))) |
|||
addr1 := Address(HashBytes([]byte("addr1"))) |
|||
|
|||
tx := NewTx(addr0, addr1, []Input{}, []Output{}) |
|||
|
|||
assert.Equal(t, tx.From, addr0) |
|||
assert.Equal(t, tx.To, addr1) |
|||
} |