示例#1
0
func (db *T) PutTransaction(tx *transaction.Envelope) (e error) {
	writable(&e, db, func(dbtx *bolt.Tx) bool {
		bucket, e := dbtx.CreateBucketIfNotExists([]byte("transactions"))
		if e != nil {
			return false
		}
		encoded, e := tx.Encode()
		if e != nil {
			return false
		}
		e = bucket.Put(tx.Hash(), encoded)
		if e != nil {
			return false
		}
		return true
	})
	return
}
示例#2
0
func NameRegistrar(srv *context.T) {
	log := srv.Log.New("cmp", "name")
	ch := srv.Router.Sub("/block/last")
loop:
	select {
	case blki := <-ch:
		if blk, ok := blki.(*block.Block); ok {
			processPendingAllocations(srv, log)
			for i := range blk.Transactions {
				tx0 := blk.Transactions[i]
				tx := tx0.Transaction
				switch tx.(type) {
				case *transaction.NameAllocation:
					log.Debug("processing name allocation transaction", "txn", tx0)
					tx1 := tx.(*transaction.NameAllocation)
					// 1. find the reservation
					// 1.1. check if it was done with this server and there's a reference
					//      in scrap records
					reservation, err := srv.DB.GetScrap(util.SHA256(append(tx1.Rand, []byte(tx1.Name)...)))
					var reservationTx *transaction.Envelope
					if reservation == nil || err != nil {
						// 1.2 no scrap found, so try searching throughout database
						curBlock, err := srv.DB.GetLastBlock()
						if err != nil {
							log.Error("can't find last block during name allocation attempt")
							break
						}
						for curBlock != nil {
							for i := range curBlock.Transactions {
								if isValidReservation(curBlock.Transactions[i], tx0) {
									reservationTx = curBlock.Transactions[i]
								}
							}

							h := curBlock.PreviousBlockHash
							curBlock, err = srv.DB.GetBlock(h)
							if err != nil {
								log.Error("can't find block during name allocation attempt", "txn", h, "err", err)
								break
							}
						}

					} else {
						blk, err := srv.DB.GetTransactionBlock(reservation)
						if err != nil {
							log.Error("can't find block for name reservation", "txn", reservationTx, "err", err)
							break
						}
						for i := range blk.Transactions {
							if isValidReservation(blk.Transactions[i], tx0) {
								reservationTx = blk.Transactions[i]
								break
							}
						}

					}

					if reservationTx == nil {
						log.Error("can't find corresponding name reservation for allocation", "txn", tx0)
						break
					}

					// 2. verify its maturity
					confirmations, err := srv.DB.GetTransactionConfirmations(reservationTx.Hash())
					if err != nil {
						log.Error("can't compute number of confirmations for reservation", "txn", reservationTx.Hash(), "err", err)
						break
					}

					if confirmations >= RESERVATION_CONFIRMATIONS_REQUIRED {
						// this reservation is confirmed
						srv.DB.PutRepository(repository.NewRepository(tx1.Name, repository.PENDING, tx0.Hash()))
						log.Info("created pending repository", "repo", tx1.Name, "alloc_txn", tx0.Hash())
					} else {
						// this allocation is wasted as the distance is not long enough
					}
				default:
					// ignore all other transactions
				}
			}
		}
	}
	goto loop
}