Exemple #1
0
func TestEncodeDecode(t *testing.T) {
	privateKey := generateKey(t)
	txn1, rand := trans.NewNameReservation("my-new-repository")
	txn1e := trans.NewEnvelope(types.EmptyHash(), txn1)
	txn2, _ := trans.NewNameAllocation("my-new-repository", rand)
	txn2e := trans.NewEnvelope(types.EmptyHash(), txn2)
	txn3, _ := trans.NewNameDeallocation("my-new-repository")
	txn3e := trans.NewEnvelope(types.EmptyHash(), txn3)

	txn1e.Sign(privateKey)
	txn2e.Sign(privateKey)
	txn3e.Sign(privateKey)

	transactions := []*trans.Envelope{txn1e, txn2e, txn3e}
	block, err := NewBlock(types.EmptyHash(), HIGHEST_TARGET, transactions)
	if err != nil {
		t.Errorf("can't create a block because of %v", err)
	}

	enc, err := block.Encode()
	if err != nil {
		t.Errorf("error while encoding block: %v", err)
	}

	block1, err := Decode(enc)
	if err != nil {
		t.Errorf("error while encoding block: %v", err)
	}

	assert.Equal(t, block, block1, "encoded and decoded block should be identical to the original one")
}
Exemple #2
0
func fixtureSampleTransactions(t *testing.T) ([]*transaction.Envelope, *ecdsa.PrivateKey) {
	privateKey := generateECDSAKey(t)
	txn1, rand := transaction.NewNameReservation("my-new-repository")
	txn1e := transaction.NewEnvelope(types.EmptyHash(), txn1)
	txn1e.Sign(privateKey)
	txn2, _ := transaction.NewNameAllocation("my-new-repository", rand)
	txn2e := transaction.NewEnvelope(txn1e.Hash(), txn2)
	txn2e.Sign(privateKey)
	txn3, _ := transaction.NewNameDeallocation("my-new-repository")
	txn3e := transaction.NewEnvelope(txn2e.Hash(), txn3)
	txn3e.Sign(privateKey)

	return []*transaction.Envelope{txn1e, txn2e, txn3e}, privateKey
}
Exemple #3
0
func (service *NameService) NameAllocation(r *http.Request, args *NameAllocationArgs, reply *NameAllocationReply) 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")
	}
	random, err := hex.DecodeString(args.Random)
	if err != nil {
		return err
	}
	tx, err := transaction.NewNameAllocation(args.Name, random)
	if err != nil {
		return err
	}

	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())
	service.srv.Router.Pub(txe, "/transaction")
	return nil
}
Exemple #4
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
}
Exemple #5
0
func TestNewBlock(t *testing.T) {
	privateKey := generateKey(t)
	txn1, rand := trans.NewNameReservation("my-new-repository")
	txn1e := trans.NewEnvelope(types.EmptyHash(), txn1)
	txn2, _ := trans.NewNameAllocation("my-new-repository", rand)
	txn2e := trans.NewEnvelope(types.EmptyHash(), txn2)
	txn3, _ := trans.NewNameDeallocation("my-new-repository")
	txn3e := trans.NewEnvelope(types.EmptyHash(), txn3)

	txn1e.Sign(privateKey)
	txn2e.Sign(privateKey)
	txn3e.Sign(privateKey)

	transactions := []*trans.Envelope{txn1e, txn2e, txn3e}
	block1, err := NewBlock(types.EmptyHash(), HIGHEST_TARGET, transactions)

	if err != nil {
		t.Errorf("can't create a block because of %v", err)
	}

	assert.Equal(t, transactions, block1.Transactions)
	assert.NotEqual(t, block1.MerkleRootHash, types.EmptyHash())
}
Exemple #6
0
func prepareBAT(srv *context.T, log log15.Logger) *transaction.Envelope {
	key, err := srv.DB.GetMainKey()
	if err != nil {
		log.Error("error while attempting to retrieve main key", "err", err)
	}
	if key != nil {
		bat, err := transaction.NewBlockAttribution()
		if err != nil {
			log.Error("error while creating a BAT", "err", err)
		} else {
			hash, err := srv.DB.GetPreviousEnvelopeHashForPublicKey(&key.PublicKey)
			if err != nil {
				log.Error("error while creating a BAT", "err", err)
			}
			bate := transaction.NewEnvelope(hash, bat)
			bate.Sign(key)
			return bate
		}
	}
	return nil

}
func TestPutGetDeleteTransaction(t *testing.T) {
	privateKey := generateECDSAKey(t)
	txn1, _ := transaction.NewNameReservation("my-new-repository")
	txn1e := transaction.NewEnvelope(types.EmptyHash(), txn1)
	txn1e.Sign(privateKey)

	db, err := NewDB("test.db")
	defer os.Remove("test.db")

	if err != nil {
		t.Errorf("error opening database: %v", err)
	}

	err = db.PutTransaction(txn1e)
	if err != nil {
		t.Errorf("error putting transaction: %v", err)
	}

	tx, err := db.GetTransaction(txn1e.Hash())
	if err != nil {
		t.Errorf("error getting transaction: %v", err)
	}

	assert.Equal(t, tx, txn1e)

	err = db.DeleteTransaction(txn1e.Hash())
	if err != nil {
		t.Errorf("error getting transaction: %v", err)
	}

	tx, err = db.GetTransaction(txn1e.Hash())
	if err != nil {
		t.Errorf("error getting transaction: %v", err)
	}

	assert.Nil(t, tx)

}
Exemple #8
0
func SetupGitRoutes(r *mux.Router, srv *context.T, log log15.Logger) {
	log = log.New("cmp", "git")
	// Git Server
	r.Methods("POST").Path("/{repository:.+}/git-upload-pack").HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
		log := log.New("cmp", "git-upload-pack")
		dec := pktline.NewDecoder(req.Body)
		resp.Header().Add("Cache-Control", "no-cache")
		resp.Header().Add("Content-Type", "application/x-git-upload-pack-result")
		enc := pktline.NewEncoder(resp)

		var wants, haves, common []git.Hash
		var objects []git.Object
		wantsRcvd := false

		for {
			var pktline []byte
			if err := dec.Decode(&pktline); err != nil {
				log.Error("error while decoding pkt-line", "err", err)
				return
			}

			switch {
			case pktline == nil:
				switch {
				case !wantsRcvd:
					wantsRcvd = true
				case wantsRcvd:
					for i := range haves {
						_, err := readObject(srv, haves[i])
						if err == nil {
							enc.Encode([]byte(fmt.Sprintf("ACK %x common\n", haves[i])))
							common = append(common, haves[i])
						} else {
							enc.Encode([]byte("NAK\n"))
						}
					}
					haves = make([]git.Hash, 0)
				}
			case bytes.Compare(pktline, []byte("done\n")) == 0:
				if len(common) == 0 {
					enc.Encode([]byte("NAK\n"))
				}
				goto done
			default:
				line := bytes.Split(pktline, []byte{' '})
				h := bytes.TrimSuffix(line[1], []byte{10})
				hash, err := hex.DecodeString(string(h))
				if err != nil {
					enc.Encode(append([]byte{3}, []byte(fmt.Sprintf("error parsing hash %s: %v\n", line[1], err))...))
					return
				}
				if string(line[0]) == "want" {
					wants = append(wants, hash)
				}
				if string(line[0]) == "have" {
					haves = append(haves, hash)
				}
			}
		}
	done:
		var err error
		for i := range wants {
			var objs []git.Object
			objs, err = processCommit(srv, wants[i], common)
			if err != nil {
				enc.Encode(append([]byte{3}, []byte(fmt.Sprintf("%s", err))...))
				return
			}
			objects = append(objects, objs...)
		}
		// filter out duplicates
		seen := make(map[string]bool)
		filteredObjects := make([]git.Object, 0)
		for i := range objects {
			hash := string(objects[i].Hash())
			if !seen[hash] {
				seen[hash] = true
				filteredObjects = append(filteredObjects, objects[i])
			}
		}
		//

		packfile := git.NewPackfile(filteredObjects)
		err = git.WritePackfile(&sideband64Writer{writer: &pktlineWriter{encoder: enc}, band: 1}, packfile)
		if err != nil {
			enc.Encode(append([]byte{3}, []byte(fmt.Sprintf("%s", err))...))
			return
		}

		enc.Encode(append([]byte{1}, pktlineToBytes(nil)...))
		enc.Encode(nil)
	})

	r.Methods("POST").Path("/{repository:.+}/git-receive-pack").HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
		reponame := mux.Vars(req)["repository"]
		var lines [][]byte
		dec := pktline.NewDecoder(req.Body)
		dec.DecodeUntilFlush(&lines)
		resp.Header().Add("Cache-Control", "no-cache")
		resp.Header().Add("Content-Type", "application/x-git-receive-pack-result")
		enc := pktline.NewEncoder(resp)

		packfile, err := git.ReadPackfile(req.Body)
		if err != nil {
			enc.Encode(append([]byte{1}, pktlineToBytes([]byte(fmt.Sprintf("unpack %v\n", err)))...))
		} else {
			enc.Encode(append([]byte{1}, pktlineToBytes([]byte("unpack ok"))...))
			for i := range packfile.Objects {
				err = git.WriteObject(packfile.Objects[i], path.Join(srv.Config.General.DataPath, "objects"))
				if err != nil {
					enc.Encode(append([]byte{3}, []byte(fmt.Sprintf("Error while writing object: %v\n", err))...))
				} else {
					srv.Router.Pub(packfile.Objects[i], "/git/object")
				}
			}
			for i := range lines {
				split := strings.Split(string(lines[i]), " ")
				old := split[0]
				new := split[1]
				ref := strings.TrimRight(split[2], string([]byte{0}))
				oldHash, err := hex.DecodeString(old)
				if err != nil {
					enc.Encode(append([]byte{3}, []byte(fmt.Sprintf("Malformed hash %s\n", old))...))
					return
				}
				newHash, err := hex.DecodeString(new)
				if err != nil {
					enc.Encode(append([]byte{3}, []byte(fmt.Sprintf("Malformed hash %s\n", new))...))
					return
				}
				tx := transaction.NewReferenceUpdate(reponame, ref, oldHash, newHash)
				key, err := srv.DB.GetMainKey()
				if err != nil {
					enc.Encode(append([]byte{3}, []byte(fmt.Sprintf("Errow while retrieving main key: %v", err))...))
					return
				}
				if key == nil {
					enc.Encode(append([]byte{3}, []byte("No main private key to sign the transaction")...))
					return
				}
				hash, err := srv.DB.GetPreviousEnvelopeHashForPublicKey(&key.PublicKey)
				if err != nil {
					enc.Encode(append([]byte{3}, []byte(fmt.Sprintf("Error while preparing transaction: %v", err))...))
					return
				}

				txe := transaction.NewEnvelope(hash, tx)
				txe.Sign(key)

				enc.Encode(append([]byte{2}, []byte(fmt.Sprintf("[gitchain] Transaction %s\n", txe.Hash()))...))
				srv.Router.Pub(txe, "/transaction")
				enc.Encode(append([]byte{1}, pktlineToBytes([]byte(fmt.Sprintf("ok %s\n", ref)))...))
			}
		}
		enc.Encode(append([]byte{1}, pktlineToBytes(nil)...))
		enc.Encode(nil)
	})

	r.Methods("GET").Path("/{repository:.+}/info/refs").HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
		req.ParseForm()
		service := req.Form["service"][0]

		reponame := mux.Vars(req)["repository"]
		repo, err := srv.DB.GetRepository(reponame)
		if err != nil {
			log.Error("error while retrieving repository", "repo", reponame, "err", err)
			resp.WriteHeader(500)
			return
		}
		if repo == nil || repo.Status == repository.PENDING {
			resp.WriteHeader(404)
			return
		}
		refs, err := srv.DB.ListRefs(reponame)
		if err != nil {
			log.Error("error listing refs", "repo", reponame, "err", err)
			resp.WriteHeader(500)
			return
		}
		reflines := make([][]byte, len(refs))
		for i := range refs {
			ref, err := srv.DB.GetRef(reponame, refs[i])
			if err != nil {
				log.Error("error getting ref", "repo", reponame, "err", err)
				resp.WriteHeader(500)
				return
			}
			refline := append(append([]byte(hex.EncodeToString(ref)), 32), []byte(refs[i])...)
			if i == 0 {
				// append capabilities
				refline = append(append(refline, 0), capabilities()...)
			}
			refline = append(refline, 10) // LF
			reflines[i] = refline
		}

		ref, err := srv.DB.GetRef(reponame, "refs/heads/master")
		if bytes.Compare(ref, make([]byte, 20)) != 0 {
			reflines = append(reflines, append(append(append([]byte(hex.EncodeToString(ref)), 32), []byte("HEAD")...), 10))
		}

		resp.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-advertisement", service))
		resp.Header().Add("Cache-Control", "no-cache")
		enc := pktline.NewEncoder(resp)
		enc.Encode([]byte(fmt.Sprintf("# service=%s\n", service)))
		enc.Encode(nil)
		if len(reflines) == 0 {
			enc.Encode(append(append(append(append([]byte("0000000000000000000000000000000000000000"), 32), nulCapabilities()...), []byte{0, 32, 10}...)))
		} else {
			for i := range reflines {
				enc.Encode(reflines[i])
			}
		}
		enc.Encode(nil)
	})

	r.Methods("GET").Path("/{repository:.+}/HEAD").HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
		reponame := mux.Vars(req)["repository"]
		ref, err := srv.DB.GetRef(reponame, "refs/heads/master")
		if err != nil {
			log.Error("error while retrieving repository HEAD", "repo", reponame, "err", err)
			resp.WriteHeader(500)
			return
		}
		resp.Header().Add("Content-Type", "text/plain")
		resp.Header().Add("Cache-Control", "no-cache")
		resp.Write([]byte(hex.EncodeToString(ref)))
	})

	r.Methods("GET").Path("/{repository:.+}/objects/{hash:.+}").HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
	})

}