<commit_before>package api

import (
	"sync"
	"time"

	"golang.org/x/net/context"

	"chain/api/asset"
	"chain/api/issuer"
	"chain/api/txbuilder"
	"chain/database/pg"
	"chain/errors"
	"chain/fedchain/bc"
	"chain/metrics"
	"chain/net/http/reqid"
	"chain/net/trace/span"
)

// POST /v3/assets/:assetID/issue
func issueAsset(ctx context.Context, assetIDStr string, reqDests []*Destination) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)
	if err := assetAuthz(ctx, assetIDStr); err != nil {
		return nil, err
	}

	var assetID bc.AssetID
	err := assetID.UnmarshalText([]byte(assetIDStr))
	if err != nil {
		return nil, errors.WithDetailf(ErrBadBuildRequest, "invalid asset id %q", assetIDStr)
	}

	// Where asset_ids are not specified in destinations - and even
	// where they are - use the one passed in above.
	for _, dest := range reqDests {
		dest.AssetID = &assetID
	}

	dests := make([]*txbuilder.Destination, 0, len(reqDests))
	for _, reqDest := range reqDests {
		parsed, err := reqDest.parse(ctx)
		if err != nil {
			return nil, err
		}
		dests = append(dests, parsed)
	}

	template, err := issuer.Issue(ctx, assetID, dests)
	if err != nil {
		return nil, err
	}

	ret := map[string]interface{}{"template": template}
	return ret, nil
}

func buildSingle(ctx context.Context, req *BuildRequest) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)
	dbtx, ctx, err := pg.Begin(ctx)
	if err != nil {
		return nil, err
	}
	defer dbtx.Rollback(ctx)

	prevTx, sources, destinations, err := req.parse(ctx)
	if err != nil {
		return nil, err
	}

	tpl, err := txbuilder.Build(ctx, prevTx, sources, destinations, req.Metadata, req.ResTime)
	if err != nil {
		return nil, err
	}

	err = dbtx.Commit(ctx)
	if err != nil {
		return nil, err
	}

	return map[string]interface{}{"template": tpl}, nil
}

// POST /v3/transact/build
// Idempotent
func build(ctx context.Context, buildReqs []*BuildRequest) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	if err := buildAuthz(ctx, buildReqs...); err != nil {
		return nil, err
	}<commit_msg>api: make build response inputs never return null<commit_after>package api

import (
	"sync"
	"time"

	"golang.org/x/net/context"

	"chain/api/asset"
	"chain/api/issuer"
	"chain/api/txbuilder"
	"chain/database/pg"
	"chain/errors"
	"chain/fedchain/bc"
	"chain/metrics"
	"chain/net/http/reqid"
	"chain/net/trace/span"
)

// POST /v3/assets/:assetID/issue
func issueAsset(ctx context.Context, assetIDStr string, reqDests []*Destination) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)
	if err := assetAuthz(ctx, assetIDStr); err != nil {
		return nil, err
	}

	var assetID bc.AssetID
	err := assetID.UnmarshalText([]byte(assetIDStr))
	if err != nil {
		return nil, errors.WithDetailf(ErrBadBuildRequest, "invalid asset id %q", assetIDStr)
	}

	// Where asset_ids are not specified in destinations - and even
	// where they are - use the one passed in above.
	for _, dest := range reqDests {
		dest.AssetID = &assetID
	}

	dests := make([]*txbuilder.Destination, 0, len(reqDests))
	for _, reqDest := range reqDests {
		parsed, err := reqDest.parse(ctx)
		if err != nil {
			return nil, err
		}
		dests = append(dests, parsed)
	}

	template, err := issuer.Issue(ctx, assetID, dests)
	if err != nil {
		return nil, err
	}

	ret := map[string]interface{}{"template": template}
	return ret, nil
}

func buildSingle(ctx context.Context, req *BuildRequest) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)
	dbtx, ctx, err := pg.Begin(ctx)
	if err != nil {
		return nil, err
	}
	defer dbtx.Rollback(ctx)

	prevTx, sources, destinations, err := req.parse(ctx)
	if err != nil {
		return nil, err
	}

	tpl, err := txbuilder.Build(ctx, prevTx, sources, destinations, req.Metadata, req.ResTime)
	if err != nil {
		return nil, err
	}

	err = dbtx.Commit(ctx)
	if err != nil {
		return nil, err
	}

	// ensure null is never returned for inputs
	if tpl.Inputs == nil {
		tpl.Inputs = []*txbuilder.Input{}
	}

	return map[string]interface{}{"template": tpl}, nil
}

// POST /v3/transact/build
// Idempotent
func build(ctx context.Context, buildReqs []*BuildRequest) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	if err := buildAuthz(ctx, buildReqs...); err != nil {
		return nil, err
	}
{'fraction_non_alphanumeric': 0.14648989350141273, 'fraction_numerical': 0.0013040643338404696, 'mean_word_length': 3.9913232104121477, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1302777', 'n_tokens_mistral': 1733, 'n_tokens_neox': 1662, 'n_words': 429}