예제 #1
0
파일: keys.go 프로젝트: linhua55/gitchain
func ECDSAPublicKeyToString(key ecdsa.PublicKey) string {
	x := key.X.Bytes()
	y := key.Y.Bytes()
	sha := util.SHA256(append(append([]byte{0x04}, x...), y...)) // should it be 0x04?
	ripe := ripemd160.New().Sum(sha)
	ripesha := util.SHA256(ripe)
	ripedoublesha := util.SHA256(ripesha)
	head := ripedoublesha[0:3]
	final := append(ripe, head...)
	i := new(big.Int)
	i.SetBytes(final)
	var b []byte
	return string(base58.EncodeBig(b, i))
}
예제 #2
0
func (service *NameService) NameReservation(r *http.Request, args *NameReservationArgs, reply *NameReservationReply) error {
	log := service.log.New("cmp", "api_name")
	key, err := service.srv.DB.GetKey(args.Alias)
	if err != nil {
		return err
	}
	if key == nil {
		return errors.New("can't find the key")
	}
	tx, random := transaction.NewNameReservation(args.Name)

	hash, err := service.srv.DB.GetPreviousEnvelopeHashForPublicKey(&key.PublicKey)
	if err != nil {
		log.Error("error while preparing transaction", "err", err)
	}
	txe := transaction.NewEnvelope(hash, tx)
	txe.Sign(key)

	reply.Id = hex.EncodeToString(txe.Hash())
	reply.Random = hex.EncodeToString(random)
	// We save sha(random+name)=txhash to scraps to be able to find
	// the transaction hash by random and number during allocation
	service.srv.DB.PutScrap(util.SHA256(append(random, []byte(args.Name)...)), txe.Hash())
	service.srv.Router.Pub(txe, "/transaction")
	return nil
}
예제 #3
0
파일: nrt.go 프로젝트: linhua55/gitchain
func NewNameReservation(name string) (*NameReservation, []byte) {
	buf := make([]byte, 4)
	rand.Read(buf)
	return &NameReservation{
		Version: NAME_RESERVATION_VERSION,
		Hashed:  util.SHA256(append([]byte(name), buf...))}, buf
}
예제 #4
0
파일: nrt.go 프로젝트: Jaspper/gitchain
func NewNameReservation(name string, publicKey *ecdsa.PublicKey) (txn *NameReservation, random []byte) {
	buf := make([]byte, 4)
	rand.Read(buf)
	return &NameReservation{
			Version:   NAME_RESERVATION_VERSION,
			Hashed:    util.SHA256(append([]byte(name), buf...)),
			PublicKey: []byte(keys.ECDSAPublicKeyToString(*publicKey))},
		buf
}
예제 #5
0
func isValidReservation(reservation *transaction.Envelope, alloc *transaction.Envelope) bool {
	allocT := alloc.Transaction.(*transaction.NameAllocation)
	switch reservation.Transaction.(type) {
	case *transaction.NameReservation:
		tx1 := reservation.Transaction.(*transaction.NameReservation)
		return bytes.Compare(util.SHA256(append([]byte(allocT.Name), allocT.Rand...)), tx1.Hashed) == 0
	default:
		return false
	}
}
예제 #6
0
파일: auth.go 프로젝트: linhua55/gitchain
func (*KeyAuth) Valid(b []byte) bool {
	var data [][]byte
	dec := gob.NewDecoder(bytes.NewBuffer(b))
	dec.Decode(&data)
	publicKey, err := keys.DecodeECDSAPublicKey(data[0])
	if err != nil {
		panic(err) // TODO: better error handling
	}
	r := new(big.Int)
	s := new(big.Int)
	r.SetBytes(data[1])
	s.SetBytes(data[2])
	return ecdsa.Verify(publicKey, util.SHA256(data[0]), r, s)
}
예제 #7
0
파일: auth.go 프로젝트: linhua55/gitchain
func (a *KeyAuth) Marshal() []byte {
	key, err := keys.EncodeECDSAPublicKey(&a.key.PublicKey)
	if err != nil {
		panic(err) // TODO: better error handling
	}
	sigR, sigS, err := ecdsa.Sign(rand.Reader, a.key, util.SHA256(key))
	if err != nil {
		panic(err) // TODO: better error handling
	}
	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	enc.Encode([][]byte{key, sigR.Bytes(), sigS.Bytes()})
	return buf.Bytes()
}
예제 #8
0
파일: net.go 프로젝트: linhua55/gitchain
func Server(srv *context.T) {
	log := srv.Log.New("cmp", "dht")
	ch := srv.Router.Sub("/dht/join")
	tch := srv.Router.Sub("/transaction/mem")
	och := srv.Router.Sub("/git/object")

	keyAuth, err := newKeyAuth()
	if err != nil {
		log.Crit("can't generate node key", "err", err)
		os.Exit(1)
	}

	id, err := wendy.NodeIDFromBytes(util.SHA256(keyAuth.Marshal()))
	log = log.New("own_node", id)

	if err != nil {
		log15.Crit("error preparing node id", "err", err)
		os.Exit(0)
	}

	hostname := strings.Split(srv.Config.Network.Hostname, ":")[0]
	node := wendy.NewNode(id, "127.0.0.1", hostname, "localhost", srv.Config.Network.Port)

	cluster := wendy.NewCluster(node, keyAuth)
	cluster.SetLogLevel(wendy.LogLevelError)
	cluster.RegisterCallback(&GitchainApp{cluster: cluster, log: log.New(), srv: srv})
	go cluster.Listen()
	defer cluster.Stop()

	log.Info("node started")

	for i := range srv.Config.Network.Join {
		log.Info("scheduling a connection", "addr", srv.Config.Network.Join[i])
		srv.Router.Pub(srv.Config.Network.Join[i], "/dht/join")
	}

loop:
	select {
	case addri := <-ch:
		if addr, ok := addri.(string); ok {
			log.Debug("received a request to join the cluster", "addr", addr)

			addr := strings.Split(addr, ":")
			port := 31000
			if len(addr) == 2 {
				port, err = strconv.Atoi(addr[1])
				if err != nil {
					log.Error("invalid port number", "addr", addr, "port", addr[1], "err", err)
					goto loop
				}
			}
			err = cluster.Join(addr[0], port)

			if err != nil {
				log.Error("can't join cluster", "addr", addr, "err", err)
				goto loop
			}
		}
	case txei := <-tch:
		if txe, ok := txei.(*transaction.Envelope); ok {
			log.Debug("received transaction", "txn", txe)
			if err = broadcast(cluster, txe, MSG_TRANSACTION); err != nil {
				log.Error("error broadcasting a transaction message", "txn", txe, "err", err)
			} else {
				log.Debug("broadcasted transaction", "txn", txe)
			}
		}
	case obji := <-och:
		if obj, ok := obji.(git.Object); ok {
			id, err := wendy.NodeIDFromBytes(util.SHA256(obj.Hash()))
			if err != nil {
				log15.Error("error preparing msg id for a git object", "obj", obj, "err", err)
			} else {
				msg := cluster.NewMessage(MSG_REGULAR|MSG_OBJECT, id, git.ObjectToBytes(obj))
				if err = cluster.Send(msg); err != nil {
					log.Error("error sending git object", "obj", obj, "err", err)
				}
			}
		}
	}
	goto loop
}
예제 #9
0
func (e *Envelope) Hash() types.Hash {
	return util.SHA256(append(append(e.Transaction.Hash(), e.PreviousEnvelopeHash...), e.NextPublicKey...))
}
예제 #10
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
}