Exemplo n.º 1
0
func init() {
	rd, _ := hex.DecodeString("0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000")
	dummy_tx, _ := btc.NewTx(rd)
	dummy_tx.Size = uint32(len(rd))
	ha := btc.Sha2Sum(rd)
	dummy_tx.Hash = btc.NewUint256(ha[:])
}
Exemplo n.º 2
0
func execute_test_tx(t *testing.T, tv *testvector) bool {
	if len(tv.inps) == 0 {
		t.Error("Vector has no inputs")
		return false
	}
	rd, er := hex.DecodeString(tv.tx)
	if er != nil {
		t.Error(er.Error())
		return false
	}
	tx, _ := btc.NewTx(rd)
	if tx == nil {
		t.Error("Canot decode tx")
		return false
	}
	tx.Size = uint32(len(rd))
	ha := btc.Sha2Sum(rd)
	tx.Hash = btc.NewUint256(ha[:])

	if skip_broken_tests(tx) {
		return false
	}

	if !tx.IsCoinBase() {
		for i := range tx.TxIn {
			if tx.TxIn[i].Input.IsNull() {
				return false
			}
		}
	}

	oks := 0
	for i := range tx.TxIn {
		var j int
		for j = range tv.inps {
			if bytes.Equal(tx.TxIn[i].Input.Hash[:], tv.inps[j].txid.Hash[:]) &&
				tx.TxIn[i].Input.Vout == uint32(tv.inps[j].vout) {
				break
			}
		}
		if j >= len(tv.inps) {
			t.Error("Matching input not found")
			continue
		}

		pk, er := btc.DecodeScript(tv.inps[j].pkscr)
		if er != nil {
			t.Error(er.Error())
			continue
		}
		var ss []byte
		if tv.inps[j].vout >= 0 {
			ss = tx.TxIn[i].ScriptSig
		}
		if VerifyTxScript(ss, pk, i, tx, tv.ver_flags) {
			oks++
		}
	}
	return oks == len(tx.TxIn)
}
Exemplo n.º 3
0
// Uncompressed private key
func sec2b58unc(pk []byte) string {
	var dat [37]byte
	dat[0] = AddrVerSecret()
	copy(dat[1:33], pk)
	sh := btc.Sha2Sum(dat[0:33])
	copy(dat[33:37], sh[:4])
	return btc.Encodeb58(dat[:])
}
Exemplo n.º 4
0
// Compressed private key
func sec2b58com(pk []byte) string {
	var dat [38]byte
	dat[0] = AddrVerSecret()
	copy(dat[1:33], pk)
	dat[33] = 1 // compressed
	sh := btc.Sha2Sum(dat[0:34])
	copy(dat[34:38], sh[:4])
	return btc.Encodeb58(dat[:])
}
Exemplo n.º 5
0
func (c *one_net_conn) sendmsg(cmd string, pl []byte) (e error) {
	sbuf := make([]byte, 24+len(pl))

	binary.LittleEndian.PutUint32(sbuf[0:4], Version)
	copy(sbuf[0:4], Magic[:])
	copy(sbuf[4:16], cmd)
	binary.LittleEndian.PutUint32(sbuf[16:20], uint32(len(pl)))

	sh := btc.Sha2Sum(pl[:])
	copy(sbuf[20:24], sh[:4])
	copy(sbuf[24:], pl)

	c.Mutex.Lock()
	c.send.buf = append(c.send.buf, sbuf...)
	//fmt.Println("...", len(c.send.buf))
	c.Mutex.Unlock()
	return
}
Exemplo n.º 6
0
func mk_out_tx(sig_scr, pk_scr []byte) (output_tx *btc.Tx) {
	// We build input_tx only to calculate it's hash for output_tx
	input_tx := new(btc.Tx)
	input_tx.Version = 1
	input_tx.TxIn = []*btc.TxIn{&btc.TxIn{Input: btc.TxPrevOut{Vout: 0xffffffff},
		ScriptSig: []byte{0, 0}, Sequence: 0xffffffff}}
	input_tx.TxOut = []*btc.TxOut{&btc.TxOut{Pk_script: pk_scr}}
	// Lock_time = 0

	output_tx = new(btc.Tx)
	output_tx.Version = 1
	output_tx.TxIn = []*btc.TxIn{&btc.TxIn{Input: btc.TxPrevOut{Hash: btc.Sha2Sum(input_tx.Serialize()), Vout: 0},
		ScriptSig: sig_scr, Sequence: 0xffffffff}}
	output_tx.TxOut = []*btc.TxOut{&btc.TxOut{}}
	// Lock_time = 0

	return
}
Exemplo n.º 7
0
func (c *OneConnection) SendRawMsg(cmd string, pl []byte) (e error) {
	c.Mutex.Lock()

	if c.Send.Buf != nil {
		// Before adding more data to the buffer, check the limit
		if len(c.Send.Buf) > MaxSendBufferSize {
			c.Mutex.Unlock()
			if common.DebugLevel > 0 {
				println(c.PeerAddr.Ip(), "Peer Send Buffer Overflow")
			}
			c.Disconnect()
			common.CountSafe("PeerSendOverflow")
			return errors.New("Send buffer overflow")
		}
	} else {
		c.Send.LastSent = time.Now()
	}

	common.CountSafe("sent_" + cmd)
	common.CountSafeAdd("sbts_"+cmd, uint64(len(pl)))
	sbuf := make([]byte, 24+len(pl))

	c.LastCmdSent = cmd
	c.LastBtsSent = uint32(len(pl))

	binary.LittleEndian.PutUint32(sbuf[0:4], common.Version)
	copy(sbuf[0:4], common.Magic[:])
	copy(sbuf[4:16], cmd)
	binary.LittleEndian.PutUint32(sbuf[16:20], uint32(len(pl)))

	sh := btc.Sha2Sum(pl[:])
	copy(sbuf[20:24], sh[:4])
	copy(sbuf[24:], pl)

	c.Send.Buf = append(c.Send.Buf, sbuf...)

	if common.DebugLevel < 0 {
		fmt.Println(cmd, len(c.Send.Buf), "->", c.PeerAddr.Ip())
	}
	c.Mutex.Unlock()
	//println(len(c.Send.Buf), "queued for seding to", c.PeerAddr.Ip())
	return
}
Exemplo n.º 8
0
func (c *OneConnection) SendRawMsg(cmd string, pl []byte) (e error) {
	c.Mutex.Lock()
	if !c.broken {
		// we never allow the buffer to be totally full because then producer would be equal consumer
		if bytes_left := SendBufSize - c.BytesToSent(); bytes_left <= len(pl)+24 {
			c.Mutex.Unlock()
			/*println(c.PeerAddr.Ip(), c.Node.Version, c.Node.Agent, "Peer Send Buffer Overflow @",
			cmd, bytes_left, len(pl)+24, c.SendBufProd, c.SendBufCons, c.BytesToSent())*/
			c.Disconnect()
			common.CountSafe("PeerSendOverflow")
			return errors.New("Send buffer overflow")
		}

		c.counters["sent_"+cmd]++
		c.counters["sbts_"+cmd] += uint64(len(pl))

		common.CountSafe("sent_" + cmd)
		common.CountSafeAdd("sbts_"+cmd, uint64(len(pl)))
		var sbuf [24]byte

		c.X.LastCmdSent = cmd
		c.X.LastBtsSent = uint32(len(pl))

		binary.LittleEndian.PutUint32(sbuf[0:4], common.Version)
		copy(sbuf[0:4], common.Magic[:])
		copy(sbuf[4:16], cmd)
		binary.LittleEndian.PutUint32(sbuf[16:20], uint32(len(pl)))

		sh := btc.Sha2Sum(pl[:])
		copy(sbuf[20:24], sh[:4])

		c.append_to_send_buffer(sbuf[:])
		c.append_to_send_buffer(pl)

		if x := c.BytesToSent(); x > c.X.MaxSentBufSize {
			c.X.MaxSentBufSize = x
		}
	}
	c.Mutex.Unlock()
	return
}
Exemplo n.º 9
0
func mk_spend_tx(input_tx *btc.Tx, sig_scr []byte, witness [][]byte) (output_tx *btc.Tx) {
	output_tx = new(btc.Tx)
	output_tx.Version = 1
	output_tx.TxIn = []*btc.TxIn{&btc.TxIn{Input: btc.TxPrevOut{Hash: btc.Sha2Sum(input_tx.Serialize()), Vout: 0},
		ScriptSig: sig_scr, Sequence: 0xffffffff}}
	output_tx.TxOut = []*btc.TxOut{&btc.TxOut{Value: input_tx.TxOut[0].Value}}
	// Lock_time = 0

	if len(witness) > 0 {
		output_tx.SegWit = make([][][]byte, 1)
		output_tx.SegWit[0] = witness
		if DBG_SCR {
			println("tx has", len(witness), "ws")
			for xx := range witness {
				println("", xx, hex.EncodeToString(witness[xx]))
			}
		}
	}
	output_tx.SetHash(output_tx.Serialize())
	return
}
Exemplo n.º 10
0
func (c *one_net_conn) readmsg() *one_net_cmd {
	c.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
	if c.recv.hdr_len < 24 {
		for {
			n, e := c.Read(c.recv.hdr[c.recv.hdr_len:])
			if e != nil {
				if nerr, ok := e.(net.Error); ok && nerr.Timeout() {
					//COUNTER("HDRT")
				} else {
					c.setbroken(true)
				}
				return nil
			}
			c.Lock()
			c.bytes_received += uint64(n)
			c.Unlock()
			c.recv.hdr_len += n
			if c.recv.hdr_len >= 4 {
				if !bytes.Equal(c.recv.hdr[:4], Magic[:]) {
					fmt.Println(c.Ip(), "NetBadMagic")
					c.setbroken(true)
					return nil
				}
				if c.recv.hdr_len == 24 {
					c.recv.cmd = strings.TrimRight(string(c.recv.hdr[4:16]), "\000")
					c.recv.pl_len = binary.LittleEndian.Uint32(c.recv.hdr[16:20])
					c.recv.datlen = 0
					if c.recv.pl_len > 0 {
						c.recv.dat = make([]byte, c.recv.pl_len)
					}
					break
				}
			}
		}
	}

	for c.recv.datlen < c.recv.pl_len {
		n, e := c.Read(c.recv.dat[c.recv.datlen:])
		if e != nil {
			if nerr, ok := e.(net.Error); ok && nerr.Timeout() {
				//COUNTER("HDRT")
			} else {
				c.setbroken(true)
			}
			return nil
		}
		if n > 0 {
			c.recv.datlen += uint32(n)
			c.Lock()
			c.bytes_received += uint64(n)
			c.Unlock()
		}
	}

	sh := btc.Sha2Sum(c.recv.dat)
	if !bytes.Equal(c.recv.hdr[20:24], sh[:4]) {
		fmt.Println(c.Ip(), "Msg checksum error")
		c.setbroken(true)
		return nil
	}

	res := new(one_net_cmd)
	res.cmd = c.recv.cmd
	res.pl = c.recv.dat

	c.recv.hdr_len = 0
	c.recv.dat = nil

	return res
}
Exemplo n.º 11
0
func (c *OneConnection) FetchMessage() *BCmsg {
	var e error
	var n int

	for c.recv.hdr_len < 24 {
		n, e = common.SockRead(c.NetConn, c.recv.hdr[c.recv.hdr_len:24])
		c.Mutex.Lock()
		c.recv.hdr_len += n
		if e != nil {
			c.Mutex.Unlock()
			c.HandleError(e)
			return nil
		}
		if c.recv.hdr_len >= 4 && !bytes.Equal(c.recv.hdr[:4], common.Magic[:]) {
			c.Mutex.Unlock()
			if common.DebugLevel > 0 {
				println("FetchMessage: Proto out of sync")
			}
			common.CountSafe("NetBadMagic")
			c.Disconnect()
			return nil
		}
		if c.broken {
			c.Mutex.Unlock()
			return nil
		}
		if c.recv.hdr_len >= 24 {
			c.recv.pl_len = binary.LittleEndian.Uint32(c.recv.hdr[16:20])
			c.recv.cmd = strings.TrimRight(string(c.recv.hdr[4:16]), "\000")
		}
		c.Mutex.Unlock()
	}

	if c.recv.pl_len > 0 {
		if c.recv.dat == nil {
			msi := maxmsgsize(c.recv.cmd)
			if c.recv.pl_len > msi {
				//println(c.PeerAddr.Ip(), "Command", c.recv.cmd, "is going to be too big", c.recv.pl_len, msi)
				c.DoS("MsgTooBig")
				return nil
			}
			c.Mutex.Lock()
			c.recv.dat = make([]byte, c.recv.pl_len)
			c.recv.datlen = 0
			c.Mutex.Unlock()
		}
		for c.recv.datlen < c.recv.pl_len {
			n, e = common.SockRead(c.NetConn, c.recv.dat[c.recv.datlen:])
			if n > 0 {
				c.Mutex.Lock()
				c.recv.datlen += uint32(n)
				c.Mutex.Unlock()
				if c.recv.datlen > c.recv.pl_len {
					println(c.PeerAddr.Ip(), "is sending more of", c.recv.cmd, "then it should have", c.recv.datlen, c.recv.pl_len)
					c.DoS("MsgSizeMismatch")
					return nil
				}
			}
			if e != nil {
				c.HandleError(e)
				return nil
			}
			if c.broken {
				return nil
			}
		}
	}

	sh := btc.Sha2Sum(c.recv.dat)
	if !bytes.Equal(c.recv.hdr[20:24], sh[:4]) {
		//println(c.PeerAddr.Ip(), "Msg checksum error")
		c.DoS("MsgBadChksum")
		return nil
	}

	ret := new(BCmsg)
	ret.cmd = c.recv.cmd
	ret.pl = c.recv.dat

	c.Mutex.Lock()
	c.recv.dat = nil
	c.recv.hdr_len = 0
	c.BytesReceived += uint64(24 + len(ret.pl))
	c.Mutex.Unlock()

	return ret
}
Exemplo n.º 12
0
func (ch *Chain) PostCheckBlock(bl *btc.Block) (er error) {
	// Size limits
	if len(bl.Raw) < 81 {
		er = errors.New("CheckBlock() : size limits failed low - RPC_Result:bad-blk-length")
		return
	}

	if bl.Txs == nil {
		er = bl.BuildTxList()
		if er != nil {
			return
		}
		if len(bl.OldData) > btc.MAX_BLOCK_SIZE {
			er = errors.New("CheckBlock() : size limits failed high - RPC_Result:bad-blk-length")
			return
		}
	}

	if !bl.Trusted {
		// We need to be satoshi compatible
		if len(bl.Txs) == 0 || !bl.Txs[0].IsCoinBase() {
			er = errors.New("CheckBlock() : first tx is not coinbase: " + bl.Hash.String() + " - RPC_Result:bad-cb-missing")
			return
		}

		// Enforce rule that the coinbase starts with serialized block height
		if bl.Height >= ch.Consensus.BIP34Height {
			var exp [6]byte
			var exp_len int
			binary.LittleEndian.PutUint32(exp[1:5], bl.Height)
			for exp_len = 5; exp_len > 1; exp_len-- {
				if exp[exp_len] != 0 || exp[exp_len-1] >= 0x80 {
					break
				}
			}
			exp[0] = byte(exp_len)
			exp_len++

			if !bytes.HasPrefix(bl.Txs[0].TxIn[0].ScriptSig, exp[:exp_len]) {
				er = errors.New("CheckBlock() : Unexpected block number in coinbase: " + bl.Hash.String() + " - RPC_Result:bad-cb-height")
				return
			}
		}

		// And again...
		for i := 1; i < len(bl.Txs); i++ {
			if bl.Txs[i].IsCoinBase() {
				er = errors.New("CheckBlock() : more than one coinbase: " + bl.Hash.String() + " - RPC_Result:bad-cb-multiple")
				return
			}
		}

		// Check Merkle Root - that's importnant
		merkle, mutated := btc.GetMerkle(bl.Txs)
		if mutated {
			er = errors.New("CheckBlock(): duplicate transaction - RPC_Result:bad-txns-duplicate")
			return
		}

		if !bytes.Equal(merkle, bl.MerkleRoot()) {
			er = errors.New("CheckBlock() : Merkle Root mismatch - RPC_Result:bad-txnmrklroot")
			return
		}
	}

	if bl.BlockTime() >= BIP16SwitchTime {
		bl.VerifyFlags = script.VER_P2SH
	} else {
		bl.VerifyFlags = 0
	}

	if bl.Height >= ch.Consensus.BIP66Height {
		bl.VerifyFlags |= script.VER_DERSIG
	}

	if bl.Height >= ch.Consensus.BIP65Height {
		bl.VerifyFlags |= script.VER_CLTV
	}

	if ch.Consensus.Enforce_CSV != 0 && bl.Height >= ch.Consensus.Enforce_CSV {
		bl.VerifyFlags |= script.VER_CSV
	}

	if ch.Consensus.Enforce_SEGWIT != 0 && bl.Height >= ch.Consensus.Enforce_SEGWIT {
		bl.VerifyFlags |= script.VER_WITNESS | script.VER_NULLDUMMY
	}

	if !bl.Trusted {
		var blockTime uint32
		var had_witness bool

		if (bl.VerifyFlags & script.VER_CSV) != 0 {
			blockTime = bl.MedianPastTime
		} else {
			blockTime = bl.BlockTime()
		}

		// Verify merkle root of witness data
		if (bl.VerifyFlags & script.VER_WITNESS) != 0 {
			var i int
			for i = len(bl.Txs[0].TxOut) - 1; i >= 0; i-- {
				o := bl.Txs[0].TxOut[i]
				if len(o.Pk_script) >= 38 && bytes.Equal(o.Pk_script[:6], []byte{0x6a, 0x24, 0xaa, 0x21, 0xa9, 0xed}) {
					if len(bl.Txs[0].SegWit) != 1 || len(bl.Txs[0].SegWit[0]) != 1 || len(bl.Txs[0].SegWit[0][0]) != 32 {
						er = errors.New("CheckBlock() : invalid witness nonce size - RPC_Result:bad-witness-nonce-size")
						println(er.Error())
						println(bl.Hash.String(), len(bl.Txs[0].SegWit))
						return
					}

					// The malleation check is ignored; as the transaction tree itself
					// already does not permit it, it is impossible to trigger in the
					// witness tree.
					merkle, _ := btc.GetWitnessMerkle(bl.Txs)
					with_nonce := btc.Sha2Sum(append(merkle, bl.Txs[0].SegWit[0][0]...))

					if !bytes.Equal(with_nonce[:], o.Pk_script[6:38]) {
						er = errors.New("CheckBlock(): Witness Merkle mismatch - RPC_Result:bad-witness-merkle-match")
						return
					}

					had_witness = true
					break
				}
			}
		}

		if !had_witness {
			for _, t := range bl.Txs {
				if t.SegWit != nil {
					er = errors.New("CheckBlock(): unexpected witness data found - RPC_Result:unexpected-witness")
					return
				}
			}
		}

		// Check transactions - this is the most time consuming task
		if !CheckTransactions(bl.Txs, bl.Height, blockTime) {
			er = errors.New("CheckBlock() : CheckTransactions() failed - RPC_Result:bad-tx")
			return
		}
	}
	return
}
Exemplo n.º 13
0
func evalScript(p []byte, stack *scrStack, tx *btc.Tx, inp int, ver_flags uint32) bool {
	if DBG_SCR {
		fmt.Println("script len", len(p))
	}

	if len(p) > 10000 {
		if DBG_ERR {
			fmt.Println("script too long", len(p))
		}
		return false
	}

	defer func() {
		if r := recover(); r != nil {
			if DBG_ERR {
				err, ok := r.(error)
				if !ok {
					err = fmt.Errorf("pkg: %v", r)
				}
				fmt.Println("evalScript panic:", err.Error())
				fmt.Println(string(debug.Stack()))
			}
		}
	}()

	var exestack scrStack
	var altstack scrStack
	sta, idx, opcnt := 0, 0, 0
	checkMinVals := (ver_flags & VER_MINDATA) != 0
	for idx < len(p) {
		inexec := exestack.nofalse()

		// Read instruction
		opcode, pushval, n, e := btc.GetOpcode(p[idx:])
		if e != nil {
			//fmt.Println(e.Error())
			//fmt.Println("A", idx, hex.EncodeToString(p))
			return false
		}
		idx += n

		if DBG_SCR {
			fmt.Printf("\nExecuting opcode 0x%02x  n=%d  inexec:%t  push:%s..\n",
				opcode, n, inexec, hex.EncodeToString(pushval))
			stack.print()
		}

		if pushval != nil && len(pushval) > btc.MAX_SCRIPT_ELEMENT_SIZE {
			if DBG_ERR {
				fmt.Println("pushval too long", len(pushval))
			}
			return false
		}

		if opcode > 0x60 {
			opcnt++
			if opcnt > 201 {
				if DBG_ERR {
					fmt.Println("evalScript: too many opcodes A")
				}
				return false
			}
		}

		if opcode == 0x7e /*OP_CAT*/ ||
			opcode == 0x7f /*OP_SUBSTR*/ ||
			opcode == 0x80 /*OP_LEFT*/ ||
			opcode == 0x81 /*OP_RIGHT*/ ||
			opcode == 0x83 /*OP_INVERT*/ ||
			opcode == 0x84 /*OP_AND*/ ||
			opcode == 0x85 /*OP_OR*/ ||
			opcode == 0x86 /*OP_XOR*/ ||
			opcode == 0x8d /*OP_2MUL*/ ||
			opcode == 0x8e /*OP_2DIV*/ ||
			opcode == 0x95 /*OP_MUL*/ ||
			opcode == 0x96 /*OP_DIV*/ ||
			opcode == 0x97 /*OP_MOD*/ ||
			opcode == 0x98 /*OP_LSHIFT*/ ||
			opcode == 0x99 /*OP_RSHIFT*/ {
			if DBG_ERR {
				fmt.Println("Unsupported opcode", opcode)
			}
			return false
		}

		if inexec && 0 <= opcode && opcode <= btc.OP_PUSHDATA4 {
			if checkMinVals && !checkMinimalPush(pushval, opcode) {
				if DBG_ERR {
					fmt.Println("Push value not in a minimal format", hex.EncodeToString(pushval))
				}
				return false
			}
			stack.push(pushval)
			if DBG_SCR {
				fmt.Println("pushed", len(pushval), "bytes")
			}
		} else if inexec || (0x63 /*OP_IF*/ <= opcode && opcode <= 0x68 /*OP_ENDIF*/) {
			switch {
			case opcode == 0x4f: // OP_1NEGATE
				stack.pushInt(-1)

			case opcode >= 0x51 && opcode <= 0x60: // OP_1-OP_16
				stack.pushInt(int64(opcode - 0x50))

			case opcode == 0x61: // OP_NOP
				// Do nothing

			/* - not handled
			OP_VER = 0x62
			*/

			case opcode == 0x63 || opcode == 0x64: //OP_IF || OP_NOTIF
				// <expression> if [statements] [else [statements]] endif
				val := false
				if inexec {
					if stack.size() < 1 {
						if DBG_ERR {
							fmt.Println("Stack too short for", opcode)
						}
						return false
					}
					if opcode == 0x63 /*OP_IF*/ {
						val = stack.popBool()
					} else {
						val = !stack.popBool()
					}
				}
				if DBG_SCR {
					fmt.Println(inexec, "if pushing", val, "...")
				}
				exestack.pushBool(val)

			/* - not handled
			   OP_VERIF = 0x65,
			   OP_VERNOTIF = 0x66,
			*/
			case opcode == 0x67: //OP_ELSE
				if exestack.size() == 0 {
					if DBG_ERR {
						fmt.Println("exestack empty in OP_ELSE")
					}
				}
				exestack.pushBool(!exestack.popBool())

			case opcode == 0x68: //OP_ENDIF
				if exestack.size() == 0 {
					if DBG_ERR {
						fmt.Println("exestack empty in OP_ENDIF")
					}
				}
				exestack.pop()

			case opcode == 0x69: //OP_VERIFY
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				if !stack.topBool(-1) {
					return false
				}
				stack.pop()

			case opcode == 0x6b: //OP_TOALTSTACK
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				altstack.push(stack.pop())

			case opcode == 0x6c: //OP_FROMALTSTACK
				if altstack.size() < 1 {
					if DBG_ERR {
						fmt.Println("AltStack too short for opcode", opcode)
					}
					return false
				}
				stack.push(altstack.pop())

			case opcode == 0x6d: //OP_2DROP
				if stack.size() < 2 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				stack.pop()
				stack.pop()

			case opcode == 0x6e: //OP_2DUP
				if stack.size() < 2 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				x1 := stack.top(-1)
				x2 := stack.top(-2)
				stack.push(x2)
				stack.push(x1)

			case opcode == 0x6f: //OP_3DUP
				if stack.size() < 3 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				x1 := stack.top(-3)
				x2 := stack.top(-2)
				x3 := stack.top(-1)
				stack.push(x1)
				stack.push(x2)
				stack.push(x3)

			case opcode == 0x70: //OP_2OVER
				if stack.size() < 4 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				x1 := stack.top(-4)
				x2 := stack.top(-3)
				stack.push(x1)
				stack.push(x2)

			case opcode == 0x71: //OP_2ROT
				// (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
				if stack.size() < 6 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				x6 := stack.pop()
				x5 := stack.pop()
				x4 := stack.pop()
				x3 := stack.pop()
				x2 := stack.pop()
				x1 := stack.pop()
				stack.push(x3)
				stack.push(x4)
				stack.push(x5)
				stack.push(x6)
				stack.push(x1)
				stack.push(x2)

			case opcode == 0x72: //OP_2SWAP
				// (x1 x2 x3 x4 -- x3 x4 x1 x2)
				if stack.size() < 4 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				x4 := stack.pop()
				x3 := stack.pop()
				x2 := stack.pop()
				x1 := stack.pop()
				stack.push(x3)
				stack.push(x4)
				stack.push(x1)
				stack.push(x2)

			case opcode == 0x73: //OP_IFDUP
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				if stack.topBool(-1) {
					stack.push(stack.top(-1))
				}

			case opcode == 0x74: //OP_DEPTH
				stack.pushInt(int64(stack.size()))

			case opcode == 0x75: //OP_DROP
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				stack.pop()

			case opcode == 0x76: //OP_DUP
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				el := stack.pop()
				stack.push(el)
				stack.push(el)

			case opcode == 0x77: //OP_NIP
				if stack.size() < 2 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				x := stack.pop()
				stack.pop()
				stack.push(x)

			case opcode == 0x78: //OP_OVER
				if stack.size() < 2 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				stack.push(stack.top(-2))

			case opcode == 0x79 || opcode == 0x7a: //OP_PICK || OP_ROLL
				if stack.size() < 2 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				n := stack.popInt(checkMinVals)
				if n < 0 || n >= int64(stack.size()) {
					if DBG_ERR {
						fmt.Println("Wrong n for opcode", opcode)
					}
					return false
				}
				if opcode == 0x79 /*OP_PICK*/ {
					stack.push(stack.top(int(-1 - n)))
				} else if n > 0 {
					tmp := make([][]byte, n)
					for i := range tmp {
						tmp[i] = stack.pop()
					}
					xn := stack.pop()
					for i := len(tmp) - 1; i >= 0; i-- {
						stack.push(tmp[i])
					}
					stack.push(xn)
				}

			case opcode == 0x7b: //OP_ROT
				if stack.size() < 3 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				x3 := stack.pop()
				x2 := stack.pop()
				x1 := stack.pop()
				stack.push(x2)
				stack.push(x3)
				stack.push(x1)

			case opcode == 0x7c: //OP_SWAP
				if stack.size() < 2 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				x1 := stack.pop()
				x2 := stack.pop()
				stack.push(x1)
				stack.push(x2)

			case opcode == 0x7d: //OP_TUCK
				if stack.size() < 2 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				x1 := stack.pop()
				x2 := stack.pop()
				stack.push(x1)
				stack.push(x2)
				stack.push(x1)

			case opcode == 0x82: //OP_SIZE
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				stack.pushInt(int64(len(stack.top(-1))))

			case opcode == 0x87 || opcode == 0x88: //OP_EQUAL || OP_EQUALVERIFY
				if stack.size() < 2 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				a := stack.pop()
				b := stack.pop()
				if opcode == 0x88 { //OP_EQUALVERIFY
					if !bytes.Equal(a, b) {
						return false
					}
				} else {
					stack.pushBool(bytes.Equal(a, b))
				}

			/* - not handled
			OP_RESERVED1 = 0x89,
			OP_RESERVED2 = 0x8a,
			*/

			case opcode == 0x8b: //OP_1ADD
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				stack.pushInt(stack.popInt(checkMinVals) + 1)

			case opcode == 0x8c: //OP_1SUB
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				stack.pushInt(stack.popInt(checkMinVals) - 1)

			case opcode == 0x8f: //OP_NEGATE
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				stack.pushInt(-stack.popInt(checkMinVals))

			case opcode == 0x90: //OP_ABS
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				a := stack.popInt(checkMinVals)
				if a < 0 {
					stack.pushInt(-a)
				} else {
					stack.pushInt(a)
				}

			case opcode == 0x91: //OP_NOT
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				stack.pushBool(stack.popInt(checkMinVals) == 0)

			case opcode == 0x92: //OP_0NOTEQUAL
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				d := stack.pop()
				if checkMinVals && len(d) > 1 {
					if DBG_ERR {
						fmt.Println("Not minimal bool value", hex.EncodeToString(d))
					}
					return false
				}
				stack.pushBool(bts2bool(d))

			case opcode == 0x93 || //OP_ADD
				opcode == 0x94 || //OP_SUB
				opcode == 0x9a || //OP_BOOLAND
				opcode == 0x9b || //OP_BOOLOR
				opcode == 0x9c || opcode == 0x9d || //OP_NUMEQUAL || OP_NUMEQUALVERIFY
				opcode == 0x9e || //OP_NUMNOTEQUAL
				opcode == 0x9f || //OP_LESSTHAN
				opcode == 0xa0 || //OP_GREATERTHAN
				opcode == 0xa1 || //OP_LESSTHANOREQUAL
				opcode == 0xa2 || //OP_GREATERTHANOREQUAL
				opcode == 0xa3 || //OP_MIN
				opcode == 0xa4: //OP_MAX
				if stack.size() < 2 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				bn2 := stack.popInt(checkMinVals)
				bn1 := stack.popInt(checkMinVals)
				var bn int64
				switch opcode {
				case 0x93:
					bn = bn1 + bn2 // OP_ADD
				case 0x94:
					bn = bn1 - bn2 // OP_SUB
				case 0x9a:
					bn = b2i(bn1 != 0 && bn2 != 0) // OP_BOOLAND
				case 0x9b:
					bn = b2i(bn1 != 0 || bn2 != 0) // OP_BOOLOR
				case 0x9c:
					bn = b2i(bn1 == bn2) // OP_NUMEQUAL
				case 0x9d:
					bn = b2i(bn1 == bn2) // OP_NUMEQUALVERIFY
				case 0x9e:
					bn = b2i(bn1 != bn2) // OP_NUMNOTEQUAL
				case 0x9f:
					bn = b2i(bn1 < bn2) // OP_LESSTHAN
				case 0xa0:
					bn = b2i(bn1 > bn2) // OP_GREATERTHAN
				case 0xa1:
					bn = b2i(bn1 <= bn2) // OP_LESSTHANOREQUAL
				case 0xa2:
					bn = b2i(bn1 >= bn2) // OP_GREATERTHANOREQUAL
				case 0xa3: // OP_MIN
					if bn1 < bn2 {
						bn = bn1
					} else {
						bn = bn2
					}
				case 0xa4: // OP_MAX
					if bn1 > bn2 {
						bn = bn1
					} else {
						bn = bn2
					}
				default:
					panic("invalid opcode")
				}
				if opcode == 0x9d { //OP_NUMEQUALVERIFY
					if bn == 0 {
						return false
					}
				} else {
					stack.pushInt(bn)
				}

			case opcode == 0xa5: //OP_WITHIN
				if stack.size() < 3 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				bn3 := stack.popInt(checkMinVals)
				bn2 := stack.popInt(checkMinVals)
				bn1 := stack.popInt(checkMinVals)
				stack.pushBool(bn2 <= bn1 && bn1 < bn3)

			case opcode == 0xa6: //OP_RIPEMD160
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				rim := ripemd160.New()
				rim.Write(stack.pop()[:])
				stack.push(rim.Sum(nil)[:])

			case opcode == 0xa7: //OP_SHA1
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				sha := sha1.New()
				sha.Write(stack.pop()[:])
				stack.push(sha.Sum(nil)[:])

			case opcode == 0xa8: //OP_SHA256
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				sha := sha256.New()
				sha.Write(stack.pop()[:])
				stack.push(sha.Sum(nil)[:])

			case opcode == 0xa9: //OP_HASH160
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				rim160 := btc.Rimp160AfterSha256(stack.pop())
				stack.push(rim160[:])

			case opcode == 0xaa: //OP_HASH256
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				h := btc.Sha2Sum(stack.pop())
				stack.push(h[:])

			case opcode == 0xab: // OP_CODESEPARATOR
				sta = idx

			case opcode == 0xac || opcode == 0xad: // OP_CHECKSIG || OP_CHECKSIGVERIFY

				if stack.size() < 2 {
					if DBG_ERR {
						fmt.Println("Stack too short for opcode", opcode)
					}
					return false
				}
				var ok bool
				pk := stack.pop()
				si := stack.pop()

				// BIP-0066
				if !CheckSignatureEncoding(si, ver_flags) {
					if DBG_ERR {
						fmt.Println("Invalid Signature Encoding A")
					}
					return false
				}

				if len(si) > 0 {
					sh := tx.SignatureHash(delSig(p[sta:], si), inp, int32(si[len(si)-1]))
					ok = btc.EcdsaVerify(pk, si, sh)
				}
				if !ok && DBG_ERR {
					if DBG_ERR {
						fmt.Println("EcdsaVerify fail 1")
					}
				}

				if DBG_SCR {
					fmt.Println("ver:", ok)
				}
				if opcode == 0xad {
					if !ok { // OP_CHECKSIGVERIFY
						return false
					}
				} else { // OP_CHECKSIG
					stack.pushBool(ok)
				}

			case opcode == 0xae || opcode == 0xaf: //OP_CHECKMULTISIG || OP_CHECKMULTISIGVERIFY
				//fmt.Println("OP_CHECKMULTISIG ...")
				//stack.print()
				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("OP_CHECKMULTISIG: Stack too short A")
					}
					return false
				}
				i := 1
				keyscnt := stack.topInt(-i, checkMinVals)
				if keyscnt < 0 || keyscnt > 20 {
					fmt.Println("OP_CHECKMULTISIG: Wrong number of keys")
					return false
				}
				opcnt += int(keyscnt)
				if opcnt > 201 {
					if DBG_ERR {
						fmt.Println("evalScript: too many opcodes B")
					}
					return false
				}
				i++
				ikey := i
				i += int(keyscnt)
				if stack.size() < i {
					if DBG_ERR {
						fmt.Println("OP_CHECKMULTISIG: Stack too short B")
					}
					return false
				}
				sigscnt := stack.topInt(-i, checkMinVals)
				if sigscnt < 0 || sigscnt > keyscnt {
					fmt.Println("OP_CHECKMULTISIG: sigscnt error")
					return false
				}
				i++
				isig := i
				i += int(sigscnt)
				if stack.size() < i {
					if DBG_ERR {
						fmt.Println("OP_CHECKMULTISIG: Stack too short C")
					}
					return false
				}

				xxx := p[sta:]
				for k := 0; k < int(sigscnt); k++ {
					xxx = delSig(xxx, stack.top(-isig-k))
				}

				success := true
				for sigscnt > 0 {
					pk := stack.top(-ikey)
					si := stack.top(-isig)

					// BIP-0066
					if !CheckSignatureEncoding(si, ver_flags) {
						if DBG_ERR {
							fmt.Println("Invalid Signature Encoding B")
						}
						return false
					}

					if len(si) > 0 {
						sh := tx.SignatureHash(xxx, inp, int32(si[len(si)-1]))
						if btc.EcdsaVerify(pk, si, sh) {
							isig++
							sigscnt--
						}
					}

					ikey++
					keyscnt--

					// If there are more signatures left than keys left,
					// then too many signatures have failed
					if sigscnt > keyscnt {
						success = false
						break
					}
				}
				for i > 0 {
					i--
					stack.pop()
				}
				if opcode == 0xaf {
					if !success { // OP_CHECKMULTISIGVERIFY
						return false
					}
				} else {
					stack.pushBool(success)
				}

			case opcode >= 0xb1: //OP_NOP2 or OP_CHECKLOCKTIMEVERIFY
				if DBG_SCR {
					println("OP_NOP2...")
				}

				if (ver_flags & VER_CLTV) == 0 {
					break // Just do NOP2
				}

				if DBG_SCR {
					println("OP_CHECKLOCKTIMEVERIFY...")
				}

				if stack.size() < 1 {
					if DBG_ERR {
						fmt.Println("OP_CHECKLOCKTIMEVERIFY: Stack too short")
					}
					return false
				}

				d := stack.top(-1)
				if len(d) > 5 {
					if DBG_ERR {
						fmt.Println("OP_CHECKLOCKTIMEVERIFY: locktime field too long", len(d))
					}
					return false
				}

				if DBG_SCR {
					fmt.Println("val from stack", hex.EncodeToString(d))
				}

				locktime := bts2int_ext(d, 5, checkMinVals)
				if locktime < 0 {
					if DBG_ERR {
						fmt.Println("OP_CHECKLOCKTIMEVERIFY: negative locktime")
					}
					return false
				}

				if !((tx.Lock_time < LOCKTIME_THRESHOLD && locktime < LOCKTIME_THRESHOLD) ||
					(tx.Lock_time >= LOCKTIME_THRESHOLD && locktime >= LOCKTIME_THRESHOLD)) {
					if DBG_ERR {
						fmt.Println("OP_CHECKLOCKTIMEVERIFY: broken lock value")
					}
					return false
				}

				if DBG_SCR {
					println("locktime > int64(tx.Lock_time)", locktime, int64(tx.Lock_time))
					println(" ... seq", len(tx.TxIn), inp, tx.TxIn[inp].Sequence)
				}

				// Actually compare the specified lock time with the transaction.
				if locktime > int64(tx.Lock_time) {
					if DBG_ERR {
						fmt.Println("OP_CHECKLOCKTIMEVERIFY: Locktime requirement not satisfied")
					}
					return false
				}

				if tx.TxIn[inp].Sequence == 0xffffffff {
					if DBG_ERR {
						fmt.Println("OP_CHECKLOCKTIMEVERIFY: TxIn final")
					}
					return false
				}

				// OP_CHECKLOCKTIMEVERIFY passed successfully

			case opcode >= 0xb0 || opcode >= 0xb2 && opcode <= 0xb9: //OP_NOP1 || OP_NOP3..OP_NOP10
				// just do nothing

			default:
				if DBG_ERR {
					fmt.Printf("Unhandled opcode 0x%02x - a handler must be implemented\n", opcode)
					stack.print()
					fmt.Println("Rest of the script:", hex.EncodeToString(p[idx:]))
				}
				return false
			}
		}

		if DBG_SCR {
			fmt.Printf("Finished Executing opcode 0x%02x\n", opcode)
			stack.print()
		}
		if stack.size()+altstack.size() > 1000 {
			if DBG_ERR {
				fmt.Println("Stack too big")
			}
			return false
		}
	}

	if DBG_SCR {
		fmt.Println("END OF SCRIPT")
		stack.print()
	}

	if exestack.size() > 0 {
		if DBG_ERR {
			fmt.Println("Unfinished if..")
		}
		return false
	}

	return true
}
Exemplo n.º 14
0
// load the content of the "balance/" folder
func load_balance(showbalance bool) {
	var unknownInputs, multisigInputs int
	f, e := os.Open("balance/unspent.txt")
	if e != nil {
		println(e.Error())
		return
	}
	rd := bufio.NewReader(f)
	for {
		l, _, e := rd.ReadLine()
		if len(l) == 0 && e != nil {
			break
		}
		if l[64] == '-' {
			txid := btc.NewUint256FromString(string(l[:64]))
			rst := strings.SplitN(string(l[65:]), " ", 2)
			vout, _ := strconv.ParseUint(rst[0], 10, 32)
			uns := new(btc.TxPrevOut)
			copy(uns.Hash[:], txid.Hash[:])
			uns.Vout = uint32(vout)
			lab := ""
			if len(rst) > 1 {
				lab = rst[1]
			}

			str := string(l)
			if sti := strings.Index(str, "_StealthC:"); sti != -1 {
				c, e := hex.DecodeString(str[sti+10 : sti+10+64])
				if e != nil {
					fmt.Println("ERROR at stealth", txid.String(), vout, e.Error())
				} else {
					// add a new key to the wallet
					sec := btc.DeriveNextPrivate(first_seed[:], c)
					is_stealth[len(priv_keys)] = true
					priv_keys = append(priv_keys, sec)
					labels = append(labels, lab)
					pub_key := btc.PublicFromPrivate(sec, true)
					publ_addrs = append(publ_addrs, btc.NewAddrFromPubkey(pub_key, AddrVerPubkey()))
					compressed_key = append(compressed_key, true) // stealth keys are always compressed
				}
			}

			if _, ok := loadedTxs[txid.Hash]; !ok {
				tf, _ := os.Open("balance/" + txid.String() + ".tx")
				if tf != nil {
					siz, _ := tf.Seek(0, os.SEEK_END)
					tf.Seek(0, os.SEEK_SET)
					buf := make([]byte, siz)
					tf.Read(buf)
					tf.Close()
					th := btc.Sha2Sum(buf)
					if bytes.Equal(th[:], txid.Hash[:]) {
						tx, _ := btc.NewTx(buf)
						if tx != nil {
							loadedTxs[txid.Hash] = tx
						} else {
							println("transaction is corrupt:", txid.String())
						}
					} else {
						println("transaction file is corrupt:", txid.String())
						os.Exit(1)
					}
				} else {
					println("transaction file not found:", txid.String())
					os.Exit(1)
				}
			}

			// Sum up all the balance and check if we have private key for this input
			uo := UO(uns)

			add_it := true

			if !btc.IsP2SH(uo.Pk_script) {
				fnd := false
				for j := range publ_addrs {
					if publ_addrs[j].Owns(uo.Pk_script) {
						fnd = true
						break
					}
				}

				if !fnd {
					if *onlvalid {
						add_it = false
					}
					if showbalance {
						unknownInputs++
						if *verbose {
							ss := uns.String()
							ss = ss[:8] + "..." + ss[len(ss)-12:]
							fmt.Println(ss, "does not belong to your wallet (cannot sign it)")
						}
					}
				}
			} else {
				if *onlvalid {
					add_it = false
				}
				if *verbose {
					ss := uns.String()
					ss = ss[:8] + "..." + ss[len(ss)-12:]
					fmt.Println(ss, "belongs to a multisig address")
				}
				multisigInputs++
			}

			if add_it {
				unspentOuts = append(unspentOuts, uns)
				unspentOutsLabel = append(unspentOutsLabel, lab)
				totBtc += UO(uns).Value
			}
		}
	}
	f.Close()
	fmt.Printf("You have %.8f BTC in %d unspent outputs. %d inputs are multisig type\n",
		float64(totBtc)/1e8, len(unspentOuts), multisigInputs)
	if showbalance {
		if unknownInputs > 0 {
			fmt.Printf("WARNING: Some inputs (%d) cannot be spent with this password (-v to print them)\n", unknownInputs)
		}
	}
}
Exemplo n.º 15
0
func load_others() {
	f, e := os.Open(RawKeysFilename)
	if e == nil {
		defer f.Close()
		td := bufio.NewReader(f)
		for {
			li, _, _ := td.ReadLine()
			if li == nil {
				break
			}
			if len(li) == 0 {
				continue
			}
			pk := strings.SplitN(strings.Trim(string(li), " "), " ", 2)
			if pk[0][0] == '#' {
				continue // Just a comment-line
			}

			pkb := btc.Decodeb58(pk[0])

			if pkb == nil {
				println("Decodeb58 failed:", pk[0])
				continue
			}

			if len(pkb) < 6 {
				println("Syntax error in the raw keys file:", pk[0])
				continue
			}

			if len(pkb) != 37 && len(pkb) != 38 {
				println(pk[0][:6], "has wrong key", len(pkb))
				println(hex.EncodeToString(pkb))
				continue
			}

			if pkb[0] != AddrVerSecret() {
				println(pk[0][:6], "has version", pkb[0], "while we expect", AddrVerSecret())
				fmt.Println("You may want to play with -t or -ltc switch")
				continue
			}

			var sh [32]byte
			var compr bool

			if len(pkb) == 37 {
				// old/uncompressed key
				sh = btc.Sha2Sum(pkb[0:33])
				if !bytes.Equal(sh[:4], pkb[33:37]) {
					println(pk[0][:6], "checksum error")
					continue
				}
				compr = false
			} else {
				if pkb[33] != 1 {
					println(pk[0][:6], "a key of length 38 bytes must be compressed")
					continue
				}

				sh = btc.Sha2Sum(pkb[0:34])
				if !bytes.Equal(sh[:4], pkb[34:38]) {
					println(pk[0][:6], "checksum error")
					continue
				}
				compr = true
			}

			key := pkb[1:33]
			pub := btc.PublicFromPrivate(key, compr)
			if pub == nil {
				println("PublicFromPrivate failed")
				os.Exit(1)
			}

			priv_keys = append(priv_keys, key)
			compressed_key = append(compressed_key, compr)
			publ_addrs = append(publ_addrs, btc.NewAddrFromPubkey(pub, AddrVerPubkey()))
			if len(pk) > 1 {
				labels = append(labels, pk[1])
			} else {
				labels = append(labels, fmt.Sprint("Other ", len(priv_keys)))
			}
		}
		if *verbose {
			fmt.Println(len(priv_keys), "keys imported from", RawKeysFilename)
		}
	} else {
		if *verbose {
			fmt.Println("You can also have some dumped (b58 encoded) priv keys in file", RawKeysFilename)
		}
	}
}