func TestNewBlockHeaderPanics(t *testing.T) { ct := uint64(100) head := coin.BlockHeader{Time: ct} assert.Panics(t, func() { coin.NewBlockHeader(head, coin.NewUnspentPool(), ct, 50, coin.BlockBody{}) }) assert.Panics(t, func() { coin.NewBlockHeader(head, coin.NewUnspentPool(), ct-1, 50, coin.BlockBody{}) }) assert.Panics(t, func() { coin.NewBlockHeader(head, coin.NewUnspentPool(), ct-ct, 50, coin.BlockBody{}) }) assert.NotPanics(t, func() { coin.NewBlockHeader(head, coin.NewUnspentPool(), ct+1, 50, coin.BlockBody{}) }) }
func (fbc *fakeBlockchain) CreateGenesisBlock(genesisAddr cipher.Address, genesisCoins, timestamp uint64) coin.Block { txn := coin.Transaction{} txn.PushOutput(genesisAddr, genesisCoins, genesisCoins) body := coin.BlockBody{coin.Transactions{txn}} prevHash := cipher.SHA256{} head := coin.BlockHeader{ Time: timestamp, BodyHash: body.Hash(), PrevHash: prevHash, BkSeq: 0, Version: 0, Fee: 0, UxHash: coin.NewUnspentPool().GetUxHash(), } b := coin.Block{ Head: head, Body: body, } // b.Body.Transactions[0].UpdateHeader() fbc.blocks = append(fbc.blocks, b) ux := coin.UxOut{ Head: coin.UxHead{ Time: timestamp, BkSeq: 0, }, Body: coin.UxBody{ SrcTransaction: txn.InnerHash, //user inner hash Address: genesisAddr, Coins: genesisCoins, Hours: genesisCoins, // Allocate 1 coin hour per coin }, } fbc.unspent.Add(ux) return b }
func TestNewBlock(t *testing.T) { // TODO -- update this test for newBlock changes prev := coin.Block{Head: coin.BlockHeader{Version: 0x02, Time: 100, BkSeq: 98}} unsp := coin.NewUnspentPool() unsp.XorHash = randSHA256() txns := coin.Transactions{coin.Transaction{}} // invalid txn fees panics assert.Panics(t, func() { coin.NewBlock(prev, 133, unsp, txns, _badFeeCalc) }) // no txns panics assert.Panics(t, func() { coin.NewBlock(prev, 133, unsp, nil, _feeCalc) }) assert.Panics(t, func() { coin.NewBlock(prev, 133, unsp, coin.Transactions{}, _feeCalc) }) // valid block is fine fee := uint64(121) currentTime := uint64(133) b := coin.NewBlock(prev, currentTime, unsp, txns, _makeFeeCalc(fee)) assert.Equal(t, b.Body.Transactions, txns) assert.Equal(t, b.Head.Fee, fee*uint64(len(txns))) assert.Equal(t, b.Body, coin.BlockBody{txns}) assert.Equal(t, b.Head.PrevHash, prev.HashHeader()) assert.Equal(t, b.Head.Time, currentTime) assert.Equal(t, b.Head.BkSeq, prev.Head.BkSeq+1) assert.Equal(t, b.Head.UxHash, unsp.GetUxHash()) }
func (self SerializedBlockchain) ToBlockchain() *coin.Blockchain { bc := &coin.Blockchain{} bc.Blocks = self.Blocks pool := coin.NewUnspentPool() pool.Rebuild(self.Unspents) bc.Unspent = pool return bc }
func TestGetUxHash(t *testing.T) { unsp := coin.NewUnspentPool() xor := randSHA256() unsp.XorHash = xor //prev := randSHA256(t) sh := unsp.GetUxHash() assert.True(t, bytes.Equal(xor[:], sh[:])) assert.NotEqual(t, sh, [4]byte{}) }
// NewBlockchain use the walker go throught the tree and update the head and unspent outputs. func NewBlockchain(tree BlockTree, walker Walker) *Blockchain { bc := &Blockchain{ tree: tree, walker: walker, unspent: coin.NewUnspentPool(), } bc.walkTree() return bc }
func createUnconfirmedTxns(t *testing.T, up *UnconfirmedTxnPool, n int) []UnconfirmedTxn { uts := make([]UnconfirmedTxn, 4) usp := coin.NewUnspentPool() for i := 0; i < len(uts); i++ { tx, _ := makeValidTxn() ut := up.createUnconfirmedTxn(&usp, tx) uts[i] = ut up.Txns[ut.Hash()] = ut } assert.Equal(t, len(up.Txns), 4) return uts }
func TestSpendsForAddresses(t *testing.T) { up := NewUnconfirmedTxnPool() unspent := coin.NewUnspentPool() addrs := make(map[cipher.Address]byte, 0) n := 4 useAddrs := make([]cipher.Address, n) for i, _ := range useAddrs { useAddrs[i] = makeAddress() } useAddrs[1] = useAddrs[0] for _, a := range useAddrs { addrs[a] = byte(1) } // Make confirmed transactions to add to unspent pool uxs := make(coin.UxArray, 0) for i := 0; i < n; i++ { txn := coin.Transaction{} txn.PushInput(randSHA256()) txn.PushOutput(useAddrs[i], 10e6, 1000) uxa := coin.CreateUnspents(coin.BlockHeader{}, txn) for _, ux := range uxa { unspent.Add(ux) } uxs = append(uxs, uxa...) } assert.Equal(t, len(uxs), 4) // Make unconfirmed txns that spend those unspents for i := 0; i < n; i++ { txn := coin.Transaction{} txn.PushInput(uxs[i].Hash()) txn.PushOutput(makeAddress(), 10e6, 1000) ut := UnconfirmedTxn{ Txn: txn, } up.Txns[ut.Hash()] = ut } // Now look them up assert.Equal(t, len(addrs), 3) assert.Equal(t, len(up.Txns), 4) auxs := up.SpendsForAddresses(&unspent, addrs) assert.Equal(t, len(auxs), 3) assert.Equal(t, len(auxs[useAddrs[0]]), 2) assert.Equal(t, len(auxs[useAddrs[2]]), 1) assert.Equal(t, len(auxs[useAddrs[3]]), 1) assert.Equal(t, auxs[useAddrs[0]], coin.UxArray{uxs[0], uxs[1]}) assert.Equal(t, auxs[useAddrs[2]], coin.UxArray{uxs[2]}) assert.Equal(t, auxs[useAddrs[3]], coin.UxArray{uxs[3]}) }
func makeValidTxn() (coin.Transaction, error) { w := wallet.NewWallet("test") w.GenerateAddresses(2) uncf := NewUnconfirmedTxnPool() now := tNow() a := makeAddress() uxs := makeUxBalancesForAddresses([]wallet.Balance{ wallet.Balance{10e6, 150}, wallet.Balance{15e6, 150}, }, now, w.GetAddresses()[:2]) unsp := coin.NewUnspentPool() addUxArrayToUnspentPool(&unsp, uxs) amt := wallet.Balance{10 * 1e6, 0} return CreateSpendingTransaction(w, uncf, &unsp, now, amt, a) }
func makeNewBlock() coin.Block { unsp := coin.NewUnspentPool() body := coin.BlockBody{ Transactions: coin.Transactions{coin.Transaction{}}, } prev := coin.Block{ Body: body, Head: coin.BlockHeader{ Version: 0x02, Time: 100, BkSeq: 0, Fee: 10, PrevHash: cipher.SHA256{}, BodyHash: body.Hash(), }} return coin.NewBlock(prev, 100+20, unsp, coin.Transactions{coin.Transaction{}}, _feeCalc) }
func TestNewBlockHeader(t *testing.T) { // TODO -- update this test for newBlockHeader changes b := makeNewBlock() prev := b.Head unsp := coin.NewUnspentPool() unsp.XorHash = randSHA256() fee := uint64(10) bh := coin.NewBlockHeader(prev, unsp, prev.Time+22, fee, b.Body) assert.Equal(t, bh.PrevHash, prev.Hash()) assert.NotEqual(t, bh.PrevHash, prev.PrevHash) assert.Equal(t, bh.Time, uint64(prev.Time+22)) assert.Equal(t, bh.BkSeq, uint64(prev.BkSeq+1)) assert.Equal(t, bh.Fee, fee) assert.Equal(t, bh.Version, prev.Version) assert.Equal(t, bh.BodyHash, b.Body.Hash()) assert.Equal(t, bh.UxHash, unsp.GetUxHash()) }
func makeInvalidTxn() (coin.Transaction, error) { w := wallet.NewWallet("test") w.GenerateAddresses(2) uncf := NewUnconfirmedTxnPool() now := tNow() a := makeAddress() uxs := makeUxBalancesForAddresses([]wallet.Balance{}, now, w.GetAddresses()[:2]) unsp := coin.NewUnspentPool() addUxArrayToUnspentPool(&unsp, uxs) amt := wallet.Balance{25 * 1e6, 0} txn, err := CreateSpendingTransaction(w, uncf, &unsp, now, amt, a) if err != nil { return txn, err } txn.Out[0].Address = cipher.Address{} return txn, nil }
func TestSerializedBlockchain(t *testing.T) { defer cleanupVisor() cleanupVisor() bc := &coin.Blockchain{} bc.Blocks = []coin.Block{} for i := uint64(0); i < 10; i++ { bc.Blocks = append(bc.Blocks, coin.Block{}) bc.Blocks[i].Head.BkSeq = i } assert.Equal(t, len(bc.Blocks), 10) bc.Unspent = coin.NewUnspentPool() for i := uint64(0); i < 10; i++ { bc.Unspent.Add(makeUxOut(t)) } assert.Equal(t, len(bc.Unspent.Pool), 10) sbc := NewSerializedBlockchain(bc) assert.Equal(t, sbc.Blocks, bc.Blocks) assert.Equal(t, len(sbc.Unspents), len(bc.Unspent.Pool)) // Back to blockchain works assert.Equal(t, bc, sbc.ToBlockchain()) // Saving and reloading works assert.Nil(t, sbc.Save(testBlockchainFile)) assertFileExists(t, testBlockchainFile) sbc2, err := LoadSerializedBlockchain(testBlockchainFile) assert.Nil(t, err) assert.Equal(t, sbc, sbc2) assert.Equal(t, bc, sbc2.ToBlockchain()) bc2, err := LoadBlockchain(testBlockchainFile) assert.Nil(t, err) assert.Equal(t, bc, bc2) }
func NewUnconfirmedTxnPool() *UnconfirmedTxnPool { return &UnconfirmedTxnPool{ Txns: make(map[coin.SHA256]UnconfirmedTxn), Unspent: coin.NewUnspentPool(), } }
func TestCreateSpendingTransaction(t *testing.T) { // Setup w := wallet.NewSimpleWallet() for i := 0; i < 4; i++ { w.CreateEntry() } uncf := NewUnconfirmedTxnPool() now := tNow() a := makeAddress() // Failing createSpends amt := wallet.Balance{0, 0} unsp := coin.NewUnspentPool() _, err := CreateSpendingTransaction(w, uncf, &unsp, now, amt, 0, 0, a) assert.NotNil(t, err) // Valid txn, fee, no change uxs := makeUxBalancesForAddresses([]wallet.Balance{ wallet.Balance{10e6, 150}, wallet.Balance{15e6, 150}, }, now, w.GetAddresses()[:2]) unsp = coin.NewUnspentPool() addUxArrayToUnspentPool(&unsp, uxs) amt = wallet.Balance{25e6, 200} tx, err := CreateSpendingTransaction(w, uncf, &unsp, now, amt, 100, 0, a) assert.Nil(t, err) assert.Equal(t, len(tx.Out), 1) assert.Equal(t, tx.Out[0], coin.TransactionOutput{ Coins: 25e6, Hours: 200, Address: a, }) assert.Equal(t, len(tx.In), 2) assert.Equal(t, tx.In, []coin.SHA256{uxs[0].Hash(), uxs[1].Hash()}) assert.Nil(t, tx.Verify()) // Valid txn, change uxs = makeUxBalancesForAddresses([]wallet.Balance{ wallet.Balance{10e6, 150}, wallet.Balance{15e6, 200}, wallet.Balance{1e6, 125}, }, now, w.GetAddresses()[:3]) unsp = coin.NewUnspentPool() addUxArrayToUnspentPool(&unsp, uxs) amt = wallet.Balance{25e6, 200} tx, err = CreateSpendingTransaction(w, uncf, &unsp, now, amt, 100, 0, a) assert.Nil(t, err) assert.Equal(t, len(tx.Out), 2) assert.Equal(t, tx.Out[0], coin.TransactionOutput{ Coins: 1e6, Hours: (150 + 200 + 125) - (200 + 100), Address: w.GetAddresses()[0], }) assert.Equal(t, tx.Out[1], coin.TransactionOutput{ Coins: 25e6, Hours: 200, Address: a, }) assert.Equal(t, len(tx.In), 3) assert.Equal(t, tx.In, []coin.SHA256{ uxs[0].Hash(), uxs[1].Hash(), uxs[2].Hash(), }) assert.Nil(t, tx.Verify()) // Valid txn, but wastes coin hours uxs = makeUxBalancesForAddresses([]wallet.Balance{ wallet.Balance{10e6, 150}, wallet.Balance{15e6, 200}, }, now, w.GetAddresses()[:2]) unsp = coin.NewUnspentPool() addUxArrayToUnspentPool(&unsp, uxs) amt = wallet.Balance{25e6, 200} _, err = CreateSpendingTransaction(w, uncf, &unsp, now, amt, 100, 0, a) assertError(t, err, "Have enough coins, but not enough to send coin "+ "hours change back. Would spend 50 more hours than requested.") // Would be valid, but unconfirmed subtraction causes it to not be // First, make a txn to subtract uxs = makeUxBalancesForAddresses([]wallet.Balance{ wallet.Balance{10e6, 150}, wallet.Balance{15e6, 150}, }, now, w.GetAddresses()[:2]) unsp = coin.NewUnspentPool() addUxArrayToUnspentPool(&unsp, uxs) amt = wallet.Balance{25e6, 200} tx, err = CreateSpendingTransaction(w, uncf, &unsp, now, amt, 100, 0, a) assert.Nil(t, err) // Add it to the unconfirmed pool (bypass RecordTxn to avoid blockchain) uncf.Txns[tx.Hash()] = uncf.createUnconfirmedTxn(&unsp, tx, w.GetAddressSet()) // Make a spend that must not reuse previous addresses _, err = CreateSpendingTransaction(w, uncf, &unsp, now, amt, 100, 0, a) assertError(t, err, "Not enough coins") }
func TestCreateSpendingTransaction(t *testing.T) { // Setup w := wallet.NewWallet("fortest.wlt") w.GenerateAddresses(4) uncf := NewUnconfirmedTxnPool() now := tNow() a := makeAddress() // Failing createSpends amt := wallet.Balance{0, 0} unsp := coin.NewUnspentPool() _, err := CreateSpendingTransaction(w, uncf, &unsp, now, amt, a) assert.NotNil(t, err) // Valid txn, fee, no change uxs := makeUxBalancesForAddresses([]wallet.Balance{ wallet.Balance{10e6, 150}, wallet.Balance{15e6, 150}, }, now, w.GetAddresses()[:2]) unsp = coin.NewUnspentPool() addUxArrayToUnspentPool(&unsp, uxs) amt = wallet.Balance{25e6, 200} tx, err := CreateSpendingTransaction(w, uncf, &unsp, now, amt, a) assert.Nil(t, err) assert.Equal(t, len(tx.Out), 1) assert.Equal(t, tx.Out[0], coin.TransactionOutput{ Coins: 25e6, Hours: 37, Address: a, }) assert.Equal(t, len(tx.In), 2) assert.Equal(t, tx.In, []cipher.SHA256{uxs[0].Hash(), uxs[1].Hash()}) assert.Nil(t, tx.Verify()) // Valid txn, change uxs = makeUxBalancesForAddresses([]wallet.Balance{ wallet.Balance{10e6, 150}, wallet.Balance{15e6, 200}, wallet.Balance{1e6, 125}, }, now, w.GetAddresses()[:3]) unsp = coin.NewUnspentPool() addUxArrayToUnspentPool(&unsp, uxs) amt = wallet.Balance{25e6, 200} tx, err = CreateSpendingTransaction(w, uncf, &unsp, now, amt, a) assert.Nil(t, err) assert.Equal(t, len(tx.Out), 2) assert.Equal(t, tx.Out[0], coin.TransactionOutput{ Coins: 1e6, Hours: (150 + 200 + 125) / 8, Address: w.GetAddresses()[0], }) assert.Equal(t, tx.Out[1], coin.TransactionOutput{ Coins: 25e6, Hours: (150 + 200 + 125) / 8, Address: a, }) assert.Equal(t, len(tx.In), 3) assert.Equal(t, tx.In, []cipher.SHA256{ uxs[0].Hash(), uxs[1].Hash(), uxs[2].Hash(), }) assert.Nil(t, tx.Verify()) // Would be valid, but unconfirmed subtraction causes it to not be // First, make a txn to subtract uxs = makeUxBalancesForAddresses([]wallet.Balance{ wallet.Balance{10e6, 150}, wallet.Balance{15e6, 150}, }, now, w.GetAddresses()[:2]) unsp = coin.NewUnspentPool() addUxArrayToUnspentPool(&unsp, uxs) amt = wallet.Balance{25e6, 200} tx, err = CreateSpendingTransaction(w, uncf, &unsp, now, amt, a) assert.Nil(t, err) // Add it to the unconfirmed pool (bypass InjectTxn to avoid blockchain) uncf.Txns[tx.Hash()] = uncf.createUnconfirmedTxn(&unsp, tx) // Make a spend that must not reuse previous addresses _, err = CreateSpendingTransaction(w, uncf, &unsp, now, amt, a) assertError(t, err, "Not enough coins") }
func newBlockchain() historydb.Blockchainer { return &fakeBlockchain{ unspent: coin.NewUnspentPool(), } }