예제 #1
0
func TestSetAnnounced(t *testing.T) {
	ut := NewUnconfirmedTxnPool()
	assert.Equal(t, len(ut.Txns), 0)
	// Unknown should be safe and a noop
	assert.NotPanics(t, func() {
		ut.SetAnnounced(cipher.SHA256{}, util.Now())
	})
	assert.Equal(t, len(ut.Txns), 0)
	utx := createUnconfirmedTxn()
	assert.True(t, utx.Announced.IsZero())
	ut.Txns[utx.Hash()] = utx
	now := util.Now()
	ut.SetAnnounced(utx.Hash(), now)
	assert.Equal(t, ut.Txns[utx.Hash()].Announced, now)
}
예제 #2
0
// Adds a coin.Transaction to the pool, or updates an existing one's timestamps
// Returns an error if txn is invalid, and whether the transaction already
// existed in the pool.
func (self *UnconfirmedTxnPool) RecordTxn(bc *coin.Blockchain,
	t coin.Transaction, addrs map[cipher.Address]byte, maxSize int,
	burnFactor uint64) (error, bool) {
	if err := VerifyTransaction(bc, &t, maxSize, burnFactor); err != nil {
		return err, false
	}
	if err := bc.VerifyTransaction(t); err != nil {
		return err, false
	}

	// Update if we already have this txn
	h := t.Hash()
	ut, ok := self.Txns[h]
	if ok {
		now := util.Now()
		ut.Received = now
		ut.Checked = now
		self.Txns[h] = ut
		return nil, true
	}

	// Add txn to index
	self.Txns[h] = self.createUnconfirmedTxn(&bc.Unspent, t, addrs)
	// Add predicted unspents
	self.Unspent[h] = coin.CreateUnspents(bc.Head().Head, t)

	return nil, false
}
예제 #3
0
// InjectTxn adds a coin.Transaction to the pool, or updates an existing one's timestamps
// Returns an error if txn is invalid, and whether the transaction already
// existed in the pool.
func (utp *UnconfirmedTxnPool) InjectTxn(bc *Blockchain,
	t coin.Transaction) (error, bool) {

	if err := t.Verify(); err != nil {
		return err, false
	}

	if err := VerifyTransactionFee(bc, &t); err != nil {
		return err, false
	}
	if err := bc.VerifyTransaction(t); err != nil {
		return err, false
	}

	// Update if we already have this txn
	h := t.Hash()
	ut, ok := utp.Txns[h]
	if ok {
		now := util.Now()
		ut.Received = now
		ut.Checked = now
		utp.Txns[h] = ut
		return nil, true
	}

	// Add txn to index
	unspent := bc.GetUnspent()
	utp.Txns[h] = utp.createUnconfirmedTxn(unspent, t)
	// Add predicted unspents
	utp.Unspent[h] = coin.CreateUnspents(bc.Head().Head, t)

	return nil, false
}
예제 #4
0
파일: unconfirmed.go 프로젝트: up4k/skycoin
// Adds a coin.Transaction to the pool, or updates an existing one's timestamps
// Returns an error if txn is invalid, and whether the transaction already
// existed in the pool.
func (self *UnconfirmedTxnPool) RecordTxn(bc *coin.Blockchain,
	t coin.Transaction, addrs map[coin.Address]byte, maxSize int,
	burnFactor uint64) (error, bool) {
	if err := VerifyTransaction(bc, &t, maxSize, burnFactor); err != nil {
		return err, false
	}
	if err := bc.VerifyTransaction(t); err != nil {
		return err, false
	}

	// Update if we already have this txn
	ut, ok := self.Txns[t.Hash()]
	if ok {
		now := util.Now()
		ut.Received = now
		ut.Checked = now
		self.Txns[ut.Txn.Hash()] = ut
		return nil, true
	}

	// Add txn to index
	self.Txns[t.Hash()] = self.createUnconfirmedTxn(&bc.Unspent, t, addrs)
	// Add predicted unspents
	uxs := coin.CreateExpectedUnspents(t)
	for i, _ := range uxs {
		self.Unspent.Add(uxs[i])
	}

	return nil, false
}
예제 #5
0
파일: unconfirmed.go 프로젝트: up4k/skycoin
// Creates an unconfirmed transaction
func (self *UnconfirmedTxnPool) createUnconfirmedTxn(bcUnsp *coin.UnspentPool,
	t coin.Transaction, addrs map[coin.Address]byte) UnconfirmedTxn {
	now := util.Now()
	ut := UnconfirmedTxn{
		Txn:          t,
		Received:     now,
		Checked:      now,
		Announced:    util.ZeroTime(),
		IsOurReceive: false,
		IsOurSpend:   false,
	}

	// Check if this unspent is related to us
	if addrs != nil {
		// Check if this is one of our receiving txns
		for i, _ := range t.Out {
			if _, ok := addrs[t.Out[i].Address]; ok {
				ut.IsOurReceive = true
				break
			}
		}
		// Check if this is one of our spending txns
		for i, _ := range t.In {
			if ux, ok := bcUnsp.Get(t.In[i]); ok {
				if _, ok := addrs[ux.Body.Address]; ok {
					ut.IsOurSpend = true
					break
				}
			}
		}
	}

	return ut
}
예제 #6
0
파일: cert.go 프로젝트: JmAbuDabi/skycoin
func main() {
	flag.Parse()

	if len(*host) == 0 {
		log.Fatalf("Missing required -host parameter")
	}

	var err error
	var notBefore time.Time
	if len(*validFrom) == 0 {
		notBefore = util.Now()
	} else {
		notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Failed to parse creation date: %v\n", err)
			os.Exit(1)
		}
	}

	err = util.GenerateCert(*certFile, *keyFile, *host, *organization, *rsaBits,
		*isCA, notBefore, *validFor)
	if err == nil {
		fmt.Printf("Created %s and %s\n", *certFile, *keyFile)
	} else {
		fmt.Fprintln(os.Stderr, "Failed to create cert and key")
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
예제 #7
0
// Send a ping if our last message sent was over pingRate ago
func (self *Pool) sendPings() {
	now := util.Now()
	for _, c := range self.Pool.Pool {
		if c.LastSent.Add(self.Config.PingRate).Before(now) {
			self.Pool.SendMessage(c, &PingMessage{})
		}
	}
}
예제 #8
0
// Removes connections that have not sent a message in too long
func (self *Pool) clearStaleConnections() {
	now := util.Now()
	for _, c := range self.Pool.Pool {
		if c.LastReceived.Add(self.Config.IdleLimit).Before(now) {
			self.Pool.Disconnect(c, DisconnectIdle)
		}
	}
}
예제 #9
0
func createUnconfirmedTxn() UnconfirmedTxn {
	ut := UnconfirmedTxn{}
	ut.Txn = coin.Transaction{}
	ut.Txn.Head.Hash = randSHA256()
	ut.Received = util.Now()
	ut.Checked = ut.Received
	ut.Announced = util.ZeroTime()
	return ut
}
예제 #10
0
func TestGenerateCert(t *testing.T) {
	defer os.Remove("certtest.pem")
	defer os.Remove("keytest.pem")
	err := GenerateCert("certtest.pem", "keytest.pem", "127.0.0.1", "org",
		2048, false, util.Now(), time.Hour*24)
	assert.Nil(t, err)
	_, err = tls.LoadX509KeyPair("certtest.pem", "keytest.pem")
	assert.Nil(t, err)
}
예제 #11
0
// Creates an unconfirmed transaction
func (utp *UnconfirmedTxnPool) createUnconfirmedTxn(bcUnsp *coin.UnspentPool,
	t coin.Transaction) UnconfirmedTxn {
	now := util.Now()
	return UnconfirmedTxn{
		Txn:       t,
		Received:  now,
		Checked:   now,
		Announced: util.ZeroTime(),
	}
}
예제 #12
0
// Creates an unconfirmed transaction
func (self *UnconfirmedTxnPool) createUnconfirmedTxn(bcUnsp *coin.UnspentPool,
	t coin.Transaction, addrs map[coin.Address]byte) UnconfirmedTxn {
	now := util.Now()
	return UnconfirmedTxn{
		Txn:       t,
		Received:  now,
		Checked:   now,
		Announced: util.ZeroTime(),
	}
}
예제 #13
0
파일: unconfirmed.go 프로젝트: up4k/skycoin
// Returns transactions in which we are a party and have not been announced
// in ago duration
func (self *UnconfirmedTxnPool) GetOldOwnedTransactions(ago time.Duration) []UnconfirmedTxn {
	txns := make([]UnconfirmedTxn, 0)
	now := util.Now()
	for _, tx := range self.Txns {
		// TODO -- don't record IsOurSpend/IsOurReceive and do lookup each time?
		// Slower but more correct
		if (tx.IsOurSpend || tx.IsOurReceive) && now.Sub(tx.Announced) > ago {
			txns = append(txns, tx)
		}
	}
	return txns
}
예제 #14
0
func TestVisorSetAnnounced(t *testing.T) {
	defer cleanupVisor()
	vc := newMasterVisorConfig(t)
	v := NewVisor(vc)

	now := util.Now()
	utx := addUnconfirmedTxn(v)
	assert.True(t, utx.Announced.IsZero())
	assert.True(t, v.Unconfirmed.Txns[utx.Hash()].Announced.IsZero())
	v.SetAnnounced(utx.Hash(), now)
	assert.False(t, v.Unconfirmed.Txns[utx.Hash()].Announced.IsZero())
	assert.Equal(t, v.Unconfirmed.Txns[utx.Hash()].Announced, now)
}
예제 #15
0
func createUnconfirmedTxn() visor.UnconfirmedTxn {
	now := util.Now()
	return visor.UnconfirmedTxn{
		Txn: coin.Transaction{
			Head: coin.TransactionHeader{
				Hash: coin.SumSHA256([]byte("cascas")),
			},
		},
		Received:  now,
		Checked:   now,
		Announced: util.ZeroTime(),
	}
}
예제 #16
0
파일: unconfirmed.go 프로젝트: up4k/skycoin
// Checks all unconfirmed txns against the blockchain. maxAge is how long
// we'll hold a txn regardless of whether it has been invalidated.
// checkPeriod is how often we check the txn against the blockchain.
func (self *UnconfirmedTxnPool) Refresh(bc *coin.Blockchain,
	checkPeriod, maxAge time.Duration) {
	now := util.Now()
	toRemove := make([]coin.SHA256, 0)
	for k, t := range self.Txns {
		if now.Sub(t.Received) >= maxAge {
			toRemove = append(toRemove, k)
		} else if now.Sub(t.Checked) >= checkPeriod {
			if bc.VerifyTransaction(t.Txn) == nil {
				t.Checked = now
				self.Txns[k] = t
			} else {
				toRemove = append(toRemove, k)
			}
		}
	}
	self.removeTxns(bc, toRemove)
}
예제 #17
0
파일: cert.go 프로젝트: JmAbuDabi/skycoin
// Checks that certFile and keyFile exist and are files, and if not,
// returns a slice of errors indicating status.
// If neither certFile nor keyFile exist, they are automatically created
// for host
func CreateCertIfNotExists(host, certFile, keyFile string) []error {
	// check that cert/key both exist, or dont
	exist, errs := certKeyXor(certFile, keyFile)
	// Automatically create a new cert if neither files exist
	if !exist && len(errs) == 0 {
		logger.Info("Creating certificate %s", certFile)
		logger.Info("Creating key %s", keyFile)
		err := util.GenerateCert(certFile, keyFile, host, "Skycoind", 2048,
			false, util.Now(), 365*24*time.Hour)
		if err == nil {
			logger.Info("Created certificate %s for host %s", certFile, host)
			logger.Info("Created key %s for host %s", keyFile, host)
		} else {
			errs = append(errs, err)
		}
	}
	return errs
}
예제 #18
0
// Refresh checks all unconfirmed txns against the blockchain. maxAge is how long
// we'll hold a txn regardless of whether it has been invalidated.
// checkPeriod is how often we check the txn against the blockchain.
func (utp *UnconfirmedTxnPool) Refresh(bc *Blockchain,
	checkPeriod, maxAge time.Duration) {

	now := util.Now()
	var toRemove []cipher.SHA256
	for k, t := range utp.Txns {
		if now.Sub(t.Received) >= maxAge {
			toRemove = append(toRemove, k)
		} else if now.Sub(t.Checked) >= checkPeriod {
			if bc.VerifyTransaction(t.Txn) == nil {
				t.Checked = now
				utp.Txns[k] = t
			} else {
				toRemove = append(toRemove, k)
			}
		}
	}
	utp.removeTxns(bc, toRemove)
}
예제 #19
0
파일: daemon.go 프로젝트: kinghuabg/skycoin
// Called when a ConnectEvent is processed off the onConnectEvent channel
func (self *Daemon) onConnect(e ConnectEvent) {
	a := e.Addr

	if e.Solicited {
		logger.Info("Connected to %s as we requested", a)
	} else {
		logger.Info("Received unsolicited connection to %s", a)
	}

	delete(self.pendingConnections, a)

	c := self.Pool.Pool.Addresses[a]
	if c == nil {
		logger.Warning("While processing an onConnect event, no pool " +
			"connection was found")
		return
	}

	blacklisted := self.Peers.Peers.IsBlacklisted(a)
	if blacklisted {
		logger.Info("%s is blacklisted, disconnecting", a)
		self.Pool.Pool.Disconnect(c, DisconnectIsBlacklisted)
		return
	}

	if self.ipCountMaxed(a) {
		logger.Info("Max connections for %s reached, disconnecting", a)
		self.Pool.Pool.Disconnect(c, DisconnectIPLimitReached)
		return
	}

	self.recordIPCount(a)

	if e.Solicited {
		self.OutgoingConnections[a] = c
	}
	self.ExpectingIntroductions[a] = util.Now()
	logger.Debug("Sending introduction message to %s", a)
	m := NewIntroductionMessage(self.Messages.Mirror, self.Config.Version,
		self.Pool.Pool.Config.Port)
	self.Pool.Pool.SendMessage(c, m)
}
예제 #20
0
파일: daemon.go 프로젝트: kinghuabg/skycoin
// Removes unsolicited connections who haven't sent a version
func (self *Daemon) cullInvalidConnections() {
	// This method only handles the erroneous people from the DHT, but not
	// malicious nodes
	now := util.Now()
	for a, t := range self.ExpectingIntroductions {
		// Forget about anyone that already disconnected
		if self.Pool.Pool.Addresses[a] == nil {
			delete(self.ExpectingIntroductions, a)
			continue
		}
		// Remove anyone that fails to send a version within introductionWait time
		if t.Add(self.Config.IntroductionWait).Before(now) {
			logger.Info("Removing %s for not sending a version", a)
			delete(self.ExpectingIntroductions, a)
			self.Pool.Pool.Disconnect(self.Pool.Pool.Addresses[a],
				DisconnectIntroductionTimeout)
			self.Peers.RemovePeer(a)
		}
	}
}
예제 #21
0
func TestRecordMessageEventNeedsIntroduction(t *testing.T) {
	// Needs Introduction but didn't get it first
	d := newDefaultDaemon()
	m := &PingMessage{}
	m.c = messageContext(addr)
	d.Pool.Pool.Addresses[addr] = m.c.Conn
	d.Pool.Pool.Pool[m.c.Conn.Id] = m.c.Conn
	assert.Equal(t, len(d.messageEvents), 0)
	d.ExpectingIntroductions[addr] = util.Now()
	d.processMessageEvent(MessageEvent{m, m.c})
	assert.Equal(t, len(d.Pool.Pool.DisconnectQueue), 1)
	if len(d.Pool.Pool.DisconnectQueue) == 0 {
		t.Fatal("DisconnectQueue empty, would block")
	}
	de := <-d.Pool.Pool.DisconnectQueue
	assert.Equal(t, de.ConnId, m.c.Conn.Id)
	assert.Equal(t, de.Reason, DisconnectNoIntroduction)
	delete(d.ExpectingIntroductions, addr)
	shutdown(d)
}
예제 #22
0
func TestRecordMessageEventIsIntroduction(t *testing.T) {
	// Needs Introduction and thats what it has received
	d := newDefaultDaemon()
	d.ExpectingIntroductions[addr] = util.Now()
	assert.Equal(t, len(d.messageEvents), 0)
	m := NewIntroductionMessage(d.Messages.Mirror, d.Config.Version,
		d.Pool.Pool.Config.Port)
	m.c = messageContext(addr)
	err := d.recordMessageEvent(m, m.c)
	assert.Nil(t, err)
	assert.Equal(t, len(d.messageEvents), 1)
	if len(d.messageEvents) == 0 {
		t.Fatal("d.messageEvents empty, would block")
	}
	me := <-d.messageEvents
	_, ok := me.Message.(*IntroductionMessage)
	assert.Equal(t, len(d.Pool.Pool.DisconnectQueue), 0)
	assert.True(t, ok)
	delete(d.ExpectingIntroductions, addr)
	shutdown(d)
}
예제 #23
0
파일: daemon.go 프로젝트: JmAbuDabi/skycoin
// Called when a ConnectEvent is processed off the onConnectEvent channel
func (self *Daemon) onConnect(c *gnet.Connection, solicited bool) {
	a := c.Addr()

	if solicited {
		logger.Info("Connected to %s as we requested", a)
	} else {
		logger.Info("Received unsolicited connection to %s", a)
	}

	serviceConList := self.pendingConnections[a] //list of services to connect to
	delete(self.pendingConnections, a)

	blacklisted := self.Peers.Peers.IsBlacklisted(a)
	if blacklisted {
		logger.Info("%s is blacklisted, disconnecting", a)
		self.Pool.Disconnect(c, DisconnectIsBlacklisted)
		return
	}

	if self.Pool.Addresses[a] != nil {
		logger.Info("Already connected to %s, disconnecting", a)
		self.Pool.Disconnect(c, DisconnectConnectedTwice)
	}

	if solicited {
		self.OutgoingConnections[a] = c
	}
	self.ExpectingIntroductions[a] = util.Now()
	logger.Debug("Sending introduction message to %s", a)

	m := NewIntroductionMessage(MirrorConstant, self.Config.Version,
		self.Pool.Config.Port)
	self.Service.Send(c, m)

	//send connection message to each service in list
	for _, service := range serviceConList {
		self.ConnectToService(c, service)
	}
}
예제 #24
0
func TestGetOldOwnedTransactions(t *testing.T) {
	mv := setupMasterVisor()
	up := mv.Unconfirmed

	// Setup txns
	notOursNew, err := makeValidTxn(mv)
	assert.Nil(t, err)
	notOursOld, err := makeValidTxn(mv)
	assert.Nil(t, err)
	ourSpendNew, err := makeValidTxn(mv)
	assert.Nil(t, err)
	ourSpendOld, err := makeValidTxn(mv)
	assert.Nil(t, err)
	ourReceiveNew, err := makeValidTxn(mv)
	assert.Nil(t, err)
	ourReceiveOld, err := makeValidTxn(mv)
	assert.Nil(t, err)
	ourBothNew, err := makeValidTxn(mv)
	assert.Nil(t, err)
	ourBothOld, err := makeValidTxn(mv)
	assert.Nil(t, err)

	// Add a transaction that is not ours, both new and old
	err, known := up.RecordTxn(mv.blockchain, notOursNew, nil, testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)
	up.SetAnnounced(notOursNew.Hash(), util.Now())
	err, known = up.RecordTxn(mv.blockchain, notOursOld, nil, testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)

	// Add a transaction that is our spend, both new and old
	addrs := make(map[cipher.Address]byte, 1)
	ux, ok := mv.blockchain.Unspent.Get(ourSpendNew.In[0])
	assert.True(t, ok)
	addrs[ux.Body.Address] = byte(1)
	err, known = up.RecordTxn(mv.blockchain, ourSpendNew, addrs, testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)
	up.SetAnnounced(ourSpendNew.Hash(), util.Now())
	addrs = make(map[cipher.Address]byte, 1)
	ux, ok = mv.blockchain.Unspent.Get(ourSpendNew.In[0])
	assert.True(t, ok)
	addrs[ux.Body.Address] = byte(1)
	err, known = up.RecordTxn(mv.blockchain, ourSpendOld, addrs, testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)

	// Add a transaction that is our receive, both new and old
	addrs = make(map[cipher.Address]byte, 1)
	addrs[ourReceiveNew.Out[1].Address] = byte(1)
	err, known = up.RecordTxn(mv.blockchain, ourReceiveNew, addrs,
		testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)
	up.SetAnnounced(ourReceiveNew.Hash(), util.Now())
	addrs = make(map[cipher.Address]byte, 1)
	addrs[ourReceiveOld.Out[1].Address] = byte(1)
	err, known = up.RecordTxn(mv.blockchain, ourReceiveOld, addrs,
		testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)
	// Add a transaction that is both our spend and receive, both new and old
	addrs = make(map[cipher.Address]byte, 2)
	ux, ok = mv.blockchain.Unspent.Get(ourBothNew.In[0])
	assert.True(t, ok)
	addrs[ux.Body.Address] = byte(1)
	addrs[ourBothNew.Out[1].Address] = byte(1)
	assert.Equal(t, len(addrs), 2)
	err, known = up.RecordTxn(mv.blockchain, ourBothNew, addrs, testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)
	up.SetAnnounced(ourBothNew.Hash(), util.Now())
	addrs = make(map[cipher.Address]byte, 1)
	ux, ok = mv.blockchain.Unspent.Get(ourBothOld.In[0])
	assert.True(t, ok)
	addrs[ux.Body.Address] = byte(1)
	addrs[ourBothOld.Out[1].Address] = byte(1)
	assert.Equal(t, len(addrs), 2)
	err, known = up.RecordTxn(mv.blockchain, ourBothOld, addrs, testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)
}
예제 #25
0
func testRefresh(t *testing.T, mv *Visor,
	refresh func(checkPeriod, maxAge time.Duration)) {
	up := mv.Unconfirmed
	// Add a transaction that is invalid, but will not be checked yet
	// Add a transaction that is invalid, and will be checked and removed
	invalidTxUnchecked, err := makeValidTxn(mv)
	assert.Nil(t, err)
	invalidTxChecked, err := makeValidTxn(mv)
	assert.Nil(t, err)
	assert.Nil(t, invalidTxUnchecked.Verify())
	assert.Nil(t, invalidTxChecked.Verify())
	// Invalidate it by spending the output that this txn references
	invalidator, err := makeValidTxn(mv)
	assert.Nil(t, err)
	assert.Nil(t, up.InjectTxn(mv.blockchain, invalidator, nil, false))
	assert.Equal(t, len(up.Txns), 1)
	_, err = mv.CreateAndExecuteBlock()
	assert.Nil(t, err)
	assert.Equal(t, len(up.Txns), 0)
	assert.NotNil(t, mv.blockchain.VerifyTransaction(invalidTxUnchecked))
	assert.NotNil(t, mv.blockchain.VerifyTransaction(invalidTxChecked))

	invalidUtxUnchecked := UnconfirmedTxn{
		Txn:       invalidTxUnchecked,
		Received:  util.Now(),
		Checked:   util.Now(),
		Announced: util.ZeroTime(),
	}
	invalidUtxChecked := invalidUtxUnchecked
	invalidUtxChecked.Txn = invalidTxChecked
	invalidUtxUnchecked.Checked = util.Now().Add(time.Hour)
	invalidUtxChecked.Checked = util.Now().Add(-time.Hour)
	up.Txns[invalidUtxUnchecked.Hash()] = invalidUtxUnchecked
	up.Txns[invalidUtxChecked.Hash()] = invalidUtxChecked
	assert.Equal(t, len(up.Txns), 2)
	bh := coin.BlockHeader{}
	for _, ux := range mv.blockchain.TxUxOut(invalidTxUnchecked, bh) {
		up.Unspent.Add(ux)
	}
	for _, ux := range mv.blockchain.TxUxOut(invalidTxChecked, bh) {
		up.Unspent.Add(ux)
	}
	// Add a transaction that is valid, and will not be checked yet
	validTxUnchecked, err := makeValidTxn(mv)
	assert.Nil(t, err)
	assert.Nil(t, up.InjectTxn(mv.blockchain, validTxUnchecked, nil, false))
	assert.Equal(t, len(up.Txns), 3)
	validUtxUnchecked := up.Txns[validTxUnchecked.Hash()]
	validUtxUnchecked.Checked = util.Now().Add(time.Hour)
	up.Txns[validUtxUnchecked.Hash()] = validUtxUnchecked
	// Add a transaction that is valid, and will be checked
	validTxChecked, err := makeValidTxn(mv)
	assert.Nil(t, err)
	assert.Nil(t, up.InjectTxn(mv.blockchain, validTxChecked, nil, false))
	assert.Equal(t, len(up.Txns), 4)
	validUtxChecked := up.Txns[validTxChecked.Hash()]
	validUtxChecked.Checked = util.Now().Add(-time.Hour)
	up.Txns[validUtxChecked.Hash()] = validUtxChecked
	// Add a transaction that is expired
	validTxExpired, err := makeValidTxn(mv)
	assert.Nil(t, err)
	assert.Nil(t, up.InjectTxn(mv.blockchain, validTxExpired, nil, false))
	assert.Equal(t, len(up.Txns), 5)
	validUtxExpired := up.Txns[validTxExpired.Hash()]
	validUtxExpired.Received = util.Now().Add(-time.Hour)
	up.Txns[validTxExpired.Hash()] = validUtxExpired

	// Pre-sanity check
	assert.Equal(t, len(up.Unspent.Arr), 2*5)
	assert.Equal(t, len(up.Txns), 5)

	// Refresh
	checkPeriod := time.Second * 2
	maxAge := time.Second * 4
	refresh(checkPeriod, maxAge)

	// All utxns that are unchecked should be exactly the same
	assert.Equal(t, up.Txns[validUtxUnchecked.Hash()], validUtxUnchecked)
	assert.Equal(t, up.Txns[invalidUtxUnchecked.Hash()], invalidUtxUnchecked)
	// The valid one that is checked should have its checked status updated
	validUtxCheckedUpdated := up.Txns[validUtxChecked.Hash()]
	assert.True(t, validUtxCheckedUpdated.Checked.After(validUtxChecked.Checked))
	validUtxChecked.Checked = validUtxCheckedUpdated.Checked
	assert.Equal(t, validUtxChecked, validUtxCheckedUpdated)
	// The invalid checked one and the expired one should be removed
	_, ok := up.Txns[invalidUtxChecked.Hash()]
	assert.False(t, ok)
	_, ok = up.Txns[validUtxExpired.Hash()]
	assert.False(t, ok)
	// Also, the unspents should have 2 * nRemaining
	assert.Equal(t, len(up.Unspent.Arr), 2*3)
	assert.Equal(t, len(up.Txns), 3)
}
예제 #26
0
func NewMessages(c MessagesConfig) *Messages {
	return &Messages{
		Config: c,
		Mirror: rand.New(rand.NewSource(util.Now().UnixNano())).Uint32(),
	}
}
예제 #27
0
// Sets all txns as announced
func (self *Visor) SetTxnsAnnounced(txns []coin.SHA256) {
	now := util.Now()
	for _, h := range txns {
		self.Visor.Unconfirmed.SetAnnounced(h, now)
	}
}
예제 #28
0
func TestGetOldOwnedTransactions(t *testing.T) {
	mv := setupMasterVisor()
	up := mv.Unconfirmed

	// Setup txns
	notOursNew, err := makeValidTxn(mv)
	assert.Nil(t, err)
	notOursOld, err := makeValidTxn(mv)
	assert.Nil(t, err)
	ourSpendNew, err := makeValidTxn(mv)
	assert.Nil(t, err)
	ourSpendOld, err := makeValidTxn(mv)
	assert.Nil(t, err)
	ourReceiveNew, err := makeValidTxn(mv)
	assert.Nil(t, err)
	ourReceiveOld, err := makeValidTxn(mv)
	assert.Nil(t, err)
	ourBothNew, err := makeValidTxn(mv)
	assert.Nil(t, err)
	ourBothOld, err := makeValidTxn(mv)
	assert.Nil(t, err)

	// Add a transaction that is not ours, both new and old
	err, known := up.RecordTxn(mv.blockchain, notOursNew, nil, testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)
	up.SetAnnounced(notOursNew.Hash(), util.Now())
	err, known = up.RecordTxn(mv.blockchain, notOursOld, nil, testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)

	// Add a transaction that is our spend, both new and old
	addrs := make(map[coin.Address]byte, 1)
	ux, ok := mv.blockchain.Unspent.Get(ourSpendNew.In[0])
	assert.True(t, ok)
	addrs[ux.Body.Address] = byte(1)
	err, known = up.RecordTxn(mv.blockchain, ourSpendNew, addrs, testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)
	up.SetAnnounced(ourSpendNew.Hash(), util.Now())
	addrs = make(map[coin.Address]byte, 1)
	ux, ok = mv.blockchain.Unspent.Get(ourSpendNew.In[0])
	assert.True(t, ok)
	addrs[ux.Body.Address] = byte(1)
	err, known = up.RecordTxn(mv.blockchain, ourSpendOld, addrs, testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)

	// Add a transaction that is our receive, both new and old
	addrs = make(map[coin.Address]byte, 1)
	addrs[ourReceiveNew.Out[1].Address] = byte(1)
	err, known = up.RecordTxn(mv.blockchain, ourReceiveNew, addrs,
		testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)
	up.SetAnnounced(ourReceiveNew.Hash(), util.Now())
	addrs = make(map[coin.Address]byte, 1)
	addrs[ourReceiveOld.Out[1].Address] = byte(1)
	err, known = up.RecordTxn(mv.blockchain, ourReceiveOld, addrs,
		testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)
	// Add a transaction that is both our spend and receive, both new and old
	addrs = make(map[coin.Address]byte, 2)
	ux, ok = mv.blockchain.Unspent.Get(ourBothNew.In[0])
	assert.True(t, ok)
	addrs[ux.Body.Address] = byte(1)
	addrs[ourBothNew.Out[1].Address] = byte(1)
	assert.Equal(t, len(addrs), 2)
	err, known = up.RecordTxn(mv.blockchain, ourBothNew, addrs, testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)
	up.SetAnnounced(ourBothNew.Hash(), util.Now())
	addrs = make(map[coin.Address]byte, 1)
	ux, ok = mv.blockchain.Unspent.Get(ourBothOld.In[0])
	assert.True(t, ok)
	addrs[ux.Body.Address] = byte(1)
	addrs[ourBothOld.Out[1].Address] = byte(1)
	assert.Equal(t, len(addrs), 2)
	err, known = up.RecordTxn(mv.blockchain, ourBothOld, addrs, testBlockSize, 0)
	assert.Nil(t, err)
	assert.False(t, known)

	// Get the old owned txns
	utxns := up.GetOldOwnedTransactions(time.Hour)

	// Check that the 3 txns are ones we are interested in and old enough
	assert.Equal(t, len(utxns), 3)
	mapTxns := make(map[coin.SHA256]bool)
	txns := make(coin.Transactions, len(utxns))
	for i, utx := range utxns {
		txns[i] = utx.Txn
		assert.True(t, utx.IsOurSpend || utx.IsOurReceive)
		assert.True(t, utx.Announced.IsZero())
		mapTxns[utx.Hash()] = true
	}
	assert.Equal(t, len(mapTxns), 3)
	txns = coin.SortTransactions(txns, getFee)
	expectTxns := coin.Transactions{ourSpendOld, ourReceiveOld, ourBothOld}
	expectTxns = coin.SortTransactions(expectTxns, getFee)
	assert.Equal(t, txns, expectTxns)
}