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[:]) }
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) }
// 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[:]) }
// 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[:]) }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
// 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) } } }
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) } } }