Преглед на файлове

bitcoin的listunspent改为异步的缓存,dcr的listunspent和listaccounts弄成异步缓存

476052856 преди 6 години
родител
ревизия
70a09b79e9
променени са 9 файла, в които са добавени 181 реда и са изтрити 110 реда
  1. BIN
      coinsapi
  2. BIN
      coinsapi.exe
  3. 38 31
      src/bitcoin/bitcoin.go
  4. 38 14
      src/bitcoin/bitcoinmain.go
  5. 5 0
      src/bitcoin/type.go
  6. 16 10
      src/dcrcash/dcrcash.go
  7. 9 10
      src/dcrcash/dcrcash_test.go
  8. 69 40
      src/dcrcash/dcrcashcoin.go
  9. 6 5
      src/dcrcash/type.go

BIN
coinsapi


BIN
coinsapi.exe


+ 38 - 31
src/bitcoin/bitcoin.go

@@ -168,7 +168,7 @@ func (m *BitCoinApi) WalleListSinceBlock(blockhash string) ([]byte, error) {
 	}
 
 	//
-	result, err := bitcoinRpc.RunCall("listsinceblock", blockhash,1,true)
+	result, err := bitcoinRpc.RunCall("listsinceblock", blockhash, 1, true)
 
 	if err != nil {
 		fmt.Println("Call listsinceblock fail:", err.Error())
@@ -378,7 +378,6 @@ func (m BitCoinApi) InitRpcConf(rpcuser string, rpcpassword string, rpchost stri
 	return true
 }
 
-
 //Adds a script (in hex) or address that can be watched as if it were in your wallet but cannot be used to spend.
 func (m BitCoinApi) WalletImportAddress(address string, rescan bool) (bool, error) {
 
@@ -411,6 +410,7 @@ func (m BitCoinApi) WalletImportAddress(address string, rescan bool) (bool, erro
 	err = errors.New(rpcResult.Error.Message)
 	return false, err
 }
+
 /*
 //list unspent transaction outputs
 func (m BitCoinApi) Listunspent(address []string) ([]UnspentInfo, error) {
@@ -440,45 +440,53 @@ func (m BitCoinApi) Listunspent(address []string) ([]UnspentInfo, error) {
 //list unspent transaction outputs
 func (m BitCoinApi) Listunspent(address []string) ([]map[string]interface{}, error) {
 
-        var unspentResult RpcUnspentResult
-        result, err := bitcoinRpc.RunCall("listunspent",1,9999999,address)
-
-        if err != nil {
-                fmt.Println("Call listunspent fail:", err.Error())
-                return nil, err
-        }
-
-        if err := json.Unmarshal([]byte(result), &unspentResult); err != nil {
-                fmt.Println("Unmarshal err :", err.Error())
-                return nil, err
-        }
-
-        // success
-        if len(unspentResult.Error.Message) != 0 {
-                err = errors.New(unspentResult.Error.Message)
-	 	return nil, err
-        }
-	var unspentValue map[string]float64
-	unspentValue = make(map[string]float64)
+	var unspentResult RpcUnspentResult
+	result, err := bitcoinRpc.RunCall("listunspent", 1, 9999999, address)
+
+	if err != nil {
+		fmt.Println("Call listunspent fail:", err.Error())
+		return nil, err
+	}
+
+	if err := json.Unmarshal([]byte(result), &unspentResult); err != nil {
+		fmt.Println("Unmarshal err :", err.Error())
+		return nil, err
+	}
+
+	// success
+	if len(unspentResult.Error.Message) != 0 {
+		err = errors.New(unspentResult.Error.Message)
+		return nil, err
+	}
+	//地址里面有相同的过滤
+
+	//var ilistunspent listunspent
+	unspentValue := map[string]*listunspent{}
+
 	for _, unspentInfo := range unspentResult.Result {
-        addr := unspentInfo.Address
-        if unspentValue[addr] == 0 {
-            unspentValue[addr] = unspentInfo.Amount
-        } else {
-            unspentValue[addr] += unspentInfo.Amount
+		addr := unspentInfo.Address
+		if addr == "" {
+			break
+		}
+		if unspentValue[addr] == nil {
+			unspentValue[addr] = &listunspent{unspentInfo.Amount, unspentInfo.Spendable}
+
+		} else {
+			unspentValue[addr].amout += unspentInfo.Amount
 		}
-	}
 
+	}
 	outputsArr := make([]map[string]interface{}, 0)
 	for k, v := range unspentValue {
 		requestData := make(map[string]interface{})
 		requestData["address"] = k
-		valuestr := fmt.Sprintf("%.8f", v)
+		valuestr := fmt.Sprintf("%.8f", v.amout)
 		value, _ := strconv.ParseFloat(valuestr, 64)
 		requestData["Amount"] = value
+		requestData["spendable"] = v.spendable
 		outputsArr = append(outputsArr, requestData)
 	}
-	return outputsArr,nil
+	return outputsArr, nil
 }
 
 //Send Raw Transaction
@@ -510,4 +518,3 @@ func (m BitCoinApi) SendRawTransaction(hexstring string) (string, error) {
 	err = errors.New(rawtransactioninfo.Error.Message)
 	return "", err
 }
-

+ 38 - 14
src/bitcoin/bitcoinmain.go

@@ -14,8 +14,9 @@ import (
 )
 
 var (
-	Config  config
-	CoinApi BitCoinApi
+	Config    config
+	CoinApi   BitCoinApi
+	m_unspent []map[string]interface{}
 )
 
 type BitCoin struct {
@@ -40,6 +41,8 @@ func (m BitCoin) InitDriver(parm interface{}) bool {
 		return false
 	}
 	go m.getwalletinfo()
+	//缓存当前未花费的
+	go listunspentpool()
 	return true
 }
 
@@ -84,7 +87,6 @@ func (m BitCoin) TransInfo(parm interface{}) ([]byte, error) {
 		LOG("DEBUG", " input para  err:%v", startH)
 		startH = 1
 	}
-
 	//get longest block count
 	blockcount, err := CoinApi.WalleGetBlockCount()
 	if err != nil {
@@ -410,24 +412,31 @@ func (m BitCoin) ChainHeight(parm interface{}) ([]byte, error) {
 }
 
 func (m BitCoin) ListUnspent(parm interface{}) ([]byte, error) {
+	i_unspent := make([]map[string]interface{}, 0)
 	pjs := parm.(*simplejson.Json)
-	address, err := pjs.Get("address").StringArray()
-	if err != nil {
-		LOG("ERROR", "  input parm error:%v", err.Error())
-		return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
-	}
-
-	unspent, err := CoinApi.Listunspent(address)
-	if err != nil {
-		LOG("ERROR", "  get listunspent:%v", err.Error())
-		return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
+	Issync, err := pjs.Get("Sync").Bool()
+	if !Issync {
+		fmt.Println("The listunspent data Asynchrony!!!!")
+		i_unspent = m_unspent
+	} else {
+		address, err := pjs.Get("address").StringArray()
+		if err != nil {
+			LOG("ERROR", "  input parm error:%v", err.Error())
+			return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
+		}
+		unspent, err := CoinApi.Listunspent(address)
+		if err != nil {
+			LOG("ERROR", "  get listunspent:%v", err.Error())
+			//return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
+		}
+		i_unspent = unspent
 	}
 
 	var jbuf []byte
 	resptmp := make(map[string]interface{})
 	resptmp["errcode"] = 0
 	resptmp["cointype"] = "BTC"
-	resptmp["unspents"] = unspent
+	resptmp["unspents"] = i_unspent
 
 	if jbuf, err = json.Marshal(resptmp); err != nil {
 		LOG("ERROR", " inner json error:%v", err.Error())
@@ -468,6 +477,21 @@ func (m BitCoin) SumcoinBalance(parm interface{}) ([]byte, error) {
 	return nil, nil
 }
 
+func listunspentpool() {
+	var address []string
+	m_unspent = make([]map[string]interface{}, 0)
+	for range time.Tick(2 * time.Minute) {
+		unspent, err := CoinApi.Listunspent(address)
+		if err != nil {
+			LOG("ERROR", "  get listunspent:%v", err.Error())
+			//return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
+		}
+
+		m_unspent = unspent
+	}
+
+}
+
 func init() {
 	Register(NameCoin, &BitCoin{})
 }

+ 5 - 0
src/bitcoin/type.go

@@ -132,3 +132,8 @@ type RpcUnspentResult struct {
 	Id     string        `json:"id"`
 }
 
+//simple   listunspent
+type listunspent struct {
+	amout     float64
+	spendable bool
+}

+ 16 - 10
src/dcrcash/dcrcash.go

@@ -59,7 +59,6 @@ func (m *DcrCashApi) WalletDumpPrivKey(address string) (string, error) {
 		return "", err
 	}
 
-	//
 	result, err := dcrcashRpc.RunCall("dumpprivkey", address)
 	if err != nil {
 		fmt.Println("Call dumpprivkey fail:", err.Error())
@@ -169,7 +168,6 @@ func (m DcrCashApi) WalleGetBalance(account string) ([]byte, error) {
 		fmt.Println("Unmarshal err :", err.Error())
 		return nil, err
 	}
-	fmt.Println("WalleGetBalance:", len(acountresult.Result.Balances))
 	// success
 	if len(acountresult.Error.Message) == 0 {
 		var jbuf []byte
@@ -386,7 +384,7 @@ func (m DcrCashApi) Listunspent(address []string) ([]map[string]interface{}, err
 	var unspentResult RpcUnspentResult
 
 	result, err := dcrcashRpc.RunCall("listunspent", 1, 9999999, address)
-	fmt.Println("Listunspent Result:", string(result))
+	//fmt.Println("Listunspent Result:", string(result))
 	if err != nil {
 		fmt.Println("Call listunspent fail:", err.Error())
 		return nil, err
@@ -403,24 +401,32 @@ func (m DcrCashApi) Listunspent(address []string) ([]map[string]interface{}, err
 		return nil, err
 	}
 
-	var unspentValue map[string]float64
-	unspentValue = make(map[string]float64)
+	//地址里面有相同的过滤
+
+	//var ilistunspent listunspent
+	unspentValue := map[string]*listunspent{}
 	for _, unspentInfo := range unspentResult.Result {
 		addr := unspentInfo.Address
-		if unspentValue[addr] == 0 {
-			unspentValue[addr] = unspentInfo.Amount
+		if addr == "" {
+			break
+		}
+		if unspentValue[addr] == nil {
+			unspentValue[addr] = &listunspent{unspentInfo.Amount, unspentInfo.Spendable}
+
 		} else {
-			unspentValue[addr] += unspentInfo.Amount
+			unspentValue[addr].amout += unspentInfo.Amount
 		}
-	}
+		//unspentValue[addr].spendable = unspentInfo.Spendable
 
+	}
 	outputsArr := make([]map[string]interface{}, 0)
 	for k, v := range unspentValue {
 		requestData := make(map[string]interface{})
 		requestData["address"] = k
-		valuestr := fmt.Sprintf("%.8f", v)
+		valuestr := fmt.Sprintf("%.8f", v.amout)
 		value, _ := strconv.ParseFloat(valuestr, 64)
 		requestData["Amount"] = value
+		requestData["spendable"] = v.spendable
 		outputsArr = append(outputsArr, requestData)
 	}
 	return outputsArr, nil

+ 9 - 10
src/dcrcash/dcrcash_test.go

@@ -140,14 +140,14 @@ func Test_ChainHeight(t *testing.T) {
 	return
 }
 
-/*func Test_ListUnspent(t *testing.T) {
+func Test_ListUnspent(t *testing.T) {
 	client := http.DefaultClient
-	geturl := fmt.Sprintf(`http://118.31.213.53:8803/coinproxy/listunspent`)
-	//geturl := fmt.Sprintf(`http://localhost:15741/coinproxy/listunspent`)
+	//geturl := fmt.Sprintf(`http://118.31.213.53:8803/coinproxy/listunspent`)
+	geturl := fmt.Sprintf(`http://localhost:15741/coinproxy/listunspent`)
 	timestamp := fmt.Sprintf("%v", time.Now().Unix())
 	t.Logf("post url:%v", geturl)
 
-	postdata := fmt.Sprintf(`{"cointype":"DCR","address":[2],"timestamp":"%v"}`, timestamp)
+	postdata := fmt.Sprintf(`{"cointype":"DCR","Sync":false,"address":[],"timestamp":"%v"}`, timestamp)
 	request, err := http.NewRequest("POST", geturl, strings.NewReader(postdata))
 	if err != nil {
 		t.Errorf("err:%s", err.Error())
@@ -170,7 +170,7 @@ func Test_ChainHeight(t *testing.T) {
 
 	return
 }
-*/
+
 func Test_SendRawTransaction(t *testing.T) {
 	client := http.DefaultClient
 	geturl := fmt.Sprintf(`http://localhost:15741/coinproxy/sendrawtransaction`)
@@ -233,15 +233,14 @@ func Test_SumCoinBalance(t *testing.T) {
 	return
 }
 */
-/*
+
 func Test_TransferAccounts(t *testing.T) {
 	client := http.DefaultClient
-	//geturl := fmt.Sprintf(`http://localhost:15741/coinproxy/sendcoins`)
-	geturl := fmt.Sprintf(`http://118.31.213.53:8803/coinproxy/sendcoins`)
+	geturl := fmt.Sprintf(`http://localhost:15741/coinproxy/sendcoins`)
+	//geturl := fmt.Sprintf(`http://118.31.213.53:8803/coinproxy/sendcoins`)
 	timestamp := fmt.Sprintf("%v", time.Now().Unix())
 	t.Logf("post url:%v", geturl)
 
-	//var b []byte
 	postdata := fmt.Sprintf(`{"cointype":"DCR","amount":"0.02","address":"DsctbrcDVEF4g4gqTpRF8ciZMqwe4va32uK","timestamp":"%v","signature":"%v"}`, timestamp, Signature([]byte("/coinproxy/sendcoins"), timestamp))
 	request, err := http.NewRequest("POST", geturl, strings.NewReader(postdata))
 	if err != nil {
@@ -263,7 +262,7 @@ func Test_TransferAccounts(t *testing.T) {
 
 	t.Logf("read bytes:%v", string(rbs))
 	return
-}*/
+}
 
 func Signature(body []byte, timestamp string) string {
 

+ 69 - 40
src/dcrcash/dcrcashcoin.go

@@ -13,11 +13,13 @@ import (
 )
 
 var (
-	Config       config
-	CoinApi      DcrCashApi
-	WalleTxfee   float64
-	balanceparam map[string]float64
-	mut          sync.Mutex
+	Config         config
+	CoinApi        DcrCashApi
+	WalleTxfee     float64
+	m_balanceparam map[string]float64
+	mut            sync.Mutex
+	m_unspent      []map[string]interface{}
+	m_AccValues    map[string]float64
 )
 
 type DcrCash struct {
@@ -36,6 +38,10 @@ func (m DcrCash) InitDriver(param interface{}) bool {
 		return false
 	}
 	go m.getwalletinfo()
+	//列出当期钱包的所有账户
+	go listaccounts()
+	//列出所有账户的balance,和listunspent
+	go SaveGetbalance()
 	return true
 }
 
@@ -93,9 +99,9 @@ func (m DcrCash) CoinBalance(parm interface{}) ([]byte, error) {
 	input, err := pjs.Get("Sync").Bool()
 	if !input {
 		fmt.Println("the balance is not sync!!")
-		totalbalance = balanceparam["totalbalance"]
-		maxConfirbalance = balanceparam["confirmedbalance"]
-		maxUnconfirbalance = balanceparam["unconfirmed"]
+		totalbalance = m_balanceparam["totalbalance"]
+		maxConfirbalance = m_balanceparam["confirmedbalance"]
+		maxUnconfirbalance = m_balanceparam["unconfirmed"]
 	} else {
 		acountBalace, err := CoinApi.WalleGetBalance("*")
 		if err != nil {
@@ -107,7 +113,6 @@ func (m DcrCash) CoinBalance(parm interface{}) ([]byte, error) {
 			LOG("ERROR", " inner json error:%v", err.Error())
 			return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, INNER_ERR, getErrMsg(INNER_ERR, nil))
 		}
-
 		for _, vbalance := range accounts {
 			if vbalance.Total != 0 {
 				totalbalance += vbalance.Total
@@ -128,6 +133,7 @@ func (m DcrCash) CoinBalance(parm interface{}) ([]byte, error) {
 	resp["confirmedbalance"] = maxConfirbalance
 	resp["unconfirmed"] = maxUnconfirbalance
 	resp["totalbalance"] = totalbalance
+	resp["querybalancetime"] = m_balanceparam["ntime"]
 	resp["errcode"] = 0
 	resp["exact"] = 0
 	if jbuf, err = json.Marshal(resp); err != nil {
@@ -252,25 +258,13 @@ func (m DcrCash) TransferAccounts(parm interface{}) ([]byte, error) {
 	}
 
 	amount := float64(f)
-	//list Accounts and account of balance
-	accountsofValues, err := CoinApi.ListAccounts()
-	if err != nil {
-		LOG("ERROR", "List accounts error:%v", err.Error())
-		return nil, err
-	}
-	AccValues := map[string]float64{}
-	if err = json.Unmarshal(accountsofValues, &AccValues); err != nil {
-		LOG("ERROR", "Unmarshal error:%v", err.Error())
-		return nil, err
-	}
 
 	fromaccout := ""
-	for account, value := range AccValues {
+	for account, value := range m_AccValues {
 		if value >= (amount + WalleTxfee) {
 			fromaccout = account
 			break
 		}
-
 	}
 	if fromaccout == "" {
 		fromaccout = DEFAULTACCOUNT
@@ -404,23 +398,31 @@ func (m DcrCash) TransInfo(parm interface{}) ([]byte, error) {
 }
 
 func (m DcrCash) ListUnspent(parm interface{}) ([]byte, error) {
+	i_listunspent := make([]map[string]interface{}, 0)
 	pjs := parm.(*simplejson.Json)
-	address, err := pjs.Get("address").StringArray()
-	if err != nil {
-		LOG("ERROR", "  input parm error:%v", err.Error())
-		return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
-	}
-	unspent, err := CoinApi.Listunspent(address)
-	if err != nil {
-		LOG("ERROR", "  get listunspent:%v", err.Error())
-		return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
+	Issync, err := pjs.Get("Sync").Bool()
+	if !Issync {
+		fmt.Println("The listunspent data Asynchrony!!!!")
+		i_listunspent = m_unspent
+	} else {
+		address, err := pjs.Get("address").StringArray()
+		if err != nil {
+			LOG("ERROR", "  input parm error:%v", err.Error())
+			return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
+		}
+		unspent, err := CoinApi.Listunspent(address)
+		if err != nil {
+			LOG("ERROR", "  get listunspent:%v", err.Error())
+			return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
+		}
+		i_listunspent = unspent
 	}
 
 	var jbuf []byte
 	resptmp := make(map[string]interface{})
 	resptmp["errcode"] = 0
 	resptmp["cointype"] = "DCR"
-	resptmp["unspents"] = unspent
+	resptmp["unspents"] = i_listunspent
 
 	if jbuf, err = json.Marshal(resptmp); err != nil {
 		LOG("ERROR", " inner json error:%v", err.Error())
@@ -468,9 +470,11 @@ func (m DcrCash) ChainHeight(parm interface{}) ([]byte, error) {
 }
 
 func SaveGetbalance() {
-	balanceparam = make(map[string]float64)
+	var address []string
+	m_unspent = make([]map[string]interface{}, 0)
+	m_balanceparam = make(map[string]float64)
 	for range time.Tick(2 * time.Minute) {
-		//DcrCashApi.WalleGetBalance()
+		fmt.Println("2 mine times", time.Now().Format("2006-01-02 15:04:05"))
 		acountBalace, err := CoinApi.WalleGetBalance("*")
 		if err != nil {
 			LOG("ERROR", " GetBalance err:%v", err.Error())
@@ -498,16 +502,41 @@ func SaveGetbalance() {
 
 		}
 		mut.Lock()
-		balanceparam["totalbalance"] = totalbalance
-		balanceparam["confirmedbalance"] = maxConfirbalance
-		balanceparam["unconfirmed"] = maxUnconfirbalance
+		m_balanceparam["totalbalance"] = totalbalance
+		m_balanceparam["confirmedbalance"] = maxConfirbalance
+		m_balanceparam["unconfirmed"] = maxUnconfirbalance
+		m_balanceparam["ntime"] = float64(time.Now().Unix())
+		mut.Unlock()
+
+		unspent, err := CoinApi.Listunspent(address)
+		if err != nil {
+			LOG("ERROR", "  get listunspent:%v", err.Error())
+			//return nil, fmt.Errorf(`{"errcode":%v,"mesage":"%s"}`, LISTUNSPENT_ERR, getErrMsg(LISTUNSPENT_ERR, nil))
+		}
+
+		m_unspent = unspent
+	}
+}
+
+func listaccounts() {
+	for range time.Tick(90 * time.Second) {
+		fmt.Println("listaccounts after 90s.....", time.Now().Format("2006-01-02 15:04:05"))
+		//list Accounts and account of balance
+		accountsofValues, err := CoinApi.ListAccounts()
+		if err != nil {
+			LOG("ERROR", "List accounts error:%v", err.Error())
+			//return nil, err
+		}
+		//
+		mut.Lock()
+		if err = json.Unmarshal(accountsofValues, &m_AccValues); err != nil {
+			LOG("ERROR", "Unmarshal error:%v", err.Error())
+			//return nil, err
+		}
 		mut.Unlock()
-		fmt.Println("2 mine times", time.Now().Format("2006-01-02 15:04:05"))
 	}
 }
 
 func init() {
 	Register(NameCoin, &DcrCash{})
-	go SaveGetbalance()
-
 }

+ 6 - 5
src/dcrcash/type.go

@@ -210,11 +210,6 @@ type RpcUnspentResult struct {
 	Id     int           `json:"id"`
 }
 
-/*type AccountsOfvalue struct {
-	Account string  `json:"account"`
-	Balance float64 `json:"balance"`
-}*/
-
 type AccountsOfvaluesResult struct {
 	Result map[string]float64 `json:"result"`
 	Error  RpcError           `json:"error"`
@@ -226,3 +221,9 @@ type OneaddressOfaccount struct {
 	Error  RpcError `json:"error"`
 	Id     int      `json:"id"`
 }
+
+//simple listunspent
+type listunspent struct {
+	amout     float64
+	spendable bool
+}