Example #1
0
// 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
}
Example #2
0
// 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)
}
Example #3
0
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
		}
	}
}
Example #4
0
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)
}
Example #5
0
// 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
			}
		}
	}
}
Example #6
0
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)
}
Example #7
0
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
}