func TestPeerFromReq(t *testing.T) { defer os.RemoveAll(testutil.InitDir(t)) ocCred := cred.NewOcCred() btcConf, err := util.LoadBitcoindConf("") if err != nil { t.Fatal(err) } // TODO(ortutay): this test is flakey, as we may not have any BTC at all btcCreds, err := cred.GetBtcCredInRange(0, util.B2S(1000), btcConf) if err != nil { t.Fatal(err) } req := calc.NewCalcReq([]string{"1 2 +"}) err = ocCred.SignOcReq(req) if err != nil { t.Fatal(err) } for _, bc := range *btcCreds { err = bc.SignOcReq(req, btcConf) if err != nil { t.Fatal(err) } } p, err := NewPeerFromReq(req, btcConf) if err != nil { t.Fatal(err) } if p.ID != req.ID { t.FailNow() } }
func TestBtcCredSign(t *testing.T) { printBitcoindExpected() conf, err := util.LoadBitcoindConf("") if err != nil { t.Errorf("%v", err) } ocReq := newReq() addr, err := getAnyBtcAddr(conf) if err != nil { t.Errorf("%v", err) } if err != nil { t.Errorf("%v", err) } btcCred := BtcCred{ Addr: addr, } err = btcCred.SignOcReq(ocReq, conf) if err != nil { t.Errorf("%v", err) } ok, err := VerifyOcReqSig(ocReq, conf) if err != nil { t.Errorf("%v", err) } if !ok { t.Errorf("sig did not verify") } }
func TestGetAddr(t *testing.T) { defer os.RemoveAll(testutil.InitDir(t)) btcConf, err := util.LoadBitcoindConf("") if err != nil { t.Errorf("%v", err) } req := NewPaymentAddrReq(msg.BTC) ps := PaymentService{BitcoindConf: btcConf} _, err = ps.getPaymentAddr(req) if err != nil { log.Fatal(err) } }
func TestAmountPaid(t *testing.T) { defer os.RemoveAll(testutil.InitDir(t)) btcConf, err := util.LoadBitcoindConf("") if err != nil { t.Fatal(err) } peer := Peer{ID: msg.OcID("123id")} otherPeer := Peer{ID: msg.OcID("456otherid")} addr, err := peer.PaymentAddr(1, btcConf) if err != nil { t.Fatal(err) } otherAddr, err := otherPeer.PaymentAddr(1, btcConf) if err != nil { t.Fatal(err) } fmt.Printf("addr %v other addr %v\n", addr, otherAddr) // Send some BTC to ourselves. amt := int64(1e6) cmd, err := btcjson.NewSendToAddressCmd("", addr, amt) if err != nil { log.Fatal(err) } sendBtcResp, err := util.SendBtcRpc(cmd, btcConf) _, ok := sendBtcResp.Result.(string) if !ok { log.Fatal(sendBtcResp) } // Send some BTC to another address. cmd, err = btcjson.NewSendToAddressCmd("", otherAddr, 1e6) if err != nil { log.Fatal(err) } sendBtcResp, err = util.SendBtcRpc(cmd, btcConf) _, ok = sendBtcResp.Result.(string) if !ok { log.Fatal(sendBtcResp) } // Verify balance pv, err := peer.AmountPaid(0, btcConf) if err != nil { log.Fatal(err) } if pv.Amount != amt { t.Fatalf("%v != %v", paid, amt) } }
func TestBtcSignRequest(t *testing.T) { printBitcoindExpected() btcConf, err := util.LoadBitcoindConf("") if err != nil { t.Errorf(err.Error()) } c, err := newClient(btcConf) if err != nil { log.Fatal(err) } err = c.BtcSignRequest(util.B2S(.08), util.B2S(.08), nil) if err != nil { log.Fatal(err) } }
func TestInvalidBtcSignatureFails(t *testing.T) { printBitcoindExpected() conf, err := util.LoadBitcoindConf("") if err != nil { t.Errorf("%v", err) } ocReq := newReq() addr, err := getAnyBtcAddr(conf) if err != nil { t.Errorf("%v", err) } if err != nil { t.Errorf("%v", err) } btcCred := BtcCred{ Addr: addr, } err = btcCred.SignOcReq(ocReq, conf) if err != nil { t.Errorf("%v", err) } originalSig := ocReq.CoinSigs[0] ocReq.CoinSigs[0] = originalSig[0:len(originalSig)-2] + "1" ok, err := VerifyOcReqSig(ocReq, conf) if ok { t.Errorf("invalid sig %v verified", ocReq.CoinSigs[0]) } if err == nil || err.Error() != "-5: Malformed base64 encoding" { t.Errorf("expected malformed base64 encoding error, but got %v", err) } originalID := ocReq.Coins[0] ocReq.Coins[0] = originalID[0:len(originalID)-2] + "1" ok, err = VerifyOcReqSig(ocReq, conf) if ok { t.Errorf("invalid node id %v verified", ocReq.Coins[0]) } if err == nil || err.Error() != "-3: Invalid address" { t.Errorf("expected invalid address error, but got %v", err) } }
func TestPeerFromReqCoinReuse(t *testing.T) { defer os.RemoveAll(testutil.InitDir(t)) ocCred1 := cred.NewOcCred() ocCred2 := cred.NewOcCred() btcConf, err := util.LoadBitcoindConf("") if err != nil { t.Fatal(err) } // TODO(ortutay): this test is flakey, as we may not have any BTC at all btcCreds, err := cred.GetBtcCredInRange(0, util.B2S(1000), btcConf) if err != nil { t.Fatal(err) } req1 := calc.NewCalcReq([]string{"1 2 +"}) err = ocCred1.SignOcReq(req1) if err != nil { t.Fatal(err) } req2 := calc.NewCalcReq([]string{"1 2 +"}) err = ocCred2.SignOcReq(req2) if err != nil { t.Fatal(err) } for _, bc := range *btcCreds { err = bc.SignOcReq(req1, btcConf) err = bc.SignOcReq(req2, btcConf) if err != nil { t.Fatal(err) } } p1, err := NewPeerFromReq(req1, btcConf) if err != nil { t.Fatal(err) } if p1.ID != req1.ID { t.FailNow() } p2, err := NewPeerFromReq(req2, btcConf) if err == nil || err != COIN_REUSE { t.Fatal("Expected COIN_REUSE error") } if p2 != nil { t.FailNow() } }
func TestGetAddr(t *testing.T) { defer os.RemoveAll(testutil.InitDir(t)) btcConf, err := util.LoadBitcoindConf("") if err != nil { t.Errorf("%v", err) } p := Peer{ID: msg.OcID("123id")} addr1, err := p.PaymentAddr(1, btcConf) if err != nil { log.Fatal(err) } addr2, err := p.PaymentAddr(1, btcConf) if err != nil { log.Fatal(err) } if addr1 != addr2 { t.Fatalf("%v != %v\n", addr1, addr2) } }
func TestPaymentRoundTrip(t *testing.T) { printBitcoindExpected() btcConf, err := util.LoadBitcoindConf("") if err != nil { t.Errorf(err.Error()) } addr := ":9443" services := make(map[string]Handler) services[calc.SERVICE_NAME] = calc.CalcService{ Conf: &conf.Conf{ Policies: []conf.Policy{ conf.Policy{ Selector: conf.PolicySelector{ Service: calc.SERVICE_NAME, Method: calc.CALCULATE_METHOD, }, Cmd: conf.MIN_FEE, Args: []interface{}{msg.PaymentValue{2e6, msg.BTC}}, }, }, }, } services[payment.SERVICE_NAME] = &payment.PaymentService{BitcoindConf: btcConf} mux := ServiceMux{ Services: services, } s := Server{ Cred: &cred.Cred{}, Addr: addr, Handler: &mux, } listener, err := net.Listen("tcp", s.Addr) defer listener.Close() if err != nil { log.Fatal(err) } c, err := newClient(btcConf) if err != nil { log.Fatal(err) } // Quote go s.Serve(listener) fmt.Printf("quote\n") calcReq := calc.NewCalcReq([]string{"1 2 +"}) work, err := calc.Measure(calcReq) if err != nil { log.Fatal(err) } quoteReq := calc.NewQuoteReq(work) fmt.Printf("quote req: %v\n", quoteReq) resp, err := c.SignAndSend(addr, quoteReq) if err != nil { log.Fatal(err) } pv, err := msg.NewPaymentValue(string(resp.Body)) fmt.Printf("resp: %v\nbody: %v\n", resp, string(resp.Body)) if err != nil { log.Fatal(err) } // Get payment address go s.Serve(listener) fmt.Printf("get payment addr\n") payAddrReq := payment.NewPaymentAddrReq(msg.BTC) fmt.Printf("req: %v\n", payAddrReq) resp, err = c.SignAndSend(addr, payAddrReq) if err != nil { log.Fatal(err) } pa, err := msg.NewPaymentAddr(string(resp.Body)) if err != nil { log.Fatal(err) } fmt.Printf("resp: %v\npa: %v\n", resp, pa) // Send low payment // TODO(ortutay): separate test for this go s.Serve(listener) fmt.Printf("send req with deferred payment") lowPv := msg.PaymentValue(*pv) lowPv.Amount -= 1 calcReqLowPv := msg.OcReq(*calcReq) calcReqLowPv.AttachDeferredPayment(&lowPv) resp, err = c.SignAndSend(addr, &calcReqLowPv) if resp.Status != msg.TOO_LOW { log.Fatalf("expected status %v, got %v", msg.TOO_LOW, resp.Status) } // Send requested payment as deferred go s.Serve(listener) fmt.Printf("send req with deferred payment") calcReq.AttachDeferredPayment(pv) resp, err = c.SignAndSend(addr, calcReq) if resp.Status != msg.OK { log.Fatalf("expected status %v, got %v", msg.OK, resp.Status) } fmt.Printf("resp: %v\n", resp) // We got the response, now send the actual payment // (normally, we would want to verify the results) go s.Serve(listener) txid, err := c.SendBtcPayment(pv, pa) if err != nil { log.Fatal(err) } txidReq := payment.NewBtcTxidReq(txid) if err != nil { log.Fatal(err) } fmt.Printf("txid req: %v\n", txidReq) resp, err = c.SignAndSend(addr, txidReq) if resp.Status != msg.OK { log.Fatalf("expected status %v, got %v", msg.OK, resp.Status) } fmt.Printf("resp: %v\n", resp) }
func main() { goopt.Parse(nil) cmdArgs := make([]string, 0) for _, arg := range os.Args[1:] { if arg[0] != '-' { cmdArgs = append(cmdArgs, arg) } } fmt.Printf("cmd args: %v\n", cmdArgs) config, err := makeConf(*fMinFee, *fMinCoins, *fMaxWork) if err != nil { log.Fatal(err.Error()) } config.AddPolicy(&conf.Policy{ Selector: conf.PolicySelector{}, Cmd: conf.MAX_BALANCE, Args: []interface{}{getPaymentValue("", *fMaxBalance)}, }) // TODO(ortutay): s/"store"/store.SERVICE_NAME/ config.AddPolicy(&conf.Policy{ Selector: conf.PolicySelector{Service: "store"}, Cmd: conf.STORE_DIR, Args: []interface{}{*fStoreDir}, }) config.AddPolicy(&conf.Policy{ Selector: conf.PolicySelector{Service: "store"}, Cmd: conf.STORE_MAX_SPACE, Args: []interface{}{getSpace("", *fStoreMaxSpace)}, }) config.AddPolicy(&conf.Policy{ Selector: conf.PolicySelector{Service: "store"}, Cmd: conf.STORE_GB_PRICE_PER_MO, Args: []interface{}{getPaymentValue("", *fStoreGbPricePerMo)}, }) fmt.Printf("running with conf: %v\n", config) util.SetAppDir(*fAppDir) ocCred, err := cred.NewOcCredLoadOrCreate("") if err != nil { log.Fatal(err.Error()) } // TODO(ortutay): really, this should be flags to the binary so that we don't // spend people's coins without explicit intent bConf, err := util.LoadBitcoindConf("") if err != nil { log.Fatal(err.Error()) } addr := fmt.Sprintf(":%v", *fPort) // TODO(ortutay): configure which services to run from command line args calcService := calc.CalcService{Conf: config} paymentService := payment.PaymentService{Conf: config, BitcoindConf: bConf} storeService := store.StoreService{Conf: config} services := make(map[string]node.Handler) services[calc.SERVICE_NAME] = &calcService services[payment.SERVICE_NAME] = &paymentService services[store.SERVICE_NAME] = &storeService mux := node.ServiceMux{ Services: services, } wakers := []node.PeriodicWaker{&storeService} s := node.Server{ Cred: &cred.Cred{ OcCred: *ocCred, BtcConf: bConf, Coins: []cred.BtcCred{}, }, BtcConf: bConf, Conf: config, Addr: addr, Handler: &mux, PeriodicWakers: wakers, } err = s.ListenAndServe() if err != nil { log.Fatal(err.Error()) } }
func main() { goopt.Parse(nil) util.SetAppDir(*fAppDir) ocCred, err := cred.NewOcCredLoadOrCreate("") if err != nil { log.Fatal(err.Error()) } bConf, err := util.LoadBitcoindConf("") if err != nil { log.Fatal(err.Error()) } pvLower, err := msg.NewPaymentValueParseString(*fCoinsLower) if err != nil { log.Fatal(err) } pvUpper, err := msg.NewPaymentValueParseString(*fCoinsUpper) if err != nil { log.Fatal(err) } coins, err := cred.GetBtcCredInRange(pvLower.Amount, pvUpper.Amount, bConf) if err != nil { log.Fatal(err.Error()) } c := node.Client{ BtcConf: bConf, Cred: cred.Cred{ OcCred: *ocCred, BtcConf: bConf, Coins: *coins, }, } var body []byte if !termutil.Isatty(os.Stdin.Fd()) { var err error body, err = ioutil.ReadAll(os.Stdin) util.Ferr(err) } cmdArgs := make([]string, 0) for _, arg := range os.Args[1:] { if arg[0] != '-' { cmdArgs = append(cmdArgs, arg) } } if len(cmdArgs) == 0 { // TODO(ortutay): print usage info return } var req *msg.OcReq switch cmdArgs[0] { case "quote": qReq, err := makeQuoteReq(cmdArgs[1:]) if err != nil { log.Fatal(err.Error()) } resp := sendRequest(&c, qReq) if resp.Status == msg.OK { var pv msg.PaymentValue err := json.Unmarshal(resp.Body, &pv) if err != nil { panic(err) } fmt.Printf("\n%v%v\n", util.S2B(pv.Amount), pv.Currency) } case "call": req, err = makeReq(cmdArgs[1:], body) if err != nil { log.Fatal(err.Error()) } resp := sendRequest(&c, req) switch fmt.Sprintf("%v.%v", req.Service, req.Method) { case "payment.balance": { var br payment.BalanceResponse err := json.Unmarshal(resp.Body, &br) if err != nil { log.Fatalf("malformed response") } fmt.Printf("\nServer reports balance of %v%v (max allowed is %v%v)\n", util.S2B(br.Balance.Amount), br.Balance.Currency, util.S2B(br.MaxBalance.Amount), br.MaxBalance.Currency) } } case "pay": payBtc(&c, cmdArgs) case "listrep": sel := rep.Record{} if len(cmdArgs) > 1 { selJson := cmdArgs[1] err := json.Unmarshal([]byte(selJson), &sel) if err != nil { log.Fatal(err.Error()) } fmt.Printf("sel json: %v %v\n", selJson, sel) } err := rep.PrettyPrint(&sel) if err != nil { log.Fatal(err.Error()) } default: fmt.Printf("unrecognized command: %v", cmdArgs) } }