Beispiel #1
0
func (ps *PaymentService) balance(req *msg.OcReq) (*msg.OcResp, error) {
	p, err := peer.NewPeerFromReq(req, ps.BitcoindConf)
	if err != nil {
		return msg.NewRespError(msg.SERVER_ERROR), nil
	}
	balance, err := p.Balance(0, ps.BitcoindConf)
	if err != nil {
		return msg.NewRespError(msg.SERVER_ERROR), nil
	}
	maxBalanceConf, err := ps.Conf.PolicyForCmd(conf.MAX_BALANCE)
	if err != nil {
		// TODO(ortutay): handle more configuration around max balance
		panic(err)
	}
	maxBalance := maxBalanceConf.Args[0].(*msg.PaymentValue)
	btcAddr, err := p.PaymentAddr(ADDRS_PER_ID, ps.BitcoindConf)
	if err != nil {
		return msg.NewRespError(msg.SERVER_ERROR), nil
	}
	resp := BalanceResponse{
		Balance:    balance,
		MaxBalance: maxBalance,
		Addr:       btcAddr,
	}
	body, err := json.Marshal(&resp)
	if err != nil {
		return msg.NewRespError(msg.SERVER_ERROR), nil
	}
	return msg.NewRespOk(body), nil
}
Beispiel #2
0
func (ps *PaymentService) getPaymentAddr(req *msg.OcReq) (*msg.OcResp, error) {
	if len(req.Args) > 1 {
		return msg.NewRespError(msg.INVALID_ARGUMENTS), nil
	}
	reqCurrency := string(msg.BTC)
	if len(req.Args) == 1 {
		reqCurrency = strings.ToUpper(req.Args[0])
	}
	p, err := peer.NewPeerFromReq(req, ps.BitcoindConf)
	if err != nil {
		return msg.NewRespError(msg.SERVER_ERROR), nil
	}
	switch reqCurrency {
	case string(msg.BTC):
		if ps.BitcoindConf == nil {
			return msg.NewRespError(msg.SERVER_ERROR), nil
		}
		// TODO(ortutay): smarter handling to map request ID to address
		btcAddr, err := p.PaymentAddr(ADDRS_PER_ID, ps.BitcoindConf)
		if err != nil {
			return msg.NewRespError(msg.SERVER_ERROR), nil
		}
		payAddr := msg.PaymentAddr{Currency: msg.BTC, Addr: btcAddr}
		return msg.NewRespOk([]byte(payAddr.String())), nil
	default:
		return msg.NewRespError(msg.CURRENCY_UNSUPPORTED), nil
	}
}
Beispiel #3
0
func (ss *StoreService) get(req *msg.OcReq) (*msg.OcResp, error) {
	var containerID ContainerID
	var blobID BlobID
	if len(req.Args) == 1 {
		containerID = ocIDToContainerID(req.ID)
		blobID = BlobID(req.Args[0])
	} else if len(req.Args) == 2 {
		if req.Args[0] == "." {
			containerID = ocIDToContainerID(req.ID)
		} else {
			containerID = ContainerID(req.Args[0])
		}
		blobID = BlobID(req.Args[1])
	} else {
		return msg.NewRespError(msg.INVALID_ARGUMENTS), nil
	}

	fmt.Printf("get %v %v\n", containerID, blobID)

	if containerID != ocIDToContainerID(req.ID) {
		resp := msg.NewRespErrorWithBody(msg.INVALID_ARGUMENTS,
			[]byte("Cannot access that container"))
		return resp, nil
	}

	container := NewContainerFromDisk(req.ID)
	if !container.HasBlobID(blobID) {
		resp := msg.NewRespErrorWithBody(msg.INVALID_ARGUMENTS,
			[]byte("Cannot access that blob"))
		return resp, nil
	}

	blob, err := NewBlobFromDisk(blobID)
	if err != nil {
		return msg.NewRespError(msg.SERVER_ERROR), nil
	}
	var buf bytes.Buffer
	for _, block := range blob.Blocks {
		_, err := buf.Write(block.Data)
		if err != nil {
			return msg.NewRespError(msg.SERVER_ERROR), nil
		}
	}
	return msg.NewRespOk(buf.Bytes()), nil
}
Beispiel #4
0
func (cs CalcService) quote(req *msg.OcReq) (*msg.OcResp, error) {
	reqMethod := req.Args[0]
	var reqWork Work
	err := json.Unmarshal([]byte(req.Args[1]), &reqWork)
	if err != nil {
		return msg.NewRespError(msg.INVALID_ARGUMENTS), nil
	}
	if reqMethod != CALCULATE_METHOD {
		return msg.NewRespError(msg.INVALID_ARGUMENTS), nil
	}

	pv, err := cs.paymentForWork(&reqWork, reqMethod)
	if err != nil {
		log.Printf("server error: %v", err.Error())
		return msg.NewRespError(msg.SERVER_ERROR), nil
	}
	resp := msg.NewRespOk([]byte(pv.String()))
	return resp, nil
}
Beispiel #5
0
func (cs CalcService) calculate(req *msg.OcReq) (*msg.OcResp, error) {
	// TODO(ortutay): pull out payment verifcation logic
	work, err := Measure(req)
	if err != nil {
		log.Printf("server error: %v", err.Error())
		return msg.NewRespError(msg.SERVER_ERROR), nil
	}
	pv, err := cs.paymentForWork(work, CALCULATE_METHOD)
	if err != nil {
		log.Printf("server error: %v", err.Error())
		return msg.NewRespError(msg.SERVER_ERROR), nil
	}
	var submitTxn string
	if pv.Amount != 0 {
		fmt.Printf("want payment: %v, got payment: %v\n", pv, req.PaymentValue)
		if req.PaymentType == msg.NONE || req.PaymentValue == nil {
			return msg.NewRespError(msg.PAYMENT_REQUIRED), nil
		}
		if req.PaymentValue.Currency != pv.Currency {
			return msg.NewRespError(msg.CURRENCY_UNSUPPORTED), nil
		}
		if req.PaymentValue.Amount < pv.Amount {
			return msg.NewRespError(msg.TOO_LOW), nil
		}

		var repStatus rep.Status
		switch req.PaymentType {
		case msg.DEFER:
			// TODO(ortutay): check if we accept deferred payment for the request
			// TODO(ortutay): marking as success is pre-emptive; need to handle
			// failure case
			repStatus = rep.SUCCESS_UNPAID
		case msg.ATTACHED:
			if !btc.TxnIsValid(req.PaymentTxn, req.PaymentValue) {
				return msg.NewRespError(msg.INVALID_TXN), nil
			}
			submitTxn = req.PaymentTxn
			// TODO(ortutay): same note as above about pre-emptive success mark
			repStatus = rep.SUCCESS_PAID
		}
		rec := rep.Record{
			Role:         rep.SERVER,
			Service:      SERVICE_NAME,
			Method:       CALCULATE_METHOD,
			Timestamp:    int(time.Now().Unix()),
			ID:           req.ID,
			Status:       repStatus,
			PaymentType:  msg.DEFER,
			PaymentValue: pv,
			Perf:         nil,
		}
		fmt.Printf("rep rec: %v\n", rec)
		id, err := rep.Put(&rec)
		if err != nil {
			return nil, fmt.Errorf("local database error: %v", err)
		}
		fmt.Printf("stored rep rec, %v %v\n", id, err)
	}

	var results []string
	for _, q := range req.Args {
		tokens := strings.Split(q, " ")
		var stack []float64
		for _, token := range tokens {
			switch token {
			case "+":
				r := stack[len(stack)-1] + stack[len(stack)-2]
				stack = stack[0 : len(stack)-2]
				stack = append(stack, r)
			case "-":
				r := stack[len(stack)-2] - stack[len(stack)-1]
				stack = stack[0 : len(stack)-2]
				stack = append(stack, r)
			case "/":
				r := stack[len(stack)-2] / stack[len(stack)-1]
				stack = stack[0 : len(stack)-2]
				stack = append(stack, r)
			case "*":
				r := stack[len(stack)-1] * stack[len(stack)-2]
				stack = stack[0 : len(stack)-2]
				stack = append(stack, r)
			default:
				f, err := strconv.ParseFloat(token, 54)
				stack = append(stack, f)
				if err != nil {
					return nil, errors.New("didn't understand \"" + token + "\"")
				}
			}
		}
		if len(stack) != 1 {
			return nil, errors.New("invalid expression")
		}
		results = append(results, fmt.Sprintf("%v", stack[0]))
	}
	resp := msg.NewRespOk([]byte(strings.Join(results, " ")))
	if submitTxn != "" {
		_ = btc.SubmitTxn(submitTxn)
	}
	return resp, nil
}
Beispiel #6
0
func (ss *StoreService) put(req *msg.OcReq) (*msg.OcResp, error) {
	var containerID ContainerID
	var blobID BlobID
	if len(req.Args) == 0 {
		containerID = ocIDToContainerID(req.ID)
		// blob will be read from request
	} else if len(req.Args) == 1 {
		if req.Args[0] == "." {
			containerID = ocIDToContainerID(req.ID)
		} else {
			containerID = ContainerID(req.Args[0])
		}
		// blob will be read from request
	} else if len(req.Args) == 2 {
		if req.Args[0] == "." {
			containerID = ocIDToContainerID(req.ID)
		} else {
			containerID = ContainerID(req.Args[0])
		}
		blobID = BlobID(req.Args[1])
	} else {
		return msg.NewRespError(msg.INVALID_ARGUMENTS), nil
	}

	if containerID != ocIDToContainerID(req.ID) {
		resp := msg.NewRespErrorWithBody(msg.INVALID_ARGUMENTS,
			[]byte("Cannot access that container"))
		return resp, nil
	}

	fmt.Printf("put request for: %v %v\n", containerID, blobID)

	// Store blob if it is new
	blob, err := NewBlobFromDisk(blobID)
	if blob == nil {
		if req.Body == nil || len(req.Body) == 0 {
			// TODO(ortutay): Neither "OK" nor "error" are appropriate status codes
			// in this case. It may be useful to have a third error class, but not
			// sure what to call it.
			return msg.NewRespOk([]byte("Please re-send with data.")), nil
		}
		if len(req.Body) > MAX_BLOB_BYTES {
			resp := msg.NewRespErrorWithBody(msg.CANNOT_COMPLETE_REQUEST,
				[]byte(fmt.Sprintf("Cannot store over %v",
					util.ByteSize(MAX_BLOB_BYTES).String())))
			return resp, nil
		}
		blob, err = NewBlobFromReader(bytes.NewReader(req.Body))
		if err != nil {
			return msg.NewRespError(msg.SERVER_ERROR), nil
		}
		err := storeBlob(blob)
		if err != nil {
			return msg.NewRespError(msg.SERVER_ERROR), nil
		}
	}

	// Append blob-id to container-id
	container := NewContainerFromDisk(req.ID)
	for _, id := range container.BlobIDs {
		if id == blob.ID {
			return msg.NewRespOk([]byte("")), nil
		}
	}
	container.WriteNewBlobID(blob.ID)

	return msg.NewRespOk([]byte(blob.ID.String())), nil
}
Beispiel #7
0
func (ss *StoreService) alloc(req *msg.OcReq) (*msg.OcResp, error) {
	// TODO(ortutay): may want multiple contianers per client
	id := ocIDToContainerID(req.ID)
	return msg.NewRespOk([]byte(id.String())), nil
}