// Encodes as Class A func (ss *SimpleSend) SerializeToAddress() string { log.Println("Encoding data to address") raw := make([]byte, 25) var sequence byte = ss.Sequence raw[1] = sequence transactionType := makeBinary(ss.TransactionType) currencyId := makeBinary(ss.CurrencyId) amount := makeBinary(ss.Amount) //TODO: Can we optimise this? pointer := 2 for _, value := range transactionType { raw[pointer] = value pointer++ } for _, value := range currencyId { raw[pointer] = value pointer++ } for _, value := range amount { raw[pointer] = value pointer++ } ////////////////////////////// rawData := btcutil.Base58Encode(raw) log.Println("Raw information: ", raw) log.Println("Encoded to address", rawData) return rawData }
// String returns the extended key as a human-readable base58-encoded string. func (k *ExtendedKey) String() string { if len(k.key) == 0 { return "zeroed extended key" } var childNumBytes [4]byte depthByte := byte(k.depth % 256) binary.BigEndian.PutUint32(childNumBytes[:], k.childNum) // The serialized format is: // version (4) || depth (1) || parent fingerprint (4)) || // child num (4) || chain code (32) || key data (33) || checksum (4) serializedBytes := make([]byte, 0, serializedKeyLen+4) serializedBytes = append(serializedBytes, k.version...) serializedBytes = append(serializedBytes, depthByte) serializedBytes = append(serializedBytes, k.parentFP...) serializedBytes = append(serializedBytes, childNumBytes[:]...) serializedBytes = append(serializedBytes, k.chainCode...) if k.isPrivate { serializedBytes = append(serializedBytes, 0x00) serializedBytes = append(serializedBytes, k.key...) } else { serializedBytes = append(serializedBytes, k.pubKeyBytes()...) } checkSum := btcwire.DoubleSha256(serializedBytes)[:4] serializedBytes = append(serializedBytes, checkSum...) return btcutil.Base58Encode(serializedBytes) }
func TestBase58(t *testing.T) { // Base58Encode tests for x, test := range stringTests { tmp := []byte(test.in) if res := btcutil.Base58Encode(tmp); res != test.out { t.Errorf("Base58Encode test #%d failed: got: %s want: %s", x, res, test.out) continue } } // Base58Decode tests for x, test := range hexTests { b, err := hex.DecodeString(test.in) if err != nil { t.Errorf("hex.DecodeString failed failed #%d: got: %s", x, test.in) continue } if res := btcutil.Base58Decode(test.out); bytes.Equal(res, b) != true { t.Errorf("Base58Decode test #%d failed: got: %q want: %q", x, res, test.in) continue } } // Base58Decode with invalid input for x, test := range invalidStringTests { if res := btcutil.Base58Decode(test.in); string(res) != test.out { t.Errorf("Base58Decode invalidString test #%d failed: got: %q want: %q", x, res, test.out) continue } } }
func AddrFromPubKeyBytes(coin string, pubKeyBytes []byte) string { prefix := Config.GetCoin(coin).AddrPrefix h160 := CalcHash160(pubKeyBytes) h160 = append([]byte{prefix}, h160...) checksum := CalcHash256(h160) b := append(h160, checksum[:4]...) return btcutil.Base58Encode(b) }
// newBlockNotifyCheckTxOut is a helper function to iterate through // each transaction output of a new block and perform any checks and // notify listening frontends when necessary. func (s *rpcServer) newBlockNotifyCheckTxOut(block *btcutil.Block, tx *btcutil.Tx, spent []bool) { for wltNtfn, cxt := range s.ws.requests.m { for i, txout := range tx.MsgTx().TxOut { _, txaddrhash, err := btcscript.ScriptToAddrHash(txout.PkScript) if err != nil { log.Debug("Error getting payment address from tx; dropping any Tx notifications.") break } for addr, id := range cxt.txRequests { if !bytes.Equal(addr[:], txaddrhash) { continue } blkhash, err := block.Sha() if err != nil { log.Error("Error getting block sha; dropping Tx notification.") break } txaddr, err := btcutil.EncodeAddress(txaddrhash, s.server.btcnet) if err != nil { log.Error("Error encoding address; dropping Tx notification.") break } reply := &btcjson.Reply{ Result: struct { Sender string `json:"sender"` Receiver string `json:"receiver"` BlockHash string `json:"blockhash"` Height int64 `json:"height"` TxHash string `json:"txhash"` Index uint32 `json:"index"` Amount int64 `json:"amount"` PkScript string `json:"pkscript"` Spent bool `json:"spent"` }{ Sender: "Unknown", // TODO(jrick) Receiver: txaddr, BlockHash: blkhash.String(), Height: block.Height(), TxHash: tx.Sha().String(), Index: uint32(i), Amount: txout.Value, PkScript: btcutil.Base58Encode(txout.PkScript), Spent: spent[i], }, Error: nil, Id: &id, } replyBytes, err := json.Marshal(reply) if err != nil { log.Errorf("RPCS: Unable to marshal tx notification: %v", err) continue } wltNtfn <- replyBytes } } } }
func WIFFromPrivKeyBytes(coin string, privKeyBytes []byte, compress bool) string { prefix := Config.GetCoin(coin).WIFPrefix bytes := append([]byte{prefix}, privKeyBytes...) if compress { bytes = append(bytes, byte(1)) } checksum := CalcHash256(bytes) bytes = append(bytes, checksum[:4]...) return btcutil.Base58Encode(bytes) }
func jsonWSRead(walletNotification chan []byte, replychan chan *btcjson.Reply, body []byte, s *rpcServer) error { var message btcjson.Message err := json.Unmarshal(body, &message) if err != nil { reply := btcjson.Reply{ Result: nil, Error: &btcjson.ErrParse, Id: nil, } log.Tracef("RPCS: reply: %v", reply) replychan <- &reply return fmt.Errorf("RPCS: Error unmarshalling json message: %v", err) } log.Tracef("RPCS: received: %v", message) var rawReply btcjson.Reply defer func() { replychan <- &rawReply close(replychan) }() // Deal with commands switch message.Method { case "getcurrentnet": var net btcwire.BitcoinNet if cfg.TestNet3 { net = btcwire.TestNet3 } else { net = btcwire.MainNet } rawReply = btcjson.Reply{ Result: float64(net), Id: &message.Id, } case "getbestblock": // All other "get block" commands give either the height, the // hash, or both but require the block SHA. This gets both for // the best block. sha, height, err := s.server.db.NewestSha() if err != nil { log.Errorf("RPCS: Error getting newest block: %v", err) rawReply = btcjson.Reply{ Result: nil, Error: &btcjson.ErrBestBlockHash, Id: &message.Id, } return err } rawReply = btcjson.Reply{ Result: map[string]interface{}{ "hash": sha.String(), "height": height, }, Id: &message.Id, } case "rescan": minblock, maxblock := int64(0), btcdb.AllShas params, ok := message.Params.([]interface{}) if !ok || len(params) < 2 { rawReply = btcjson.Reply{ Result: nil, Error: &btcjson.ErrInvalidParams, Id: &message.Id, } return ErrBadParamsField } fminblock, ok := params[0].(float64) if !ok { rawReply = btcjson.Reply{ Result: nil, Error: &btcjson.ErrInvalidParams, Id: &message.Id, } return ErrBadParamsField } minblock = int64(fminblock) iaddrs, ok := params[1].([]interface{}) if !ok { rawReply = btcjson.Reply{ Result: nil, Error: &btcjson.ErrInvalidParams, Id: &message.Id, } return ErrBadParamsField } // addrHashes holds a set of string-ified address hashes. addrHashes := make(map[string]bool, len(iaddrs)) for i := range iaddrs { addr, ok := iaddrs[i].(string) if !ok { rawReply = btcjson.Reply{ Result: nil, Error: &btcjson.ErrInvalidParams, Id: &message.Id, } return ErrBadParamsField } addrhash, _, err := btcutil.DecodeAddress(addr) if err != nil { rawReply = btcjson.Reply{ Result: nil, Error: &btcjson.ErrInvalidParams, Id: &message.Id, } return ErrBadParamsField } addrHashes[string(addrhash)] = true } if len(params) > 2 { fmaxblock, ok := params[2].(float64) if !ok { rawReply = btcjson.Reply{ Result: nil, Error: &btcjson.ErrInvalidParams, Id: &message.Id, } return ErrBadParamsField } maxblock = int64(fmaxblock) } log.Debugf("RPCS: Begining rescan") // FetchHeightRange may not return a complete list of block shas for // the given range, so fetch range as many times as necessary. for { blkshalist, err := s.server.db.FetchHeightRange(minblock, maxblock) if err != nil { return err } if len(blkshalist) == 0 { break } for i := range blkshalist { blk, err := s.server.db.FetchBlockBySha(&blkshalist[i]) if err != nil { return err } txShaList, err := blk.TxShas() if err != nil { return err } txList := s.server.db.FetchTxByShaList(txShaList) for _, txReply := range txList { if txReply.Err != nil || txReply.Tx == nil { continue } for txOutIdx, txout := range txReply.Tx.TxOut { st, txaddrhash, err := btcscript.ScriptToAddrHash(txout.PkScript) if st != btcscript.ScriptAddr || err != nil { continue } txaddr, err := btcutil.EncodeAddress(txaddrhash, s.server.btcnet) if err != nil { log.Errorf("Error encoding address: %v", err) return err } if ok := addrHashes[string(txaddrhash)]; ok { reply := btcjson.Reply{ Result: struct { Sender string `json:"sender"` Receiver string `json:"receiver"` BlockHash string `json:"blockhash"` Height int64 `json:"height"` TxHash string `json:"txhash"` Index uint32 `json:"index"` Amount int64 `json:"amount"` PkScript string `json:"pkscript"` Spent bool `json:"spent"` }{ Sender: "Unknown", // TODO(jrick) Receiver: txaddr, BlockHash: blkshalist[i].String(), Height: blk.Height(), TxHash: txReply.Sha.String(), Index: uint32(txOutIdx), Amount: txout.Value, PkScript: btcutil.Base58Encode(txout.PkScript), Spent: txReply.TxSpent[txOutIdx], }, Error: nil, Id: &message.Id, } replychan <- &reply } } } } if maxblock-minblock > int64(len(blkshalist)) { minblock += int64(len(blkshalist)) } else { break } } rawReply = btcjson.Reply{ Result: nil, Error: nil, Id: &message.Id, } log.Debug("RPCS: Finished rescan") case "notifynewtxs": params, ok := message.Params.([]interface{}) if !ok || len(params) != 1 { rawReply = btcjson.Reply{ Result: nil, Error: &btcjson.ErrInvalidParams, Id: &message.Id, } return ErrBadParamsField } addr, ok := params[0].(string) if !ok { rawReply = btcjson.Reply{ Result: nil, Error: &btcjson.ErrInvalidParams, Id: &message.Id, } return ErrBadParamsField } addrhash, _, err := btcutil.DecodeAddress(addr) if err != nil { jsonError := btcjson.Error{ Code: btcjson.ErrInvalidParams.Code, Message: "Cannot decode address", } rawReply = btcjson.Reply{ Result: nil, Error: &jsonError, Id: &message.Id, } return ErrBadParamsField } var hash addressHash copy(hash[:], addrhash) s.ws.requests.AddTxRequest(walletNotification, hash, message.Id) rawReply = btcjson.Reply{ Result: nil, Error: nil, Id: &message.Id, } case "notifyspent": params, ok := message.Params.([]interface{}) if !ok || len(params) != 2 { rawReply = btcjson.Reply{ Result: nil, Error: &btcjson.ErrInvalidParams, Id: &message.Id, } return ErrBadParamsField } hashBE, ok1 := params[0].(string) index, ok2 := params[1].(float64) if !ok1 || !ok2 { rawReply = btcjson.Reply{ Result: nil, Error: &btcjson.ErrInvalidParams, Id: &message.Id, } return ErrBadParamsField } hash, err := btcwire.NewShaHashFromStr(hashBE) if err != nil { jsonError := btcjson.Error{ Code: btcjson.ErrInvalidParams.Code, Message: "Hash string cannot be parsed.", } rawReply = btcjson.Reply{ Result: nil, Error: &jsonError, Id: &message.Id, } return ErrBadParamsField } op := btcwire.NewOutPoint(hash, uint32(index)) s.ws.requests.AddSpentRequest(walletNotification, op, message.Id) rawReply = btcjson.Reply{ Result: nil, Error: nil, Id: &message.Id, } default: rawReply = btcjson.Reply{ Result: nil, Error: &btcjson.ErrMethodNotFound, Id: &message.Id, } } return btcjson.ErrMethodNotFound }