func makeTransactionForChainWithHoursFee(t *testing.T, bc *Blockchain, ux coin.UxOut, sec cipher.SecKey, hours, fee uint64) (coin.Transaction, cipher.SecKey) { chrs := ux.CoinHours(bc.Time()) if chrs < hours+fee { log.Panicf("CoinHours underflow. Have %d, need at least %d", chrs, hours+fee) } assert.Equal(t, cipher.AddressFromPubKey(cipher.PubKeyFromSecKey(sec)), ux.Body.Address) knownUx, exists := bc.GetUnspent().Get(ux.Hash()) assert.True(t, exists) assert.Equal(t, knownUx, ux) tx := coin.Transaction{} tx.PushInput(ux.Hash()) p, newSec := cipher.GenerateKeyPair() addr := cipher.AddressFromPubKey(p) tx.PushOutput(addr, 1e6, hours) coinsOut := ux.Body.Coins - 1e6 if coinsOut > 0 { tx.PushOutput(genAddress, coinsOut, chrs-hours-fee) } tx.SignInputs([]cipher.SecKey{sec}) assert.Equal(t, len(tx.Sigs), 1) assert.Nil(t, cipher.ChkSig(ux.Body.Address, cipher.AddSHA256(tx.HashInner(), tx.In[0]), tx.Sigs[0])) tx.UpdateHeader() assert.Nil(t, tx.Verify()) err := bc.VerifyTransaction(tx) assert.Nil(t, err) return tx, newSec }
func TestSerialize(t *testing.T) { routeId := RandRouteId() transportId := RandTransportId() datagram := []byte{'t', 'e', 's', 't'} msg := InRouteMessage{transportId, routeId, datagram} serialized := Serialize((uint16)(MsgInRouteMessage), msg) msg1 := InRouteMessage{} err := Deserialize(serialized, &msg1) assert.Nil(t, err) assert.Equal(t, msg.TransportId, msg1.TransportId) assert.Equal(t, msg.RouteId, msg1.RouteId) assert.Equal(t, msg.Datagram, msg1.Datagram) sequence := (uint32)(rand.Intn(65536)) msg2 := TransportDatagramTransfer{RandRouteId(), sequence, datagram} serialized = Serialize((uint16)(MsgTransportDatagramTransfer), msg2) msg3 := TransportDatagramTransfer{} err = Deserialize(serialized, &msg3) assert.Nil(t, err) assert.Equal(t, msg2.RouteId, msg3.RouteId) assert.Equal(t, msg2.Sequence, msg3.Sequence) assert.Equal(t, msg2.Datagram, msg3.Datagram) nodeId, _ := cipher.GenerateKeyPair() msg4 := AddRouteControlMessage{nodeId, routeId} serialized = Serialize((uint16)(MsgAddRouteControlMessage), msg4) msg5 := AddRouteControlMessage{} err = Deserialize(serialized, &msg5) assert.Nil(t, err) assert.Equal(t, msg4.NodeId, msg5.NodeId) assert.Equal(t, msg4.RouteId, msg5.RouteId) }
func TestFullTransaction(t *testing.T) { p1, s1 := cipher.GenerateKeyPair() a1 := cipher.AddressFromPubKey(p1) bc := NewBlockchain() bc.CreateGenesisBlock(a1, _genTime, _genCoins) tx := Transaction{} ux := bc.Unspent.Array()[0] tx.PushInput(ux.Hash()) p2, s2 := cipher.GenerateKeyPair() a2 := cipher.AddressFromPubKey(p2) tx.PushOutput(a1, ux.Body.Coins-6e6, 100) tx.PushOutput(a2, 1e6, 100) tx.PushOutput(a2, 5e6, 100) tx.SignInputs([]cipher.SecKey{s1}) tx.UpdateHeader() assert.Nil(t, tx.Verify()) assert.Nil(t, bc.VerifyTransaction(tx)) b, err := bc.NewBlockFromTransactions(Transactions{tx}, bc.Time()+_incTime) assert.Nil(t, err) _, err = bc.ExecuteBlock(b) assert.Nil(t, err) txo := CreateUnspents(bc.Head().Head, tx) tx = Transaction{} assert.Equal(t, txo[0].Body.Address, a1) assert.Equal(t, txo[1].Body.Address, a2) assert.Equal(t, txo[2].Body.Address, a2) ux0, ok := bc.Unspent.Get(txo[0].Hash()) assert.True(t, ok) ux1, ok := bc.Unspent.Get(txo[1].Hash()) assert.True(t, ok) ux2, ok := bc.Unspent.Get(txo[2].Hash()) assert.True(t, ok) tx.PushInput(ux0.Hash()) tx.PushInput(ux1.Hash()) tx.PushInput(ux2.Hash()) tx.PushOutput(a2, 10e6, 200) tx.PushOutput(a1, ux.Body.Coins-10e6, 100) tx.SignInputs([]cipher.SecKey{s1, s2, s2}) tx.UpdateHeader() assert.Nil(t, tx.Verify()) assert.Nil(t, bc.VerifyTransaction(tx)) b, err = bc.NewBlockFromTransactions(Transactions{tx}, bc.Time()+_incTime) assert.Nil(t, err) _, err = bc.ExecuteBlock(b) assert.Nil(t, err) }
func TestBlockStat_01(t *testing.T) { bs := BlockStat{} bs.Init() _, seckey := cipher.GenerateKeyPair() hash := cipher.SumSHA256(secp256k1.RandByte(888)) sig := cipher.SignHash(hash, seckey) var r int = -1 r = bs.try_add_hash_and_sig(hash, cipher.Sig{}) if r != 4 { t.Log("BlockStat::try_add_hash_and_sig() failed to detect invalid signature.") t.Fail() } r = bs.try_add_hash_and_sig(cipher.SHA256{}, sig) if r != 4 { t.Log("BlockStat::try_add_hash_and_sig() failed to detect invalid hash and signature.") t.Fail() } r = bs.try_add_hash_and_sig(cipher.SHA256{}, cipher.Sig{}) if r != 4 { t.Log("BlockStat::try_add_hash_and_sig() failed to detect invalid hash and signature.") t.Fail() } //signer_pubkey, err := cipher.PubKeyFromSig(cipher.Sig{}, cipher.SHA256{}) //if err != nil { //fmt.Printf("Got pubkey='%s' from all-zero sig and all-zero hash.\n", signer_pubkey.Hex()) //} bs.frozen = true r2 := bs.try_add_hash_and_sig(hash, sig) if r2 != 3 { t.Log("BlockStat::try_add_hash_and_sig() failed to detect frozen.") t.Fail() } bs.frozen = false r3 := bs.try_add_hash_and_sig(hash, sig) if r3 != 0 { t.Log("BlockStat::try_add_hash_and_sig() failed to add.") t.Fail() } sig2 := cipher.SignHash(hash, seckey) // Redo signing. r4 := bs.try_add_hash_and_sig(hash, sig2) if r4 != 1 { t.Log("BlockStat::try_add_hash_and_sig() failed to detect duplicate (hash,pubkey).") t.Fail() } r5 := bs.try_add_hash_and_sig(hash, sig) if r5 != 1 { t.Log("BlockStat::try_add_hash_and_sig() failed to detect duplicate (hash,sig).") t.Fail() } }
func TestCrypto1(t *testing.T) { for i := 0; i < 10; i++ { _, seckey := cipher.GenerateKeyPair() if cipher.TestSecKey(seckey) != nil { t.Fatal("CRYPTOGRAPHIC INTEGRITY CHECK FAILED") } } }
func makeUxBodyWithSecret(t *testing.T) (coin.UxBody, cipher.SecKey) { p, s := cipher.GenerateKeyPair() return coin.UxBody{ SrcTransaction: cipher.SumSHA256(randBytes(t, 128)), Address: cipher.AddressFromPubKey(p), Coins: 10e6, Hours: 100, }, s }
//Generate Blockchain configuration for client only Blockchain, not intended to be synced to network func NewLocalBlockchain() Blockchain { pubkey, seckey := cipher.GenerateKeyPair() //generate new/random pubkey/private key fmt.Printf("NewLocalBlockchain: genesis address seckey= %v \n", seckey.Hex()) VC := NewBlockchain() VC.SecKey = seckey VC.Genesis.GenesisAddress = cipher.AddressFromPubKey(pubkey) VC.Genesis.GenesisTime = uint64(time.Now().Unix()) VC.InjectGenesisBlock() return VC }
func TestBlockStat_02(t *testing.T) { bs := BlockStat{} bs.Init() hash1 := cipher.SumSHA256(secp256k1.RandByte(888)) n1 := 3 for i := 0; i < n1; i++ { _, seckey := cipher.GenerateKeyPair() sig := cipher.SignHash(hash1, seckey) bs.try_add_hash_and_sig(hash1, sig) } hash2 := cipher.SumSHA256(secp256k1.RandByte(888)) n2 := 2 for i := 0; i < n2; i++ { _, seckey := cipher.GenerateKeyPair() sig := cipher.SignHash(hash2, seckey) bs.try_add_hash_and_sig(hash2, sig) } hash3 := cipher.SumSHA256(secp256k1.RandByte(888)) n3 := 1 for i := 0; i < n3; i++ { _, seckey := cipher.GenerateKeyPair() sig := cipher.SignHash(hash3, seckey) bs.try_add_hash_and_sig(hash3, sig) } best_hash, _, _ := bs.GetBestHashPubkeySig() if best_hash != hash1 { t.Log("BlockStat::try_add_hash_and_sig() or BlockStat::GetBestHashPubkeySig() issue.") t.Fail() } }
func makeTx(s cipher.SecKey, ux *UxOut, outs []outAddr, tm uint64, seq uint64) (*Transaction, UxArray, error) { if ux == nil { // genesis block tx. tx := Transaction{} tx.PushOutput(outs[0].Addr, outs[0].Coins, outs[0].Hours) _, s = cipher.GenerateKeyPair() ux := UxOut{ Head: UxHead{ Time: 100, BkSeq: 0, }, Body: UxBody{ SrcTransaction: tx.InnerHash, Address: outs[0].Addr, Coins: outs[0].Coins, Hours: outs[0].Hours, }, } return &tx, []UxOut{ux}, nil } tx := Transaction{} tx.PushInput(ux.Hash()) tx.SignInputs([]cipher.SecKey{s}) for _, o := range outs { tx.PushOutput(o.Addr, o.Coins, o.Hours) } tx.UpdateHeader() uxo := make(UxArray, len(tx.Out)) for i := range tx.Out { uxo[i] = UxOut{ Head: UxHead{ Time: tm, BkSeq: seq, }, Body: UxBody{ SrcTransaction: tx.Hash(), Address: tx.Out[i].Address, Coins: tx.Out[i].Coins, Hours: tx.Out[i].Hours, }, } } return &tx, uxo, nil }
func NewConsensusParticipantPtr(pMan ConnectionManagerInterface) *ConsensusParticipant { node := ConsensusParticipant{ pConnectionManager: pMan, block_queue: BlockchainTail{}, Incoming_block_count: 0, } node.block_queue.Init() //node.block_stat_queue.Init() // In PROD: each reads/loads the keys. In case the class does not // expect to sign anything, SecKey should not be stored. // In SIMU: generate random keys. node.SetPubkeySeckey(cipher.GenerateKeyPair()) return &node }
func TestInitDir(t *testing.T) { // dir, teardown, err := setup(t) dir, _, err := setup(t) if err != nil { t.Fatal(err) } fmt.Println(dir) // defer teardown() // check the exitence of dir. if _, err := os.Stat(dir); os.IsNotExist(err) { t.Fatal("account init dir failed") } // store some account. p, s := cipher.GenerateKeyPair() acnt := account.Account{ Pubkey: p.Hex(), Seckey: s.Hex(), } v := fmt.Sprintf(`{"active_account":"%s","accounts":[{"pubkey":"%s", "seckey":"%s"}]}`, p.Hex(), p.Hex(), s.Hex()) if err := ioutil.WriteFile(filepath.Join(dir, "data.act"), []byte(v), 0777); err != nil { t.Fatal(err) } // init dir again. account.InitDir(dir) // check if the account is loaded. a, err := account.Get(p.Hex()) if err != nil { t.Fatal(err) } assert.Equal(t, acnt.Pubkey, a.Pubkey) assert.Equal(t, acnt.Seckey, a.Seckey) activeAccount, err := account.GetActive() if err != nil { t.Fatal(err) } assert.Equal(t, activeAccount.Pubkey, p.Hex()) }
func TestVerifyTransaction(t *testing.T) { ft := FakeTree{} bc := NewBlockchain(&ft, nil) gb := bc.CreateGenesisBlock(genAddress, _genCoins, _genTime) // Genesis block is not valid by normal standards assert.NotNil(t, bc.VerifyTransaction(gb.Body.Transactions[0])) assert.Equal(t, bc.Len(), uint64(1)) _, ux := addBlockToBlockchain(t, bc) assert.Equal(t, bc.Len(), uint64(3)) // Valid txn tx, _ := makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100, 50) assert.Nil(t, bc.VerifyTransaction(tx)) assert.Equal(t, bc.Len(), uint64(3)) // Failure, spending unknown output tx, _ = makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100, 50) tx.Sigs = nil tx.In[0] = cipher.SHA256{} tx.SignInputs([]cipher.SecKey{genSecret}) tx.UpdateHeader() assertError(t, bc.VerifyTransaction(tx), "Unspent output does not exist") assert.Equal(t, bc.Len(), uint64(3)) // Failure, duplicate input tx, _ = makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100, 50) tx.Sigs = nil tx.In = append(tx.In, tx.In[0]) tx.SignInputs([]cipher.SecKey{genSecret, genSecret}) tx.UpdateHeader() assertError(t, bc.VerifyTransaction(tx), "Duplicate spend") assert.Equal(t, bc.Len(), uint64(3)) // Failure, zero coin output tx, _ = makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100, 50) tx.Sigs = nil tx.PushOutput(genAddress, 0, 100) tx.SignInputs([]cipher.SecKey{genSecret}) tx.UpdateHeader() assertError(t, bc.VerifyTransaction(tx), "Zero coin output") // Failure, hash collision with unspents tx, _ = makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100, 50) uxOut := coin.CreateUnspents(bc.Head().Head, tx) bc.GetUnspent().Add(uxOut[0]) assertError(t, bc.VerifyTransaction(tx), "New unspent collides with existing unspent") // Failure, not spending enough coins tx, _ = makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100, 50) tx.PushOutput(genAddress, 10e6, 100) tx.Sigs = nil tx.SignInputs([]cipher.SecKey{genSecret}) tx.UpdateHeader() assertError(t, bc.VerifyTransaction(tx), "Insufficient coins") // Failure, spending outputs we don't own _, s := cipher.GenerateKeyPair() tx = coin.Transaction{} for _, u := range bc.GetUnspent().Pool { if u.Body.Address != genAddress { ux = u break } } assert.NotEqual(t, ux.Body.Address, genAddress) tx.PushInput(ux.Hash()) tx.PushOutput(genAddress, ux.Body.Coins, ux.Body.Hours) tx.SignInputs([]cipher.SecKey{s}) tx.UpdateHeader() assertError(t, bc.VerifyTransaction(tx), "Signature not valid for output being spent") // Failure, wrong signature for txn hash tx = coin.Transaction{} tx.PushInput(ux.Hash()) tx.SignInputs([]cipher.SecKey{genSecret}) tx.PushOutput(genAddress, ux.Body.Coins, ux.Body.Hours) tx.UpdateHeader() assertError(t, bc.VerifyTransaction(tx), "Signature not valid for output being spent") }
func NewWalletEntry() WalletEntry { pub, sec := cipher.GenerateKeyPair() return NewWalletEntryFromKeypair(pub, sec) }
func makeAddress() cipher.Address { p, _ := cipher.GenerateKeyPair() return cipher.AddressFromPubKey(p) }
func init() { _, s := cipher.GenerateKeyPair() gSeckey = s.Hex() }
func _gensec() cipher.SecKey { _, s := cipher.GenerateKeyPair() return s }
package coin import ( "encoding/hex" "math/rand" "testing" "time" "github.com/skycoin/skycoin/src/cipher" "github.com/stretchr/testify/assert" ) var ( genPublic, genSecret = cipher.GenerateKeyPair() genAddress = cipher.AddressFromPubKey(genPublic) testMaxSize = 1024 * 1024 _genTime uint64 = 1000 _incTime uint64 = 3600 * 1000 _genCoins uint64 = 1000e6 _genCoinHours uint64 = 1000 * 1000 ) func assertError(t *testing.T, err error, msg string) { assert.NotNil(t, err) assert.Equal(t, err.Error(), msg) } func tNow() uint64 { return uint64(time.Now().UTC().Unix()) }
func CreatePubKey() cipher.PubKey { pub, _ := cipher.GenerateKeyPair() return pub }
func TestVerifyTransactionSpending(t *testing.T) { ft := FakeTree{} bc := NewBlockchain(&ft, nil) bc.CreateGenesisBlock(genAddress, _genCoins, _genTime) // Overspending hours tx := coin.Transaction{} uxs := bc.GetUnspent().Array() tx.PushInput(uxs[0].Hash()) tx.PushOutput(genAddress, 1e6, uxs[0].Body.Hours) tx.PushOutput(genAddress, uxs[0].Body.Coins-1e6, 1) uxIn, err := bc.GetUnspent().GetMultiple(tx.In) assert.Nil(t, err) uxOut := coin.CreateUnspents(bc.Head().Head, tx) assertError(t, coin.VerifyTransactionSpending(bc.Time(), uxIn, uxOut), "Insufficient coin hours") // add block to blockchain. _, ux := addBlockToBlockchain(t, bc) // addBlockToBlockchain(t, bc) // Valid tx, _ = makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100, 50) uxIn, err = bc.GetUnspent().GetMultiple(tx.In) assert.Nil(t, err) uxOut = coin.CreateUnspents(bc.Head().Head, tx) assert.Nil(t, coin.VerifyTransactionSpending(bc.Time(), uxIn, uxOut)) // Destroying coins tx = coin.Transaction{} tx.PushInput(ux.Hash()) tx.PushOutput(genAddress, 1e6, 100) tx.PushOutput(genAddress, 10e6, 100) uxIn, err = bc.GetUnspent().GetMultiple(tx.In) assert.Nil(t, err) uxOut = coin.CreateUnspents(bc.Head().Head, tx) err = coin.VerifyTransactionSpending(bc.Time(), uxIn, uxOut) assert.NotNil(t, err) assert.Equal(t, err.Error(), "Transactions may not create or destroy coins") assertError(t, coin.VerifyTransactionSpending(bc.Time(), uxIn, uxOut), "Transactions may not create or destroy coins") // Insufficient coins tx = coin.Transaction{} tx.PushInput(ux.Hash()) p, s := cipher.GenerateKeyPair() a := cipher.AddressFromPubKey(p) coins := ux.Body.Coins assert.True(t, coins > 1e6) tx.PushOutput(a, 1e6, 100) tx.PushOutput(genAddress, coins-1e6, 100) tx.SignInputs([]cipher.SecKey{genSecret}) tx.UpdateHeader() b, err := bc.NewBlockFromTransactions(coin.Transactions{tx}, bc.Time()+_incTime) assert.Nil(t, err) uxs, err = bc.ExecuteBlock(&b) assert.Nil(t, err) tx = coin.Transaction{} tx.PushInput(uxs[0].Hash()) tx.PushOutput(a, 10e6, 1) tx.SignInputs([]cipher.SecKey{s}) tx.UpdateHeader() uxIn, err = bc.GetUnspent().GetMultiple(tx.In) assert.Nil(t, err) uxOut = coin.CreateUnspents(bc.Head().Head, tx) assertError(t, coin.VerifyTransactionSpending(bc.Time(), uxIn, uxOut), "Insufficient coins") }